This is the first part of a series of articles about troubleshooting TLS / SSL communications problem when you make Http Web Request or WCF queries from your ASP.NET applications (or any web application such as a web api, or WCF) to SSL endpoints.
Here is a simple code snippet which makes an Http call to an endpoint. Notice that the request is made to an SSL endpoint over HTTPS:
As seen in the code snippet above, the ASP.NET application acts as a client and makes an HTTP call to https://iis85.buggybits.com/. Let's assume that the target application is running on another server.
When we run our application we get the following error message:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
If we look at the details of the error message (e.g.: by disabling the custom errors), we see that we are getting the following details:
Server Error in '/' Application. -------------------------------------------------------------------------------- An existing connection was forcibly closed by the remote host Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. ... [SocketException (0x2746): An existing connection was forcibly closed by the remote host] System.Net.Sockets.Socket.Receive(Byte buffer, Int32 offset, Int32 size, SocketFlags socketFlags) +139 System.Net.Sockets.NetworkStream.Read(Byte buffer, Int32 offset, Int32 size) +146 ... [IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.] System.Net.Sockets.NetworkStream.Read(Byte buffer, Int32 offset, Int32 size) +742
This generic error message tells us that the TCP connection was closed and that the closure was not done a friendly way at all. The stack trace itself is not very useful here as we only see that we are getting that exception while we receive the information from the socket but there is no clue what it is that the ASP.NET application is receiving so no clue about the problem.
Remember that the ASP.NET application acts as a client here and sends an HTTP request to https://iis85.buggybits.com/ running on a remote machine. To reach the remote site, the server where our application runs initiates a TCP connection to the remote server. Opening the connection requires a three-way handshake and then, since this connection should be open over SSL, an SSL Handshake should take place.
It is possible that either the TCP handshake or SSL handshake could be failing. For some reason, the certificate could be invalid or underlying SSL handshake could fail.
To analyze the handshake we can get a network trace and analyze it but in some scenarios it is very useful to run a "browser test" first:
The rule of thumb is that the ASP.NET application (which is our client in this scenario) should be able to communicate with the remote server without getting a certificate error. Unlike the "human clients", an ASP.NET client cannot tell "OK, I understand the certificate is not valid for my request but I'll take the risk and continue to the website" so if it detects a problem with the certificate then it will fail (unless you explicitly tell the HTTP web request to ignore the certificate errors, which I do not suggest at all).
If we open a browser on the machine where the ASP.NET application runs and browse the URL we get the following message:
If you click "continue to the web site" and check the certificate details it clearly tells us that there is a name mismatch:
And if you click "view certificate" you will see that the certificate is an SAN (server alternate name) certificate obtained for www.buggybit.com and the SAN DNS entries do not contain our URL, iis85.buggybits.com:
So, the certificate is not valid. To fix this problem we should go to the IIS machine where iis85.buggybits.com works and configure the web site with a correct certificate. After that we can run our browser test again and this time we successfully browse https://iis85.buggybits.com/ and the page opens just fine without a certificate warning.
A "browser test" is the first action to take to test the connectivity but there are scenarios where the test may not be useful, or, even deceptive. We will see the reason for that and a more complex troubleshooting scenario in our next post.