Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
494 views
in Technique[技术] by (71.8m points)

c# - How do you check the Negotiated TLS Handshake from the Server?

If I have a dozen endpoints, and my WebAPI Service is configured for TLS 1.1 and TLS 1.2, how do I check each incoming endpoint request to see which version was negotiated?

So if a consumer of my endpoints currently only supports TLS 1.0 and TLS 1.1, they'll (obviously?) negotiate a TLS 1.1 handshake. But if a different consumer supports TLS 1.2 and TLS 1.3, they'll (obviously?) negotiate a TLS 1.2 handshake.

I want to track all of my consumers to see what handshakes are being negotiated. How do I do that per-request?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you are using IIS it looks like you can add some extended logging to your IIS logs.

https://cloudblogs.microsoft.com/microsoftsecure/2017/09/07/new-iis-functionality-to-help-identify-weak-tls-usage/

plagiarizing ... er ... quoting for posterity:

To enable this new functionality, these four server variables need to be configured as the sources of the custom fields in IIS applicationHost.config. The custom logging can be configured on either server level or site level. Here is a sample site-level configuration:

<site name="Default Web Site" id="1" serverAutoStart="true">
 <application path="/">
 <virtualDirectory path="/" physicalPath="C:inetpubwwwroot" />
 </application>
 <bindings>
 <binding protocol="https" bindingInformation="*:443:" />
 </bindings>
 <logFile>
 <customFields>
 <clear />
<add logFieldName="crypt-protocol" sourceName="CRYPT_PROTOCOL" sourceType="ServerVariable" />
<add logFieldName="crypt-cipher" sourceName="CRYPT_CIPHER_ALG_ID" sourceType="ServerVariable" />
<add logFieldName="crypt-hash" sourceName="CRYPT_HASH_ALG_ID" sourceType="ServerVariable" />
<add logFieldName="crypt-keyexchange" sourceName="CRYPT_KEYEXCHANGE_ALG_ID" sourceType="ServerVariable" />
 </customFields>
 </logFile>
 </site>

Each SSL info field is a hexadecimal number that maps to either a secure protocol version or cipher suite algorithm. For an HTTP plain-text request, all four fields will be logged as ‘-‘.

Me again:

It looks like CRYPT_PROTOCOL can be 400 for TLS1.2, 40 for TLS 1.0, 10 for SSLv3 in the IIS Text logs.

From the examples, it looks like there might be ServerVariable values on each Request if you want to try to include in custom logs that are a bit easier to customize than the IIS log itself.

Great Question! and I may have a chance to use this answer m'self.


So ... it looks like you CAN get the ServerVariables from WebAPI but only in an unexpected way. See the snippet below. It seems if you enumerate the collection or call the Keys property all you get is some subset of variables. But if you explicitly request the CRYPT_* variables before any of those actions then you can indeed get them from your controller. I tried this on WebAPI 5.2.6 targeting .net 4.6.2 running under IIS as an Azure Classic Cloud Service. I suggest trying this and seeing if it works for you. If you have a more recent reference for Server Variables, please edit this answer and replace https://docs.microsoft.com/en-us/iis/web-dev-reference/server-variables with your link.

Below worked for me on date of writing for environment listed. It may change in the future. For production I would definitely move this into a helper method.

if (Request.Properties.TryGetValue("MS_HttpContext", out object context))
 {
 if (context is HttpContextWrapper wrapper)
  {
  var v = wrapper.Request?.ServerVariables;
  if (v != null)
   {
   var headers = response.Headers;
   const string CRYPT_PROTOCOL = nameof(CRYPT_PROTOCOL);
   try
    {
    headers.Add($"SV_{CRYPT_PROTOCOL}", $"[{v[CRYPT_PROTOCOL].Replace("
", "0x0D").Replace("
", "0x0A")}]");
    }
    catch (Exception ex)
    {
       headers.Add($"SV_{CRYPT_PROTOCOL}", ex.Message);
    }
    foreach (string key in v.AllKeys)
      {
      headers.Add($"SV_{key}", v[key].Replace("
", "0x0D").Replace("
", "0x0A"));
      }
     headers.Add($"SV_DONE", "All Server Variables Replaced");
     }
  }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...