如何从服务器检查协商的 TLS 握手?

Sua*_*ere 7 c# asp.net-mvc ssl asp.net-web-api tls1.2

如果我有十几个端点,并且我的 WebAPI 服务配置为TLS 1.1TLS 1.2,我如何检查每个传入的端点请求以查看协商的是哪个版本?

因此,如果我的端点的使用者目前仅支持TLS 1.0and TLS 1.1,他们将(显然?)协商TLS 1.1握手。但是如果不同的消费者支持TLS 1.2and TLS 1.3,他们会(显然?)协商TLS 1.2握手。

我想跟踪我所有的消费者,看看正在协商什么握手。我如何按请求执行此操作?

No *_*rns 6

如果您使用的是 IIS,看起来您可以向 IIS 日志添加一些扩展日志记录。

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

抄袭......呃......为后代引用:

要启用此新功能,需要将这四个服务器变量配置为 IIS applicationHost.config 中自定义字段的来源。可以在服务器级别或站点级别配置自定义日志记录。这是一个示例站点级配置:

<site name="Default Web Site" id="1" serverAutoStart="true">
 <application path="/">
 <virtualDirectory path="/" physicalPath="C:\inetpub\wwwroot" />
 </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>
Run Code Online (Sandbox Code Playgroud)

每个 SSL 信息字段都是一个十六进制数,映射到安全协议版本或密码套件算法。对于 HTTP 纯文本请求,所有四个字段都将记录为“-”。

又是我:

看起来CRYPT_PROTOCOL可以400用于IIS 文本日志中的TLS1.2、40TLS 1.010和 SSLv3。

从示例中可以看出,如果您想尝试将自定义日志包含在比 IIS 日志本身更易于自定义的自定义日志中,则每个请求上可能都有 ServerVariable 值。

好问题!我可能有机会自己使用这个答案。


所以......看起来你可以从 WebAPI 获取 ServerVariables 但只是以一种意想不到的方式。请参阅下面的片段。似乎如果您枚举集合或调用 Keys 属性,您得到的只是变量的一些子集。但是,如果您在任何这些操作之前明确请求 CRYPT_* 变量,那么您can indeed就可以从控制器中获取它们。我在 WebAPI 5.2.6 上尝试了这个,目标是在 IIS 下作为 Azure 经典云服务运行的 .net 4.6.2。我建议试试这个,看看它是否适合你。如果您有关于服务器变量的更新参考,请编辑此答案并将https://docs.microsoft.com/en-us/iis/web-dev-reference/server-variables替换为您的链接。

下面在为列出的环境写作日期对我有用。未来可能会改变。对于生产,我肯定会将其移动到辅助方法中。

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("\r", "0x0D").Replace("\n", "0x0A")}]");
    }
    catch (Exception ex)
    {
       headers.Add($"SV_{CRYPT_PROTOCOL}", ex.Message);
    }
    foreach (string key in v.AllKeys)
      {
      headers.Add($"SV_{key}", v[key].Replace("\r", "0x0D").Replace("\n", "0x0A"));
      }
     headers.Add($"SV_DONE", "All Server Variables Replaced");
     }
  }
Run Code Online (Sandbox Code Playgroud)