由于遵从性原因,我们必须关闭Web服务器上某些密码和SSL2的支持。这不是一个真正的问题,但我们还想通知他们,在他们成功登录网站后,我们建议在他们的浏览器中打开TLS 1.2,以防他们尚未使用TLS 1.2连接到服务器。所以我的问题是:
如何检测对IIS中运行的ASP.net(MVC 4)应用程序的https请求中使用的协议和密码?
我知道有很多方法可以将SCHANNEL请求记录到事件日志中,然后再次读取它们,但这听起来很难听
我已经看到,System.Net.Security.SslStream具有我需要的属性,例如:ciperalgorithm、HashAlgorithm、KeyExchangeAlgorithm&;SslProtocol,但我不确定在mvc4应用程序的控制器操作中从何处获取这些属性
ILSpy确定的坏消息是,无法从ASP.Net中的任何位置访问System.Net.SslStream实例。该类用于针对网络进行直接编程,例如通过WCF框架。从ASP.NET(无论是在IIS或HttpListener上使用System.Web还是OWIN)可以做的最好的事情是获取一个服务器变量(请参阅IIS服务器变量列表),以确定连接是否由与客户端协商的任何安全传输来保护
就在web请求期间从事件日志中确定读取数据而言。。。这似乎很可怕。但如果你能让它工作,请分享代码。:)
或者,您可以尝试实现自己的Owin主机(也称为web服务器!),该主机在下面使用SslStream。也许吧P有关SslStream编程的详细介绍,请参阅本文
但是,由于您已经能够关闭服务器上的某些协议(如本文所述,我假定)。。。您可以在两个不同的子域上设置站点,例如www.example.com和secure.example.com,其中前者是普通web服务器,后者配置为仅接受TLS 1.2连接。然后,您将编写一些引导逻辑,从www.example.com获得服务,并尝试向secure.example.com/securityUpgradeCheck发出AJAX请求(可能带有风格优美的微调器动画和“请稍候,尝试保护此连接”文本,以打动您的用户:)。如果该请求成功,用户可以重定向到secure.example.com(可能是永久性的,因为该用户代理随后已知支持TLS 1.2,除非用户出于某种原因更改其浏览器设置)
为了增加影响,请为安全域订购EV SSL证书,以便您的用户注意到安全方面的升级。:)
更新:在编写自定义(本机)ISAPI过滤器(或扩展)的理论基础上,我做了更多的挖掘,以通过SChannel API获取这些信息。起初我满怀希望,因为我发现了一个函数HSE\u REQ\u GET\u SSPI\u INFO,它将返回一个SSPICtxtHandle结构,您可以通过扩展控制块服务器支持函数函数从自定义ISAPI扩展调用该函数。事实证明,CtxtHandle结构代表了一个SChannel上下文,可以为您提供一个对SECPKG\u ATTR\u CONNECTION\u INFO属性的引用,您可以使用该属性检索SSL连接级别信息(据我所知,SslStream类中出现的信息)。然而,不幸的是,微软预见到了这种可能性,并决定只有在使用客户端证书时,此信息才可用。这种行为是“设计的”
有一个(本机)SSPI函数,QueryContextAttributes(Schannel),我在通过MSDN进行的长时间搜索中发现了这个函数,可能会起作用。我还没有尝试过,它可能会因为与上面链接的ISAPI限制相同的“按设计”原因而失败。然而,这可能值得一试。如果您想探索这条路线,下面是一个ISAPI扩展的示例。实际上,使用这种方法,您可能可以使用较新的IIS 7.0+SDK编写IIS模块
但是,假设您没有要求客户机证书的奢侈,而且这种远射不起作用,那么绝对只剩下两种选择
- 使用不同的web服务器(Apache等),运行在相同的物理/虚拟机上,但在不同的端口上,等等(根据我们在评论中的讨论,因为您无法启动另一台机器)。如果您只想给客户机一条信息性消息,那么这种方法加上AJAX请求就足够了。是的,一个不同的端口可能会被某个地方的防火墙阻止,但是,嘿,无论如何,这只是一条可选的信息消息
- 依靠半脆性方法和系统事件日志。启用Schannel事件日志记录,然后编写一些事件日志查询代码,尝试将请求与上次记录的Schannel事件关联起来。请注意,您需要找到一种方法来可靠地将事件日志中放入的内容与当前HTTP请求关联起来,因此您可能还需要编写ISAPI筛选器/扩展或IIS模块(在本例中)来查找Schannel上下文句柄(我假设关联将基于此)
顺便问一下,您的负载平衡器是否配置为执行任何SSL拦截?因为这整件事无论如何都没有意义。。。只是考虑一下。
更新:启用Schannel日志记录可获得此gem:
<;事件xmlns=”http://schemas.microsoft.com/win/2004/08/events/event“>;
<;系统>;
<;提供者名称=“Schannel”Guid=“{1F678132-5938-4686-9FDC-C8FF68F15C85}”/>;
<;EventID>;36880</EventID>;
<;版本>;0</版本>;
<;级别>;4</级别>;
<;任务>;0</任务>;
<;操作码>;0</操作码>;
<;关键词>;0x80000000000000</关键词>;
<;TimeCreated SystemTime=“2014-08-13T02:59:35.431187600Z”/>;
<;EventRecordID>;25943</EventRecordID>;
<;相关性/>;
<;执行过程id=“928”ThreadID=“12912”/>;
<;频道>;系统</频道>;
<;计算机>**********</计算机>;
<;安全用户ID=“S-1-5-18”/>;
</系统>;
<;用户数据>;
<;EventXML xmlns:auto-ns3=”http://schemas.microsoft.com/win/2004/08/events“xmlns=”LSA_NS“>;
<;类型>;客户</类型>;
<;协议>;TLS 1.2</协议>;
<;CipherSuite>;0x3c</CipherSuite>;
<;交换长度>;2048年</交换长度>;
</EventXML>;
</用户数据>;
</事件>;
这可以直接从托管代码中读取。不幸的是,我认为UserID只对应于IIS工作进程SID,但假设您可以提出某种关联启发,您可以设置一个后台线程来持续轮询事件日志,并为您提供最近建立的客户端握手列表(可能使用ConcurrentDictionary)
在那里。就这样。我不再好奇了。我做完了P