I am using the great Charles Web Proxy do make a reverse proxy and debug an exchange between my client and a secure server.I accepted the Charles certificate as a trusted authority and it works generally very well when using it in Proxy Mode, the problem is when I try to make a reverse proxy.
I am using an external library over which I have no control that uses an HttpUrlConnection and lets me specify the URL. Following the Charles documentation, I set my URL to https://mybox.test.com:100 (note that I used a hostname, added to my host file, instead of localhost in the hope that I can have a valid certificate).
The problem is that as part of the Https validation, HttpUrlConnection verifies the host name (mybox.test.com since it is pointing to my reverse proxy) against the one in the certificate (the one of the secure site I am connecting to). Obviously that does not match and causes a
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching localhost found.
I realize that Charles cannot generate a certificate for mybox.test.com, since it only listens to a particular port and has no knowledge of the URL used in the HttpUrlConnection. I do not see how it could generate a correct certificate that would be accepted.
My question is: is there a better way to use a reverse proxy with Https or do I need to disable the host name and certificate validation ?
Related
Is there a way to specify the connection method when using a proxy?
I'm using the below code which sends an HTTP CONNECT. That is not supported by my load balancer. A GET request would terminate the TLS connection between the proxy and the website. The CONNECT method creates a TLS connection end to end between the end user and website. Essentially I need to inspect the traffic at the proxy.
HttpHost proxy = new HttpHost(proxyHost, proxyPort);
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
clientBuilder
.setConnectionManager(connectionManager)
.setProxy(proxy)
.setDefaultRequestConfig(config);
Below is what the connection looks like:
Hypertext Transfer Protocol
CONNECT xyz.com:443 HTTP/1.1\r\n
Host: xyz.com\r\n
User-Agent: Apache-HttpClient/4.5.13 (Java/19.0.1)\r\n
\r\n
For HTTPS communications through a proxy, the client will use a CONNECT request to create a connection through the proxy to the remote trusted site.
With HTTPS, the client will only communicate with a server that it trusts. The trust usually requires that the server presents an X.509 certificate that is signed by a trusted authority (not self-signed), not expired, and has a subject that matches the site the client is trying to reach.
When communicating with a proxy, the proxy is typically unable to match that criteria. However, there are proxies that can match the above criteria by generating a new cert on the fly that has a matching subject to that expected by the client.
In that case, once the client has established a TLS connection with the proxy, the proxy can then decrypt the payload of the HTTPS traffic.
For the proxy to create a certificate trusted by the client, it must be signed by a CA (certificate authority) that is trusted by the client. Now, by default, the client will not trust the cert since it will not recognize the CA. However, you may modify the client by placing a cert for the CA on the client. Once the client trusts the CA, it will trust all of the certs generated by the proxy.
That being said, here's configuration for an HTTPS proxy (written by Cisco) that provides instructions for just that:
https://www.cisco.com/c/en/us/support/docs/unified-communications/jabber/212044-Configure-Charles-Proxy-to-Capture-HTTPS.html
The configuration action you'll need for Apache (if Apache supports this) will be similar - you'll need to get a cert from the Apache proxy to install on your client.
I'm currently searching the web for similar proxies. I'm essentially looking for a key word that describes this technique of enabling your HTTPS proxy to do man-in-the-middle attacks with a dynamically generated cert matching the request. If I find the terms, I'll update the post.
EDIT: Update for squid
I found an article about configuring squid for inspecting HTTPS traffic: https://scubarda.com/2020/03/23/configure-squid-proxy-for-ssl-tls-inspection-https-interception/
In the article, the author indicates that you would have to install the X.509 Cyber Saiyan certificate in your browser (client's) certificate/authorities section (but this is just for this specific configuration).
Some good keywords to search for now are HTTPS inspection...
If this is a temporary debug solution, you can use one of the Man In The Middle (MITM) proxies that are designed just for this:
Burp
Charles
Zap
Once installed somewhere, you'll just need to import the proxy CA cert into the server making the connections (each of the above proxies has a how-to guide for this), and set the proxy address to the MITM.
I have created a Public Cert for my server with abc.com and imported it into my clients trustore, But I'm using cde.com to invoke my application which resides on the server. cde.com resolves to abc.com with auto domain resolution (with a DNS). So my question is which hostname I should use for HostName verification. I think as per the specification [1] I should use cde.com to do the verification. Is my understanding correct?
I'm trying to write a utility class (as I haven't been able to find one), that allows me the check that an HTTPS connection is okay. When I curl the site I get the error
curl: (60) SSL certificate problem: Invalid certificate chain
When I access the site on Chrome, I get
The identity of this website has not been verified. Server's certificate does not match the URL. The server could not prove that is is *.domain.com; its security certificate is from *.another.com.
This is exactly what I'd like to test for in Java but I haven't been able to do so. How can I test that the SSL connection is okay?
One easy way could be to to do a GET to a given URL. If the connection is OK must return an HTTP 200 OK response code, else the Java request library e.g Java's HttpsUrlConnection, Apache's HttpCLient, Ning's HttpClient should return the exception.
It is very rudimentary but depends on your needs could serve.
I got a url with https, which has a common certification (which means this url could be visited from the browser and has a https security badge). Now I want to get the info from this url using HttpsUrlConnection, how can I do a certification check.
I am a SSL beginner, so I did some searching. And I got this, which is a self-signed check demo.
I'm wondering if the common https link should be checked like this. Does HttpsUrlConnection do a check, I found on the Android Developers:
If an application wants to trust Certificate Authority (CA) certificates that are not part of the system, it should specify its own X509TrustManager via a SSLSocketFactory set on the HttpsURLConnection.
Does this means I don't need to check the server certificate if I can browse it from a web browser? Can I do a validation like the web browser does? And where can I find the trust store file, can I just make a default key store? Or anybody can tell me how to implement a TrustManager(I do want a validation, not a trust manager that trust anything).
maybe this information will help you HttpComponents
We have configure a Big F5 load balancer virtual server for a particular IP address which redirects incoming https requests to several Windows servers where there is functionality to generate responses.
I am using SoapUI to test access to these windows servers via the IP address of virtual server in the Big F5.
Using Server and Client certificates generated by the organization where the we have also this set up and sending requests via SoapUI I get the predicted responses back.
The business requirements call for Commercially signed certificates by Thawte.
We created a Certifcate Servcice Request (CSR) to generate a Server certificate and its private key and then we had it signed by Thawte, and also requested a Client Commercially signed certificate from Thawte.
We loaded both certificates in SoapUI client and the Big F5 load balancer but we attempting to test the requests we get the "javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake" error.
My questions are:
How can I monitor where exactly the 2 way SSL handshake is terminated
The actual reason what exactly is happening?.. why using commercially signed certificates this does not work now?
Any replies are welcome. Thanks.
However when we swithch Serverto commercially signed by Thawte
This is possibly due to the Java security feature. If so you need to edit the soapui-4.x.x.vmoptions file located at soapui-4.x.x\bin folder and add -Dsun.security.ssl.allowUnsafeRenegotiation=true to the end.
You may also need to export the certificate as a pfx file and set it up in soapUI preference page. For details you can check http://geekswithblogs.net/gvdmaaden/archive/2011/02/24/how-to-configure-soapui-with-client-certificate-authentication.aspx and http://forums.devarticles.com/java-development-38/javax-net-ssl-sslhandshakeexception-received-fatal-alert-handshake-failure-11809.html .
The client is a SoapUI request that has not changed except a different client certificate
That suggests that the server doesn't trust the new client certificate, which in turn implies that the client certificate wasn't even sent because it wasn't signed by one of the server's trusted signers. Closing the connection is the server's only real option in this circumstance, as there isn't an SSL alert for it.
Make sure you have address translation on and the SNAt set to Auto Map for your VIP