本文仅介绍F-Stack服务器作为被动接受连接的一方如何在不修改程序的前提下如何相对简单的修改TCP建连时的MSS选项
TCP数据包在经过某些网络设备(如负载均衡等)时可能会被增加某些头(如vlan、gre、ipip等),但是又没有正确的减小syn包中MSS选项的值,导致后续的数据包加上额外的头后可能超过1500的MTU而无法正常收发包,此时我们可能无法控制中间链路的网络设备,就需要修改应用服务器的MSS配置,但最好上还是应该由中间网络设备进行兼容。
F-Stack-1.21.5(FreeBSD-11.0)
FreeBSD-11.0的ipfw工具不支持直接修改tcp的mss选项的值,必须要同时借助netgraph(工具:ngctl)来实现,参考命令如下
# 创建 tcpmss 节点并将其连接到 ng_ipfw 节点
ff_ngctl mkpeer ipfw: tcpmss 100 msshook
# 设置mss和hook函数
# 该命令会报错ff_ngctl: recv incoming message: Operation not permitted,实际为回显结果时f-stack的ff_ngctl对freesbd的ngctl的一个兼容性问题,不影响设置效果,仅影响设置成功后的回显
ff_ngctl msg ipfw:100 config '{ inHook="msshook" outHook="msshook" maxMSS=1440 }'
# 将流量导入 tcpmss 节点
ff_ipfw add 300 netgraph 100 tcp from any to any tcpflags syn out via f-stack-0
# 让数据包在被修改后继续由 ipfw 处理, 可选,也可以配置在config.ini
ff_sysctl net.inet.ip.fw.one_pass=0
F-Stack-1.22+(FreeBSD-13.0)
FreeBSD-13.0的ipfw工具通过pmod模块引入的方式支持了直接修改tcp的mss选项值的功能,命令参考如下:
ff_ipfw add 1000 tcp-setmss 1440 tcp from any to any tcpflags syn out
【注意:】目前除了dev分支最新代码默认支持了ip_fw_pmod模块,其他分支和release版本需要先打上下面这个patch,在F-Stack的ipfw开启ip_fw_pmod模块功能:ff_ipfw support ip_fw_pmod and tcpmod for tcp-setmss.
F-Stack通用方式
因为F-Stack并未实际实现修改网卡MTU的功能,所以可以通过修改用户态FreeBSD协议栈中网卡设备MTU的操作,来达到减小mss选项的值(MTU – 40),但网卡实际的MTU还是1500,并没有减小,从而达到也可以正常收发超过设置的MTU(如1480)大小的包(如1500),但这里借助了F-Stack的feature(不是bug)来实现的,并不建议作为标准方案使用,参考命令如下
ff_ifconfig f-stack-0 mtu 1480
Linux协议栈
linux协议栈对标ipfw,使用iptables修改mss选项值的命令参考
iptables -t mangle -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1440