4

We have an internal application that makes XML calls out to our vendor sites. For PCI compliance and security reasons, they are starting to disable everything except TLS 1.1 and TLS 1.2. They have set up a test site with this new requirement for us to test against.

Our application (C#, Windows Forms app, .NET 4.5) can connect to their current site just fine. When I try to make a call to their new test site, it fails on the GetRequestStream() call with "The underlying connection was closed: An unexpected error occurred on a send."

If I update the app and set: System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12

Then it gets by the GetRequestStream() and fails on the GetResponse() call with "The underlying connection was closed: The connection was closed unexpectedly."

I have tried a bunch of stuff, none of which has worked. I am setting the UserAgent, I tried setting KeepAlive = false, ... If I go to the vendors URL in a browser, I can get to it fine. I am just having issues with my C# app

Any thoughts? I obviously dont have access to their server. Is there a setting someone on my machine I need to change?

kirtan
  • 289
  • 4
  • 13
jrhoads23
  • 109
  • 1
  • 8
  • Maybe they're using a self-signed certificate on the test server? – Gusman Feb 26 '16 at 17:44
  • How can I tell? Visually comparing the cert from both sites they appear identical (except for the domain name and stuff) – jrhoads23 Feb 26 '16 at 17:50
  • 1
    Well, just go to the site and check the certificate info on the browser, if it's self signed it will be stated. – Gusman Feb 26 '16 at 17:51
  • @jrhoads23: To rule out any SSL certificate problems, go to [https://www.digicert.com/help/](https://www.digicert.com/help/) and type in your test server's URL. It will try to validate the certificate and show you the results. – Gabriel S. Feb 28 '16 at 15:51
  • Very cool tool. I just tried it and everything comes back valid – jrhoads23 Feb 28 '16 at 15:58
  • So in all probability this means that there are no problems with the server's SSL certificate, you can rule this out as the potential cause. – Gabriel S. Feb 28 '16 at 16:03

2 Answers2

0

I think that it is likely that your request is failing during the TLS negotiation stage. I have had similar problems myself and it usually comes down to having to use a network protocol analyzer (such as wireshark) to trace the communication between the client and server and to determine where the messaging has stopped. If TLS negotiation fails, the server will terminate the connection and you will get errors similar to what you got above.

  • Ok. I have never used Wireshark so I will download it and see what I find. What did you end up doing to fix your similar issues? – jrhoads23 Feb 26 '16 at 18:51
  • @jrhoads23: Alternatively, you could try [Fiddler](http://www.telerik.com/fiddler), which is aimed at inspecting HTTP(S) communications and is easier to use and understand than Wireshark. Although you may still need Wireshark to inspect in more details the lower-level TCP/SSL errors. – Gabriel S. Feb 28 '16 at 13:37
  • I have downloaded Fiddler and Wireshark. Fiddler didnt seem to tell me much. I was able to capture and isolate the packets in Wireshark but I am not sure how to tell where the problem is coming – jrhoads23 Feb 28 '16 at 15:52
  • You can take a look at [this](http://stackoverflow.com/questions/1470634/get-http-requests-and-responses-made-using-httpwebrequest-httpwebresponse-to-sho) thread for some tips on how to use Fiddler with .NET applications. – Gabriel S. Feb 28 '16 at 16:01
0

It may be possible that the test server does not have a proper SSL certificate. You can find out in .NET if there are any SSL validation errors using the ServerCertificateValidationCallback. I suggest to ignore the validation errors when in Debug mode, like this:

#if DEBUG
ServicePointManager.ServerCertificateValidationCallback += ValidationCallback; 
#endif

var webRequest = HttpWebRequest.Create("https://your.url");
...

#if DEBUG
bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
#endif

This way you knowingly ignore any SSL certificate issues while testing (in Debug mode), but you let the verification mechanism work as usual in production (Release mode). By the way, you can check the sslPolicyErrors parameter to see exactly if and what caused the validation failure.

UPDATE: The author of the question confirmed that the SSL certificate is valid, so my answer doesn't help directly with the error he's receiving.

Community
  • 1
  • 1
Gabriel S.
  • 1,347
  • 11
  • 31
  • Thanks for the suggestion. I put this code in place and the ValidationCallback function gets called on the GetRequestStream() call. At that point the sslPolicyErrors is None (and it doesnt throw an exception there). It does not call the ValidationCallback function when I make the GetResponse() call which is what is throwing the exception. So based on this I would *guess* the server certificate is valid? – jrhoads23 Feb 28 '16 at 02:52
  • Can you try setting `ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls` and see if it's any difference? – Gabriel S. Feb 28 '16 at 13:33
  • Yeah I tried setting that and still get the same exception on GetResponse() – jrhoads23 Feb 28 '16 at 14:54
  • If you're getting the request stream, I assume you want to write something in it, so it's a POST/PUT verb you're performing, am I right? Does the exception you're getting happen to have an inner exception or some other relevant data? – Gabriel S. Feb 28 '16 at 15:09
  • This is my basic workflow: set SecurityProtocol to Tls12, create HttpWebRequest object with URL, set request Method to POST, set request UserAgent, set request KeepAlive to false, set request ContentType to application/x-www-form-urlencoded, encode data to send, set request ContentLength to data length, write data to stream created from request GetRequestStream(), at this point it fails on the request GetResponse() call – jrhoads23 Feb 28 '16 at 15:47
  • Have you tried a simple GET to that same server? Does it work fine? As for the `ContentLength` property, I think it's not necessary to set it manually, HttpWebRequest knows how to set it on the request by itself. – Gabriel S. Feb 28 '16 at 15:55
  • I know POST is required and all the other settings are correct because if I do the exact same thing but to the live URL (one that has not been switched to TLS 1.2) everything works – jrhoads23 Feb 28 '16 at 15:59
  • I would suggest to try a simple GET as a test to the main URL of the test server, just to see if the error persists. Maybe the result will give some clues. – Gabriel S. Feb 28 '16 at 16:13