我有一台 Windows 10 笔记本电脑,有一个奇怪的问题,即无法打开任何浏览器https://rutracker.org/
情况是这样的(在开发者工具模式下):浏览器长时间不承认它向远程发送了任何内容(例如 Chrome 报告它“停滞”),然后请求被列为失败,没有明显原因。我也尝试了 Firefox 和 Edge,结果相同,它们无法连接并且无法提供任何有意义的调试。
我甚至安装了 cURL。结果如下:
curl -k -vvv https://rutracker.org/forum/index.php
* Trying 195.82.146.214...
* TCP_NODELAY set
* Connected to rutracker.org (195.82.146.214) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
然后它会挂起很长时间,然后抱怨 SSL_ERROR_SYSCALL。相比之下,在 Linux 上看起来完全不同:
curl -k -vvv https://rutracker.org/forum/index.php
* Hostname was NOT found in DNS cache
* Trying 195.82.146.214...
* Connected to rutracker.org (195.82.146.214) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: CN=rutracker.org
* start date: 2018-07-20 04:13:49 GMT
* expire date: 2018-10-18 04:13:49 GMT
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
> GET /forum/index.php HTTP/1.1
> User-Agent: curl/7.38.0
> Host: rutracker.org
> Accept: */*
>
< HTTP/1.1 200 OK
也许有一种浏览器版本将使用纯 OpenSSL,完全避免 Windows SSL 实现?因为这似乎是这里的问题所在。我最近检查了 Malwarebytes,没有发现任何特别的东西。
编辑:我发现只有当我通过 PPTP VPN 连接时才会发生这种情况。当我切换到 L2TP 时,我可以毫无问题地打开网站。这是怎么回事?
答案1
Windows 的 TLS 库没有任何问题(事实上,在针对 OpenSSL/1.1.0i 进行编译时,Linux 上的 curl 的行为也相同)——它只是使用了一种较新的握手格式,该格式尝试使用更少、更大的消息(减少延迟),而您的 curl 使用了一个仍然具有“SSLv3 兼容”模式的旧库。
但这只是可能引发相同问题的众多因素之一。真正的问题是:
- 在 VPN 服务器上,虚拟“PPTP 客户端”网络接口的 MTU 设置为相对较低的值(例如 1280 字节)——以解决 VPN 开销等问题。
- 在 TLS 握手期间,Rutracker 服务器会向您发送一个大于此 MTU 的 IP 数据包。
- VPN 服务器无法转发该数据包,因为它大于输出接口,并返回 ICMP“太大”错误数据包,指示支持的 MTU。
- Rutracker 网络服务器忽略ICMP 消息,不会相应地调整其路由缓存,并继续向您发送相同的大数据包。从步骤 2 重新开始。
这种基于 ICMP 的 MTU 协商称为“路径 MTU 发现”,发送方忽略接收方建议的情况称为“PMTU 黑洞”。也许 Rutracker 的管理员听说过完全阻止 ICMP 会使网站在某种程度上“更安全”...
从示例 VPN 服务器的角度来看,情况如下(使用故意错误配置的 OpenVPN)——请注意大数据包是如何被一次又一次地拒绝的:
IP 31.220.xy48872 > 195.82.146.214.443:标志 [S],序列 2337162999,win 29200,选项 [mss 1358,sackOK,TS val 674971446 ecr 0,nop,wscale 7],长度 0 IP 195.82.146.214.443 > 31.220.xy48872:标志 [S.],seq 2391406816,ack 2337163000,win 14600,选项 [mss 1460,nop,wscale 8],长度 0 IP 31.220.xy48872 > 195.82.146.214.443: 标志 [.], ack 1, win 229, 长度 0 IP 31.220.xy48872 > 195.82.146.214.443: 标志 [P.], 序号 1:217, ack 1, win 229, 长度 216 IP 195.82.146.214.443 > 31.220.xy48872:标志 [.],ack 217,win 62,长度 0 IP 195.82.146.214.443 > 31.220.xy48872:标志 [.],序号 1:1359,ack 217,win 62,长度 1358 IP 31.220.xy > 195.82.146.214:ICMP 31.220.xy 不可达 - 需要分片 (mtu 1280),长度 556 IP 195.82.146.214.443 > 31.220.xy48872:标志 [P.],序列号 1359:3242,ack 217,win 62,长度 1883 IP 31.220.xy > 195.82.146.214:ICMP 31.220.xy 不可达 - 需要分片 (mtu 1280),长度 556 IP 195.82.146.214.443 > 31.220.xy48872:标志 [.],序号 1:1359,ack 217,win 62,长度 1358 IP 31.220.xy > 195.82.146.214:ICMP 31.220.xy 不可达 - 需要分片 (mtu 1280),长度 556 IP 195.82.146.214.443 > 31.220.xy48872:标志 [.],序号 1:1359,ack 217,win 62,长度 1358 IP 31.220.xy > 195.82.146.214:ICMP 31.220.xy 不可达 - 需要分片 (mtu 1280),长度 556 IP 195.82.146.214.443 > 31.220.xy48872:标志 [.],序号 1:1359,ack 217,win 62,长度 1358 IP 31.220.xy > 195.82.146.214:ICMP 31.220.xy 不可达 - 需要分片 (mtu 1280),长度 556 IP 195.82.146.214.443 > 31.220.xy48872:标志 [.],序号 1:1359,ack 217,win 62,长度 1358 IP 31.220.xy > 195.82.146.214:ICMP 31.220.xy 不可达 - 需要分片 (mtu 1280),长度 556
L2TP VPN 不受影响,可能出于以下几个原因:
- 它可以使用默认的 1500 MTU 作为隧道并透明地分段超大数据包;
- 它可以对看到的连接执行 TCP MSS 限制;
- 它可以向您的 VPN 客户端软件报告减少的 MTU,以便您的操作系统已经提前知道在其 TCP 连接请求中放置正确的 MSS。
作为客户端,您的选择是(取决于操作系统支持的内容):
- 根本不要使用 PPTP VPN。(不是因为 MTU 问题——在这方面 PPTP 并不比其他类型的 VPN 更好或更差——而是因为该协议存在安全问题。MPPE 加密和 MSCHAP 身份验证都非常薄弱。)
- 在客户端操作系统上降低 VPN 接口的 MTU(例如降低至 1400 或 1280)。例如,Linux 允许您执行此操作
ip link set ppp0 mtu <bytes>
。您的系统将相应地向 Rutracker 服务器通告较低的 TCP MSS 值。 - 在客户端操作系统上启用 TCP MTU 探测。例如,Linux 有
sysctl net.ipv4.tcp_mtu_probing=1
。即使在 ICMP PMTUD 不起作用的情况下,此功能也能正常工作。 - 配置 VPN 客户端的或者VPN 服务器的防火墙执行 TCP MSS 限制。(这可以在路径上的任何地方完成。)
- 尝试说服 Rutracker 管理员,他们做出了一个错误的决定。