OpenWrt中的MSS钳制是干什么用的
前记——首先还是挺遗憾的,正式入职的时候被调到了别的组,关于网络的知识不得不说dog250赵亚大佬的博客,从高中开始就一直帮助过我解决过很多问题,甚至后来才发现hostloc论坛十分流行的魔改版BBR就是出自大佬之手。实习的时候一直没有和赵亚大佬仔细聊聊,本想着正式入职再简单介绍自己,但是万万没想到调去了别的部门,不过有幸实习的时候组会有过一些讨论,也算是共事过了。
老早之前就看到OpenWrt防火墙中的MSS钳制
选项,一直没有过多思考其作用,可以在防火墙
->wan
->常规设置
中找到,wan
区域中该选项默认是开启的,其他区域默认没有。这里以发现问题->解决问题的思路来探讨这个选项的意义及作用。
MTU问题
这个问题很常见,当Don't Fragment
标志被设置在IPv4头中,且IP数据包大小超过接口MTU时,就会因为无法分片而被丢弃。典型的状况就是,DNS解析正常、可以ping通目标、HTTP访问正常、部分网站HTTPS异常。这是由于TLS握手时服务端会响应一个包含证书的远超MTU大小的数据包,该包很大程度上(当服务端发出时就被设置了DF标志)会被丢弃,导致HTTP网站无法打开,Wireshark
可以观察到TCP previous segment not captured
消息。
这次碰到的情况的简易网络拓扑可以如下显示:
1 |
PC <---> (LAN) OpenWrt (Wireguard) <---> (Wireguard) Server (WAN) |
可以确信各自的MTU都合法,网络通信均正常,但是仍旧发生了MTU问题。在PC和Server处进行抓包,可以观察到PC->Server的TCP第一次握手的MSS值为1460,Server->PC的TCP第二次握手的MSS值为1436,显然TCP数据段在经过Wireguard隧道的时候,PMTU(路径MTU发现)机制没有正常工作,导致过大的数据包被丢弃。接下来是思考和解决的过程:
- 再次检查Wireguard两端的MTU配置,均正常
- 怀疑OpenWrt路由表的配置,该路由条目为手动添加,怀疑MTU错误,发现路由默认MTU即为接口MTU,正常
- 怀疑nftable出现了问题,因为该路由是通过规则来决定使用的,即对于某些数据包设置标记0x8888,然后添加一个规则,有0x8888标记的数据包使用0x8888号路由表
- 尝试在设置0x8888标记时,强制缩小TCP的MSS值,这个专业术语叫做
TCP MSS Clamping
,看到Clamping这个单词还有点陌生,一查夹紧的意思,顿时恍然大悟,这不就是TCP钳制
的意思 - 所以只要将Wireguard接口对应区域的
TCP钳制
选项打上勾,这个问题便迎刃而解,握手时MSS值将会被缩小到1360(1400-IP头-TCP头),从而可以顺利通过Wireguard隧道
TCP钳制
用白话文概括一下:这个选项就是在TCP三次握手的时候,将MSS值匹配至接口的MTU值。这个选项理应默认就打开,不知为何默认是关闭的状态,因为会产生性能消耗?或者说会使硬件NAT机制失效?话说回来一般家庭网络情况也较为简单,WAN
区域的TCP钳制
选项打开即可应对大多数情况。