CUPS/IPP over HTTPS via CF/Gorouter - TLS handshake error - cloud-foundry

I want to print PostScripts via CUPS/HTTPS on Cloud Foundry.
It's working when I'm using HTTP but fails for HTTPS with gorouter's log:
http: TLS handshake error from ...
My cipher_suites:
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
I tried to set router.logging_level to debug (default is info) but it changes nothing...
Is there any chance to get more information?
What is the most detailed log level for gorouter?

I solved my problem.
In my case mutual TLS was enabled on gourouter:
By default, Gorouter requests but does not require client certificates in TLS handshakes.
https://docs.cloudfoundry.org/adminguide/securing-traffic.html#gorouter_mutual_auth
Checking if mTLS is enabled
1. Widows SCHANNEL event logging
Add a registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
EventLogging REG_DWORD = 3
https://blogs.technet.microsoft.com/kevinjustin/2017/11/08/schannel-event-logging/
Now you should find event logs that server asks for client certificate but it can't be found.
2. curl
Look at the bold lines:
curl -I -v -H "Connection: close" https://your-app.cloud
About to connect() to your-app.cloud port 443 (#0)
Connected to your-app.cloud port 443 (#0)
Initializing NSS with certpath: sql:/etc/pki/nssdb
CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none
NSS: client certificate not found (nickname not specified)
SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
3. openssl
Look at the bold lines:
openssl s_client -connect your-app.cloud:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
...
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read server session ticket A
SSL_connect:SSLv3 read finished A
Disable Gorouter mTLS
Change Gorouter properties using CF deployment manifest:
- name: router
- name: gorouter
release: routing
properties:
router:
forwarded_client_cert: always_forward
client_cert_validation: none
Now you can check if mTLS is enabled again.
Note that these settings didn't for the routing version 0.164.0 but for 0.178.0 it works as expected.

Related

MITM proxy, TLS 1.2 Certificate verification failed

Trying to create my own simple MITM-proxy for the specific app which using TLS 1.2 protocol and connecting to several IP addresses, however got in stuck with the error in the app log "Certificate verify failed". How to solve this problem?
The app using about the following code to check the cert:
X509* cert = SSL_get_peer_certificate( ssl );
X509_STORE_CTX * xCtx = X509_STORE_CTX_new();
X509_STORE_CTX_init( xCtx, (X509_STORE*)Store, cert, NULL );
int res = X509_verify_cert( xCtx );
if( !res ) { /*Certificate verify failed*/ };
I did the following steps to achieve the result:
Created CA root key and self-signed certificate according to this manual. It is a bit outdated, so i have made some changes like md5 to sha256, also I didn't use pass phrase, used different key size and other minor changes.
Created proxy key and certificate using the above Root CA to sign it.
Both certificates have been added to the Local Computer Certificates in Personal and Trusted Root Certification Authorities (not sure if this was necessary). Btw, I'm using Windows 10.
Wrote a simple proxy server using sample code from here. Cert.pem and Key.pem took from the second step.
Changed all IP addresses in the app to 127.0.0.1:443 to see if TLS connection established successfully and we can receive first message with an Application Data.
I believe that connection established properly, because WireShark shows common sequence for establishing a TLS connection: Client/Server hello, Certificate, Client key exchange, two encrypted handshake messages. Moreover, using OpenSSL for testing connection:
openssl s_client -connect localhost:443
allow me to write some message and later successfully receive it using SSL_Read() in proxy server. However, there are some errors:
verify error:num=20:unable to get local issuer certificate
verify return:1
verify error:num=21:unable to verify the first certificate
verify return:1
Verify return code: 21 (unable to verify the first certificate)
Using OpenSSL client to directly connect to the original IP addresses give the same errors, but application works great.
Also the output:
openssl verify -CAfile "signing-ca-1.crt" "cert.crt"
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
e:\MyProg\SSL_serv\Debug\cert.crt: OK
It seems that I missed something important. Could you please tell me how to solve this problem with cert?
One of the very purposes of having certificates, along with certificate authorities, is to prevent MITM. The app you are trying trick does the proper thing and checks the certificate. And it doesn't like your's. Its really that simple.
Is it possible to circumvent it and run MITM on an app anyway? Absolutely! Is it going to be easy? Probably not. What you need to do is to patch the app and remove this certificate check.

GNU libmicrohttpd with client TLS allows empty certificate

I am using GNU libmicrohttpd to establish HTTPS server. My requirement is that the server and the client both authenticate during the TLS handshake however what I observe is that even if the client sends empty certificate the connection is accepted.
in wireshark I see that the server requests certificate and the client sends certificate with len 0. How to make the microhttpd to not accept that case - the certificate must always be verified with the provided CA pem?
if(!(server_handle = MHD_start_daemon(flags, port, NULL, NULL,
&mhttpd_layer::access_handler_callback, callback_data,
// now, continue with the options
MHD_OPTION_NOTIFY_COMPLETED, &mhttpd_layer::request_completed_callback, l_callback_data,
MHD_OPTION_SOCK_ADDR, (sockaddr*) &(it->addr),
MHD_OPTION_CONNECTION_TIMEOUT, it->conn_timeout,
MHD_OPTION_CONNECTION_LIMIT, it->conn_limit,
MHD_OPTION_PER_IP_CONNECTION_LIMIT, it->per_ip_conn_limit,
// HTTPS certificate options
MHD_OPTION_HTTPS_MEM_KEY, it->https_key_buff.data(),
MHD_OPTION_HTTPS_MEM_CERT, it->https_cert_buff.data(),
MHD_OPTION_HTTPS_MEM_TRUST, it->https_turst_ca_buff.data(),
MHD_OPTION_END)))
Maybe I should manually on the access callback retrieve the certificate as described by their tutorial (https://www.gnu.org/software/libmicrohttpd/tutorial.html#Adding-a-layer-of-security) ? In this case why do I provide the CA - this doesn't seem the proper way to me?

openssl api to disable authentication

Have a simple server and client that uses openssl. Application program is in C++ and uses openssl-1.1.0g source code that I built myself. The simple case where I supply client and server certificates and private keys is working fine. Handshake happens fine and data transfer works great too. Now I have two more requirements:
Need to disable client authentication on server. client will have a CA certificate but no private key. Client will do server auth.
Don't know how to tell openssl api not to ask for client certificate
[Update] This is fixed. In the conf file, under the client section tried using keyword VerifyCAFile for CA certificate and removed the PrivateKey. Got handshake success without any code change.
Disable client and server auth. Both sides doesn't have certificate or private keys.
Tried using anon section in the conf file which doesn't have the certificate or the key specified. Also set the cipher string is aNULL in this section of the conf file. aNULL is the list of all anonymous ciphers according the page here:
https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
But this doesn't work.
Here is the setup -
Server:
SSL_CTX_new(TLS_server_method()) - create server ctx
CONF_modules_load_file - load conf file
SSL_CTX_config - get section for server
BIO_new_socket((int)socket, BIO_CLOSE) - create socket BIO
SSL_new(ctx) - create ssl
SSL_set_bio - set bio in ssl
SSL_set_accept_state(_ssl); - set accept for server
SSL_do_handshake - do handshake
Client:
SSL_CTX_new(TLS_client_method()) - create server ctx
CONF_modules_load_file - load conf file
SSL_CTX_config - get section for client
BIO_new_socket((int)socket, BIO_CLOSE) - create socket BIO
SSL_new(ctx) - create ssl
SSL_set_bio - set bio in ssl
SSL_set_connect_state(ssl) - set connect for client
SSL_do_handshake - do handshake
Conf file:
testApp = test_sect
[test_sect]
# list of configuration modules
ssl_conf = ssl_sect
[ssl_sect]
server = server_section
client = client_section
anon = anon_section
[server_section]
CipherString = DEFAULT
Certificate = <path to server.cer>
PrivateKey = <path to server.key>
[client_section]
CipherString = DEFAULT
Certificate = <path to client.cer>
PrivateKey = <path to client.key>
[anon_section]
CipherString = aNULL
On the server, you want something like:
SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
I thought this was the default, however.

uWebSockets (C++): secure wss server

I am using uWebSockets in C++ to host a WebSocket server. However, I need it to be a secure wss server instead of simply a ws server.
I have tried this code:
uS::TLS::Context tls = uS::TLS::createContext ("./cert.perm", "./key.perm", "passphrase");
if (h.listen (9002, tls)) {
cout << "Game server listening on port 9002" << endl;
h.run();
}
I am using this shell command to generate the certificate and key:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 30
I then tried connecting to my remote server using wss://address instead of the usual ws://address, however, it cannot connect.
Any ideas why? Thanks
UPDATE #1
The tls variable seems to be actually NULL, so it looks like the certificate part isn't working.
UPDATE #2
I got the file extensions wrong in the code, they're meant to be pem instead of perm. However, the server will now not establish a connection on both wss and ws.
UPDATE #3
After fixing the issue mentioned above, the tls variable is now 1 instead of 0 (which I assumed was NULL).
If you are using a web browser ws-client to connect to wss://address, try checking if the browser is the problem. It happened to me that I had created my own certificates, but the browser blocks the connection as they are not certified by any CA.
Enter in your browser something like: "https://address", and add a security exception for your "address".
I know you can use uWebSockets for SSL/TLS, however... I would consider separating the TLS/SSL concern from the main application.
Separating the TLS/SSL layer from the app allows you to update the TLS/SSL without recompiling the application as well as simplifies the codebase.
I would recommend using a TLS/SSL proxy or tunnel while having the app bind locally to the loopback address or to a unix socket.

Asio certificate verify failed

I downloaded Asio Standalone and would like to run the ssl example (client and server) provided with the Asio source code on my local computer. I managed to get the library running. The code compiles without errors. But I think the client has a problem reading the server certificate from the certificate store on my debian system in /etc/ssl/certs. Because I get the following error:
Handshake failed: certificate verify failed
What I did so far:
I created the server certificate and key as descripted in my last post and added the crt file to /etc/ssl/certs
I set the verify_path on client side as following:
asio::ssl::context ctx(asio::ssl::context::tlsv11);
ctx.set_default_verify_paths();
I start the server on port 8877 on my local computer
I start the client with host IP 127.0.0.1 and port 8877
then I get the error as mentioned above.
Am I right that asio finds my certificate? (because otherwise I would expect an error 'file_not_found' or something like that) Why is the certificate not valid? Because I self-signed it or because I don't use 127.0.0.1 as a 'Common Name' in the certificate ? But I guess the client should accept a self-signed certificate in it's local certificate store...