WCF/TLS 服务中的 SecurityNegotiationException 仅在高延迟网络上
SecurityNegotiationException in WCF/TLS service only on high latency network
我尝试使 WCF Web 服务在高延迟/低带宽网络上运行,但事情没有按计划运行。
WCF 服务在 windows 服务中自托管,实现了这个接口:
[OperationContract(Name = "send-file")]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
void SendFile(MyFileInfo myFile);
MyFileInfo 对象包含文件(作为字节数组)。该文件大约为 45 kB(千字节)。
TLS 正在使用,客户端和服务器身份验证(来自同一 CA 的证书,来自同一域的客户端和服务器)。
ServicePointManager.SecurityProtocol 在客户端和服务器上都设置为 SecurityProtocolType.Tls12,Expect100Continue 设置为 true,KeepAlive 在绑定传输元素上以编程方式设置为 true。
App.config 在这里(客户端和服务器相同):
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MyHttpsBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" messageEncoding="Text"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="104857600" maxReceivedMessageSize="104857600"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="104857600" maxArrayLength="104857600" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None" />
<message clientCredentialType="None" ></message>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service
name="MyService"
behaviorConfiguration="MyHttpsBehavior">
<endpoint binding="wsHttpBinding"
bindingConfiguration="MyHttpsBinding" name="MyEndpoint"
contract="IMyInterface">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyHttpsBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
在标准本地网络(WLAN 或以太网,MTU 始终设置为 1248)上一切正常,但当我切换到(模拟)高延迟/低带宽网络时出现错误:
- 800 毫秒延迟,入站和出站。这使得 1.6sc 来回
旅行。
- 492 Kbps(千比特,不是字节)。
- MTU = 1248
起初,我的 app.conf 超时设置设置为 1 分钟,客户端抛出了一个坚实的 System.TimeoutException : "The request channel timed out while waiting for a reply after 00:00:59.1535069. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'https://myserver:4444/' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout."
服务器上没有错误。
如果我算一下,文件是 45 kb = 46080 b ~> 37 个数据包(MTU 和碎片)=> 37 * 1600(延迟)= 最少 1 分钟(加上 TLS,加上负载,加上... )
我将客户端和服务器上的超时设置更改为 5 分钟,弹出一个新的客户端异常:"System.ServiceModel.Security.SecurityNegotiationException: Could not establish trust relationship for the SSL/TLS secure channel with authority 'myserver:4444'"
客户端和服务器可以是 Windows 8 或 Windows 2008 R2,防火墙已关闭,如果我停止延迟模拟器 (Clumsy),一切都会恢复正常。
我比 WCF 更能感觉到 TLS 问题,但我不是专家。也许你们中有人对这个问题有想法?
提前致谢!
Dj
编辑
我尝试了 Wireshark 会话(客户端视图),结果如下:
2 26.958440 client -> server TCP 66 64972 → 4444 [SYN] Seq=0 Win=8192 Len=0 MSS=1208 WS=256 SACK_PERM=1
3 26.958603 server -> client TCP 66 4444 → 64972 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
4 28.606141 client -> server TCP 54 64972 → 4444 [ACK] Seq=1 Ack=1 Win=66304 Len=0
5 28.606359 client -> server TCP 276 64972 → 4444 [PSH, ACK] Seq=1 Ack=1 Win=66304 Len=222
6 28.610326 server -> client TCP 1262 4444 → 64972 [ACK] Seq=1 Ack=223 Win=66304 Len=1208
7 28.610328 server -> client TCP 711 4444 → 64972 [PSH, ACK] Seq=1209 Ack=223 Win=66304 Len=657
8 30.277053 client -> server TCP 54 64972 → 4444 [ACK] Seq=223 Ack=1866 Win=61440 Len=0
9 30.277177 client -> server TCP 236 64972 → 4444 [PSH, ACK] Seq=223 Ack=1866 Win=61440 Len=182
10 30.279375 server -> client TCP 161 4444 → 64972 [PSH, ACK] Seq=1866 Ack=405 Win=66048 Len=107
11 31.920922 client -> server TCP 331 64972 → 4444 [PSH, ACK] Seq=405 Ack=1973 Win=61440 Len=277
12 31.921599 server -> client TCP 139 4444 → 64972 [PSH, ACK] Seq=1973 Ack=682 Win=65792 Len=85
13 32.249867 client -> server TCP 1262 64972 → 4444 [ACK] Seq=682 Ack=1973 Win=61440 Len=1208
14 32.250099 client -> server TCP 1262 64972 → 4444 [ACK] Seq=1890 Ack=1973 Win=61440 Len=1208
15 32.250226 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=3098 Win=66304 Len=0
16 32.250437 client -> server TCP 1262 64972 → 4444 [ACK] Seq=3098 Ack=1973 Win=61440 Len=1208
17 32.250699 client -> server TCP 1262 64972 → 4444 [ACK] Seq=4306 Ack=1973 Win=61440 Len=1208
18 32.250816 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=5514 Win=66304 Len=0
19 33.623716 client -> server TCP 54 64972 → 4444 [ACK] Seq=5514 Ack=2058 Win=61440 Len=0
... lots of similar packets ...
89 37.189910 client -> server TCP 1262 64972 → 4444 [ACK] Seq=61082 Ack=2058 Win=61440 Len=1208
90 37.190103 client -> server TCP 1262 64972 → 4444 [ACK] Seq=62290 Ack=2058 Win=61440 Len=1208
91 37.190260 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=63498 Win=53760 Len=0
92 37.190303 client -> server TCP 1262 64972 → 4444 [ACK] Seq=63498 Ack=2058 Win=61440 Len=1208
93 37.190499 client -> server TCP 1262 64972 → 4444 [ACK] Seq=64706 Ack=2058 Win=61440 Len=1208
94 37.190654 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=65914 Win=51200 Len=0
95 37.190699 client -> server TCP 1262 64972 → 4444 [PSH, ACK] Seq=65914 Ack=2058 Win=61440 Len=1208
96 37.190890 client -> server TCP 865 64972 → 4444 [PSH, ACK] Seq=67122 Ack=2058 Win=61440 Len=811
97 37.191046 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=67933 Win=49152 Len=0
98 160.241458 server -> client TCP 60 4444 → 64972 [RST, ACK] Seq=2058 Ack=67933 Win=0 Len=0
98 数据包 (RST ACK) 与我在客户端出现异常的时间完全相同。服务器上仍然没有错误。
我没有时间进一步调查,我仍然不知道为什么相互身份验证不起作用,但如果我禁用客户端证书,一切都会再次正常。问题(几乎)解决了...
我尝试使 WCF Web 服务在高延迟/低带宽网络上运行,但事情没有按计划运行。 WCF 服务在 windows 服务中自托管,实现了这个接口:
[OperationContract(Name = "send-file")]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
void SendFile(MyFileInfo myFile);
MyFileInfo 对象包含文件(作为字节数组)。该文件大约为 45 kB(千字节)。
TLS 正在使用,客户端和服务器身份验证(来自同一 CA 的证书,来自同一域的客户端和服务器)。
ServicePointManager.SecurityProtocol 在客户端和服务器上都设置为 SecurityProtocolType.Tls12,Expect100Continue 设置为 true,KeepAlive 在绑定传输元素上以编程方式设置为 true。
App.config 在这里(客户端和服务器相同):
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MyHttpsBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" messageEncoding="Text"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="104857600" maxReceivedMessageSize="104857600"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="104857600" maxArrayLength="104857600" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None" />
<message clientCredentialType="None" ></message>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service
name="MyService"
behaviorConfiguration="MyHttpsBehavior">
<endpoint binding="wsHttpBinding"
bindingConfiguration="MyHttpsBinding" name="MyEndpoint"
contract="IMyInterface">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyHttpsBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
在标准本地网络(WLAN 或以太网,MTU 始终设置为 1248)上一切正常,但当我切换到(模拟)高延迟/低带宽网络时出现错误:
- 800 毫秒延迟,入站和出站。这使得 1.6sc 来回 旅行。
- 492 Kbps(千比特,不是字节)。
- MTU = 1248
起初,我的 app.conf 超时设置设置为 1 分钟,客户端抛出了一个坚实的 System.TimeoutException : "The request channel timed out while waiting for a reply after 00:00:59.1535069. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'https://myserver:4444/' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout."
服务器上没有错误。
如果我算一下,文件是 45 kb = 46080 b ~> 37 个数据包(MTU 和碎片)=> 37 * 1600(延迟)= 最少 1 分钟(加上 TLS,加上负载,加上... )
我将客户端和服务器上的超时设置更改为 5 分钟,弹出一个新的客户端异常:"System.ServiceModel.Security.SecurityNegotiationException: Could not establish trust relationship for the SSL/TLS secure channel with authority 'myserver:4444'"
客户端和服务器可以是 Windows 8 或 Windows 2008 R2,防火墙已关闭,如果我停止延迟模拟器 (Clumsy),一切都会恢复正常。
我比 WCF 更能感觉到 TLS 问题,但我不是专家。也许你们中有人对这个问题有想法?
提前致谢!
Dj
编辑 我尝试了 Wireshark 会话(客户端视图),结果如下:
2 26.958440 client -> server TCP 66 64972 → 4444 [SYN] Seq=0 Win=8192 Len=0 MSS=1208 WS=256 SACK_PERM=1
3 26.958603 server -> client TCP 66 4444 → 64972 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
4 28.606141 client -> server TCP 54 64972 → 4444 [ACK] Seq=1 Ack=1 Win=66304 Len=0
5 28.606359 client -> server TCP 276 64972 → 4444 [PSH, ACK] Seq=1 Ack=1 Win=66304 Len=222
6 28.610326 server -> client TCP 1262 4444 → 64972 [ACK] Seq=1 Ack=223 Win=66304 Len=1208
7 28.610328 server -> client TCP 711 4444 → 64972 [PSH, ACK] Seq=1209 Ack=223 Win=66304 Len=657
8 30.277053 client -> server TCP 54 64972 → 4444 [ACK] Seq=223 Ack=1866 Win=61440 Len=0
9 30.277177 client -> server TCP 236 64972 → 4444 [PSH, ACK] Seq=223 Ack=1866 Win=61440 Len=182
10 30.279375 server -> client TCP 161 4444 → 64972 [PSH, ACK] Seq=1866 Ack=405 Win=66048 Len=107
11 31.920922 client -> server TCP 331 64972 → 4444 [PSH, ACK] Seq=405 Ack=1973 Win=61440 Len=277
12 31.921599 server -> client TCP 139 4444 → 64972 [PSH, ACK] Seq=1973 Ack=682 Win=65792 Len=85
13 32.249867 client -> server TCP 1262 64972 → 4444 [ACK] Seq=682 Ack=1973 Win=61440 Len=1208
14 32.250099 client -> server TCP 1262 64972 → 4444 [ACK] Seq=1890 Ack=1973 Win=61440 Len=1208
15 32.250226 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=3098 Win=66304 Len=0
16 32.250437 client -> server TCP 1262 64972 → 4444 [ACK] Seq=3098 Ack=1973 Win=61440 Len=1208
17 32.250699 client -> server TCP 1262 64972 → 4444 [ACK] Seq=4306 Ack=1973 Win=61440 Len=1208
18 32.250816 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=5514 Win=66304 Len=0
19 33.623716 client -> server TCP 54 64972 → 4444 [ACK] Seq=5514 Ack=2058 Win=61440 Len=0
... lots of similar packets ...
89 37.189910 client -> server TCP 1262 64972 → 4444 [ACK] Seq=61082 Ack=2058 Win=61440 Len=1208
90 37.190103 client -> server TCP 1262 64972 → 4444 [ACK] Seq=62290 Ack=2058 Win=61440 Len=1208
91 37.190260 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=63498 Win=53760 Len=0
92 37.190303 client -> server TCP 1262 64972 → 4444 [ACK] Seq=63498 Ack=2058 Win=61440 Len=1208
93 37.190499 client -> server TCP 1262 64972 → 4444 [ACK] Seq=64706 Ack=2058 Win=61440 Len=1208
94 37.190654 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=65914 Win=51200 Len=0
95 37.190699 client -> server TCP 1262 64972 → 4444 [PSH, ACK] Seq=65914 Ack=2058 Win=61440 Len=1208
96 37.190890 client -> server TCP 865 64972 → 4444 [PSH, ACK] Seq=67122 Ack=2058 Win=61440 Len=811
97 37.191046 server -> client TCP 60 4444 → 64972 [ACK] Seq=2058 Ack=67933 Win=49152 Len=0
98 160.241458 server -> client TCP 60 4444 → 64972 [RST, ACK] Seq=2058 Ack=67933 Win=0 Len=0
98 数据包 (RST ACK) 与我在客户端出现异常的时间完全相同。服务器上仍然没有错误。
我没有时间进一步调查,我仍然不知道为什么相互身份验证不起作用,但如果我禁用客户端证书,一切都会再次正常。问题(几乎)解决了...