我的应用程序必须通过https与不同的主机通信,默认设置ServicePointManager.SecurityProtocol = TLS
直到今天仍然很好。现在我有一些主机(如System.Net
跟踪日志显示)不回答初始TLS握手消息,但保持底层连接打开直到超时,抛出超时异常。我尝试将HttpWebRequest
的超时时间设置为5分钟,结果相同。据推测,这些主机正在等待SSL3握手,因为IE和Firefox都可以在30-40秒的延迟后连接到这些主机。在.NET中似乎有一些回退机制将TLS降级为SSL3,但由于某种原因它没有起作用。
FWIW,这是我的请求发送的握手消息(常规TLS 1.0 CLIENT HELLO消息):
00000000 : 16 03 01 00 57 01 00 00-53 03 01 4C 12 39 B4 F9 : ....W...S..L.9..
00000010 : A3 2C 3D EE E1 2A 7A 3E-D2 D6 0D 2E A9 A8 6C 03 : .,=..*z>......l.
00000020 : E7 8F A3 43 0A 73 9C CE-D7 EE CF 00 00 18 00 2F : ...C.s........./
00000030 : 00 35 00 05 00 0A C0 09-C0 0A C0 13 C0 14 00 32 : .5.............2
00000040 : 00 38 00 13 00 04 01 00-00 12 00 0A 00 08 00 06 : .8..............
00000050 : 00 17 00 18 00 19 00 0B-00 02 01 00 : ............
有没有办法在特定HttpWebRequest
中使用SSL3而不是TLS,还是强制进行回退?似乎ServicePointManager
的设置是全局的,我真的不愿意为整个应用程序将安全协议设置降级为SSL3。
答案 0 :(得分:13)
实际上,ServicePointManager
设置是每个应用程序域。这使我能够通过创建一个单独的appdomain设置为仅使用SSL3来解决此问题,使我的数据收集对象MarshalByRefObject
(WebClient
和WebRequest
都是由编组编组,但最好减少跨appdomain调用的数量)并在那里创建它。与基于超时的检测方案完美结合。
答案 1 :(得分:4)
.NET包含自动协商到协议的较低版本的规定。 ServicePointManager.SecurityProtocol
的值决定了行为。它可以采用3个不同的值:SecurityProtocol.Ssl3, SecurityProtocol.Tls, or SecurityProtocol.Ssl3 | SecurityProtocol.Tls
。虽然是全球性的,但可以根据需要进行更改。
如果没有访问具有相同错误行为的服务器,我无法识别解决方案。关于我可以做的唯一建议是尝试连接Ssl3 | Tls
设置,如果这不起作用,请使用Ssl3
设置重试。尝试降低超时并捕获超时异常,然后重试。
编辑
我在上一个版本中写的很多内容都是错误的。