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 to SSL endpoints.
As explained in the introduction article, we will cover some of the problems for our simple ASP.NET 4.6 application which makes an Http Web Request to an SSL endpoint. Here is the simple code:
protected void Page_Load(object sender, EventArgs e)
WebRequest wreq = WebRequest.Create("https://iis85.buggybits.com/");
WebResponse wres = wreq.GetResponse();
Stream str = wres.GetResponseStream();
StreamReader strr = new StreamReader(str);
string realresp = strr.ReadToEnd();
As seen in the code above the ASP.NET application acts as a client and makes an HTTP call to https://iis85.buggybits.com/. That 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 disable the custom errors locally and access the application from local server we get 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.
Note 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 test website intiates a TCP connection to the remote server. Opening the connection requires a three-way handshake should take place and then, since this connection attempt request is made over SSL, an SSL Handshake should take place. It is possible that it is either failing at TCP handshake or SSL handshake. It is possible that 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 is that the ASP.NET client should contact the remote server without receiving a certificate error. Unlike the "human clients", an ASP.NET client cannot say "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 the site's security certificate 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 and 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 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 now this time we successfully browse https://iis85.buggybits.com/ and the page opens just fine without a certificate warning.
However our application still fails with the same error message and we will cover the second scenario in our next post.