Search code examples
.netsslhttpwebrequesttls1.2servicepointmanager

HttpWebRequest always sending TLS 1.0


I'm connecting to a 3rd party API using HttpWebRequest and getting failures ("Underlying Connection closed") that the API doesn't support the version of TLS that's used for the request. I inspect the request in Fiddler and see that my request is sending TLS 1.0.

I've tried setting the newer TLS / SSL version on the global ServicePointManager as recommended in many, many answers here on SO (and tried many different flavors of setting setting that), but even after setting that before the request is made, I still get the same error and I inspect in Fiddler and see that the request is still using TLS 1.0!. It's like my attempt at using ServicePointManager is not having any effect at all.

My DLL making the request is on .NET 4.6.1, and consuming DLL also on .NET 4.6.1, so I don't think framework version is the culprit.

Any ideas or guidance is greatly appreciated!!!


Solution

  • I had a similar issue with an Android app I was working on.

    It turned out that I had to specifically turn off TLS 1.0, which then allowed newer version of TLS to be tried. I thought it was a stupid problem to have, but what I ended up doing worked, so I wasn't going to complain too hard.

    This first article includes a lot of links to pages about auditing your code to see if a method you are using specifically locks you into TLS 1.0, as if you have accidentally hard coded it in.

    If you're using a custom binding:
    - Configure WCF to allow the OS to choose the best security protocol by setting SslProtocols to use SslProtocols.None.
    - Or configure the protocol used with the configuration path system.serviceModel/bindings/customBinding/binding/sslStreamSecurity:sslProtocols.

    If you're not using a custom binding and you're setting your WCF binding using configuration, set the protocol used with the configuration path system.serviceModel/bindings/netTcpBinding/binding/security/transport:sslProtocols.

    For .NET Framework 4.6 - 4.6.2 and not WCF
    Set the DontEnableSystemDefaultTlsVersions AppContext switch to false. See Configuring security via AppContext switches.

    For WCF using .NET Framework 4.6 - 4.6.2 using TCP transport security with Certificate Credentials
    You must install the latest OS patches. See Security updates.

    The WCF framework automatically chooses the highest protocol available up to TLS 1.2 unless you explicitly configure a protocol version. For more information, see the preceding section For WCF TCP transport using transport security with certificate credentials.

    https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls

    The above page links to the below link, which is specific to removing TLS 1.0 dependencies from your project in an effort to move to TLS 1.2+.

    https://www.microsoft.com/en-us/download/details.aspx?id=55266

    1. Identify all instances of AcquireCredentialsHandle(). This helps reviewers get closer proximity to code blocks where TLS may be hardcoded.
    2. Review any instances of the SecPkgContext_SupportedProtocols and SecPkgContext_ConnectionInfo structures for hardcoded TLS.
    3. In native code, set any non-zero assignments of grbitEnabledProtocols to zero. This allows the operating system to use its default TLS version.
    4. Disable FIPS Mode if it is enabled due to the potential for conflict with settings required for explicitly disabling TLS 1.0/1.1 in this document. See Appendix B for more information.
    5. Update and recompile any applications using WinHTTP hosted on Server 2012 or older. a. Applications must add code to support TLS 1.2 via WinHttpSetOption
    6. To cover all the bases, scan source code and online service configuration files for the patterns below corresponding to enumerated type values commonly used in TLS hardcoding:
      a. SecurityProtocolType
      b. SSLv2, SSLv23, SSLv3, TLS1, TLS 10, TLS11
      c. WINHTTP_FLAG_SECURE_PROTOCOL_
      d. SP_PROT_
      e. NSStreamSocketSecurityLevel
      f. PROTOCOL_SSL or PROTOCOL_TLS

    That's the meat of the document, but there's more to it than that. I'd suggest checking it out and making sure you aren't accidentally making a mistake or you have legacy code that's preventing you from moving forward. This might be a bit of a rewrite, rather than just a setting, so good luck!