![使用 OpenWRT 路由器时,某些网站的 TLS 握手会重置](https://linux22.com/image/1569271/%E4%BD%BF%E7%94%A8%20OpenWRT%20%E8%B7%AF%E7%94%B1%E5%99%A8%E6%97%B6%EF%BC%8C%E6%9F%90%E4%BA%9B%E7%BD%91%E7%AB%99%E7%9A%84%20TLS%20%E6%8F%A1%E6%89%8B%E4%BC%9A%E9%87%8D%E7%BD%AE.png)
目前我的路由器出现了一个非常奇怪的问题。TP-Link TL-WDR4300rev. 1.7 运行 OpenWRT 18.06.1。
问题最初出现在 1-2 个月前,当时我使用的是 OpenWRT 15.05,而路由器上的最后一次配置更改(升级到 18.06.1 之前)大约是在一年前。
因此,1-2 个月前我注意到有些网站无法在所有设备(搭载 iOS 系统的 iPhone、Android 手机、Ubuntu 笔记本电脑、Windows 笔记本电脑)的所有浏览器上加载。但是,如果设备断开 WiFi 连接并使用蜂窝网络等,则网站会立即加载。
我的 ISP 是德国电信,无法加载的网站的典型示例是https://telekom.de,通常预计是可以达到的。
我已经升级到最新的稳定版 OpenWRT,并开始调查该问题。日志中没有丢包,路由器上也没有与该问题相关的任何其他错误消息。Curl 能够直接在路由器上获取一个受影响网站(telekom.de)的内容:
root@OpenWrt:~# curl --tlsv1.0 -v https://telekom.de
> GET / HTTP/1.1
> Host: telekom.de
> User-Agent: curl/7.60.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Sat, 01 Sep 2018 20:56:23 GMT
< Server: Apache
< Location: https://www.telekom.de/start
< Content-Length: 236
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://www.telekom.de/start">here</a>.</p>
</body></html>
在所有客户端上它仍然不起作用:
$ curl --tlsv1.0 -v https://telekom.de
* Rebuilt URL to: https://telekom.de/
* Hostname was NOT found in DNS cache
* Trying 46.29.100.76...
* Connected to telekom.de (46.29.100.76) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to telekom.de:443
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to telekom.de:443
我尝试将 Windows 笔记本电脑直接连接到德国电信的 PPPoE 光纤调制解调器,网站开始正常加载。我还将 Windows 笔记本电脑变成了 WiFi 路由器,所有客户端都能够加载有问题的网站。
我最初的想法是可能与 IPv6 有关(另一个可能相关的问题是这里),并且我已经配置了它(之前配置不正确)。但这没有帮助,并且在 Windows 客户端的适配器设置中禁用 IPv6 也无济于事。
当使用 OpenWRT 作为路由器时,浏览器会尝试执行 TLS 握手一段时间(1-2 分钟),然后显示“安全连接失败”消息。
以下是 Wireshark 捕获的 telekom.de TLS 握手信息。
以下是我的一些路由器设置:
界面截图:
输出iptables -L -v(我不使用标准的 OpenWRT 防火墙配置,因为它包含很多链,对我来说太复杂了,所以我在启动时通过 iptables-restore 命令重写它):
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
5651 481K ACCEPT all -- lo any anywhere anywhere
137K 17M ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
184 10370 logdrop all -- any any anywhere anywhere ctstate INVALID
0 0 ACCEPT udp -- pppoe-wan any anywhere anywhere udp dpt:bootpc
0 0 ACCEPT udp -- l2tp-voip any anywhere anywhere udp dpt:bootpc
67318 4219K ACCEPT all -- br-lan any anywhere anywhere
5423 290K logdrop all -- any any anywhere anywhere
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
423K 49M ACCEPT all -- br-lan pppoe-wan anywhere anywhere
0 0 ACCEPT all -- br-lan l2tp-voip anywhere anywhere
0 0 ACCEPT all -- br-lan br-lan anywhere anywhere
1324K 1610M ACCEPT all -- pppoe-wan br-lan anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- l2tp-voip br-lan anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 logdrop all -- any any anywhere anywhere
Chain OUTPUT (policy ACCEPT 188K packets, 25M bytes)
pkts bytes target prot opt in out source destination
Chain logdrop (3 references)
pkts bytes target prot opt in out source destination
5607 300K LOG all -- any any anywhere anywhere LOG level warning prefix "dropped: "
5607 300K DROP all -- any any anywhere anywhere
输出iptables -t nat -L -v:
Chain PREROUTING (policy ACCEPT 59800 packets, 4849K bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 39692 packets, 2880K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 29226 packets, 2171K bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 2123 packets, 232K bytes)
pkts bytes target prot opt in out source destination
35523 2660K MASQUERADE all -- any pppoe-wan anywhere anywhere
2 1098 MASQUERADE all -- any l2tp-voip anywhere anywhere
/etc/config/network 的内容:
cat /etc/config/network
config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'xxxx:xxxx:xxxx:xxxx::/64'
config interface 'lan'
option ifname 'eth0.1'
option type 'bridge'
option proto 'static'
option ipaddr '192.168.x.x'
option netmask '255.255.255.0'
option ip6addr 'xxxx:xxxx:xxxx:xxxx::1/64'
config interface 'wan'
option proto 'pppoe'
option password 'yyyyyyyy'
option ifname 'eth0.7'
option username '[email protected]'
option ipv6 '1'
config interface 'wan6'
option ifname '@wan'
option proto 'dhcpv6'
option reqprefix 'auto'
option reqaddress 'try'
config switch
option name 'switch0'
option reset '1'
option enable_vlan '1'
config switch_vlan
option device 'switch0'
option vlan '1'
option vid '1'
option ports '0t 2 3 4 5'
config switch_vlan
option device 'switch0'
option vlan '3'
option vid '7'
option ports '0t 1t'
config interface 'voip'
option proto 'l2tp'
option server 'ooo.ooo.ooo.ooo'
option username 'xxxxxxxxxxx'
option password 'xxxxxxxxxxx'
option defaultroute '0'
option peerdns '0'
option delegate '0'
option ipv6 '0'
config route
option interface 'voip'
option target 'xxxxxxxxxxxxxxx'
option netmask 'xxxxxxxxxxx'
option gateway 'xxxxxxxxxx'
造成此问题的原因是什么?
更新:遵循以下建议类似问题,我尝试为 pppoe-wan 设置不同的 MTU(1400,1476,1480)(ifconfig pppoe-wan mtu xxxx)很遗憾,这并没有起到什么帮助作用。
更新 2: 在 ubuntuforums.org 上,通过重新安装 Ubuntu 解决了类似的问题。我刚刚尝试重新刷新 OpenWRT(以下https://openwrt.org/toh/tp-link/tl-wdr4300#flash_overwrite;然后我应用了我的配置)。不幸的是,它没有帮助。
答案1
这似乎是 MTU 和碎片的问题。以太网 MTU 为 1500,而 PPPoE MTU 为 (1500-8) = 1492。
仅在路由器上设置 MTU 是没有用的。您可以减少传出数据包中的 MSS 大小。
将此规则添加到iptables
,假设ppp0
是您的 PPPoE 接口:
-A FORWARD -o ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
另一种方法是固定大小:
-A FORWARD -o ppp0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1400
答案2
正如 RalfFriedl 所写,这确实是 MTU 问题。但是,简单地更改 MTU 并没有帮助。PPPoE 的 MTU 总是小于以太网,例如以太网 MTU 1488 --> PPPoverEthernet MTU 1480。不知何故,即使路由器知道 PPPoE 的正确 MTU,并且如果连接是由路由器本身发起的,它将正常工作,所有客户端计算机仍将发送 MTU 为 1500 的数据包,并且 iptables 需要知道在转发数据包时需要调整 MTU。
以下是该问题的详细描述:现在是 2017 年了 — 为什么我还要关心 MTU?
默认情况下,OpenWRT 有一个特殊选项来缓解此问题:
然而,即使使用非标准的 iptables 规则,也可以轻松修复此问题在 iptables 中使用 --set-mss 选项
重点是这个 mss 夹紧规则应该位于 FORWARD 规则的开头,避免数据包被其他规则先捕获(例如,conntrack规则等)
就我而言,这是第一条规则:
-A FORWARD -i br-lan -o pppoe-wan -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu