由于合规性原因,我们必须关闭Web服务器上某些密码和SSL2的支持。这并不是真正的问题,但是在他们成功登录网站后,我们还想通知他们,如果他们尚未使用TLS 1.2连接到服务器,我们建议在他们的浏览器中打开TLS 1.2。所以我的问题是:
如何检测对IIS中运行的ASP.net(MVC 4)应用程序的https请求中使用的协议和密码?
我知道有多种方法可以将SCHANNEL请求记录到事件日志中,然后再次将其读出,但这对我来说听起来很丑。
而且我已经看到System.Net.Security.SslStream具有我需要的属性,例如:CipherAlgorithm,HashAlgorithm,KeyExchangeAlgorithm和SslProtocol,但是我不确定在mvc4的Controller Action中可以从哪里获得这些属性。应用。
最佳答案
由ILSpy确定的坏消息是,无法从ASP.NET内部的任何地方访问System.Net.SslStream
实例。该类用于通过WCF框架针对网络进行直接编程。从ASP.NET(无论是在IIS还是HttpListener之上使用System.Web或OWIN),您可以做的最好的事情就是获取服务器变量(see list of IIS server variables),以确定是否通过与客户端协商的任何安全传输来确保连接的安全。
就在Web请求期间确定性地从事件日志中读取数据而言……这似乎很可怕。但是,如果您可以使用它,请共享代码。 :)
另外,您可以尝试实现自己的在下面使用SslStream
的Owin主机(又名Web服务器!)。也许。 :P有关SslStream
编程的完整介绍,请参见this article。
但是,由于您已经能够关闭服务器上的某些协议(我假设是在this article中),因此您可以将站点设置在两个不同的子域中,例如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_REQ_GET_SSPI_INFO
,该函数将返回SSPI CtxtHandle
结构,并且可以通过EXTENSION_CONTROL_BLOCK
ServerSupportFunction
函数从自定义ISAPI扩展中调用该函数。事实证明,该CtxtHandle
结构表示SChannel上下文,并且可以为您提供对SECPKG_ATTR_CONNECTION_INFO
属性的引用,通过该属性可以检索SSL连接级信息(与中的SslStream
类相同的信息)。 NET,据我所知)。但是,令人遗憾的是,Microsoft anticipated that possibility并决定仅在使用客户端证书时此信息才可用。该行为是“设计使然”。
我在长时间的MSDN搜索中发现了一个(本机)SSPI函数QueryContextAttributes (Schannel)
,该函数可能有效。我没有尝试过,它可能由于与上面链接的ISAPI API限制相同的“设计”原因而失败。但是,可能值得尝试。如果您想探索这条路线,这里是an example of an ISAPI extension。实际上,通过这种方法,您也许可以使用更新的IIS 7.0+ SDK来编写IIS模块。
但是,假设您没有要求提供客户证书的奢侈功能,并且远距离拍摄不起作用,那么绝对只剩下两个选择。
使用在同一台物理/虚拟机上但在不同端口上运行的其他Web服务器(Apache等)(根据我们在注释中的讨论,因为您不能启动另一台计算机)。如果您只想向客户提供参考消息,则此方法以及AJAX请求可能就足够了。是的,其他端口很可能会被某个地方的防火墙阻止,但是,嘿-无论如何,这只是一个可选的信息性消息。
依靠带有系统事件日志的半脆弱方法。 Enable Schannel event logging,然后编写一些事件日志查询代码,以尝试将请求与最后记录的Schannel事件相关联。请注意,您将需要找到一种方法来可靠地将事件日志中放入的内容与当前HTTP请求相关联,因此在这种情况下,您可能还需要编写ISAPI过滤器/扩展或IIS模块才能找到Schannel上下文句柄(这是我假设相关性的基础)。
顺便说一句-您的负载均衡器是否配置为可以进行SSL拦截?因为那样的话,整个事情还是没有意义的……只是要考虑的一个想法。
更新:启用Schannel日志记录可以获取以下信息:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Schannel" Guid="{1F678132-5938-4686-9FDC-C8FF68F15C85}" />
<EventID>36880</EventID>
<Version>0</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2014-08-13T02:59:35.431187600Z" />
<EventRecordID>25943</EventRecordID>
<Correlation />
<Execution ProcessID="928" ThreadID="12912" />
<Channel>System</Channel>
<Computer>**********</Computer>
<Security UserID="S-1-5-18" />
</System>
<UserData>
<EventXML xmlns:auto-ns3="http://schemas.microsoft.com/win/2004/08/events" xmlns="LSA_NS">
<Type>client</Type>
<Protocol>TLS 1.2</Protocol>
<CipherSuite>0x3c</CipherSuite>
<ExchangeStrength>2048</ExchangeStrength>
</EventXML>
</UserData>
</Event>
可以直接从托管代码中读出。不幸的是,我认为UserID仅对应于IIS工作进程SID,但是假设您可以提出某种相关启发式方法,则可以设置一个后台线程来连续轮询事件日志并为您提供一个最近建立的客户端列表。握手(也许使用
ConcurrentDictionary
)。那里。而已。不用再为我调查了。我受够了。 :P