本文目录导读:

在 QuickQ(或其他基于 Linux 内核的 VPN 实现)中使用 WireGuard 时,TSO(TCP 分段卸载) 和 GRO(通用接收卸载) 通常会导致冲突并引发连接问题,尤其是在物理接口和虚拟接口(如 wg0)之间数据包处理异常时。
为什么会产生冲突?
- 数据包大小与加密机制:WireGuard 对每个数据包进行加密和封装,TSO/GRO 会尝试合并或分段数据包,但 WireGuard 期望处理的是 完整的、未合并的 MTU 大小数据包,TSO 将大包分片或 GRO 合并小包,会导致加密后的数据包超出 MTU 或被错误重组。
- 硬件卸载与虚拟接口不兼容:TSO/GRO 是物理网卡的硬件卸载功能,而 WireGuard 是一个虚拟网络接口,当物理网卡执行 TSO/GRO 后再交给 WireGuard 时,容易引发 校验和错误 或 数据包损坏。
- MTU 问题:WireGuard 默认 MTU 为 1420(部分实现为 1420-1500),如果物理网卡 TSO 产生大于隧道 MTU 的数据包,会导致分片或丢包。
典型症状
- 连接建立后,大文件传输缓慢、断流或超时
- 小数据包(如 SSH、ping)正常,但 HTTP 下载失败
tcpdump显示大量重传、校验和错误- WireGuard 日志中频繁出现
packet too big或segmentation fault
解决方案
关闭物理网卡的 TSO/GRO(推荐)
在宿主机的物理网卡上关闭这些卸载功能:
# 查看当前状态 ethtool -k eth0 | grep -E "tcp-segmentation-offload|generic-receive-offload" # 临时关闭(重启失效) ethtool -K eth0 tso off ethtool -K eth0 gro off # 永久关闭(写入配置文件) # vim /etc/network/interfaces 或 systemd network 配置中添加 ethtool 命令
关闭 WireGuard 接口的 TSO/GRO
在 WireGuard 接口上直接关闭(如果内核支持):
# 对于 wg0 接口 ethtool -K wg0 tx-udp_tnl-segmentation off # 或更通用的 ethtool -K wg0 tso off gro off
调整 MTU
将物理网卡或 WireGuard 接口的 MTU 设为更低的值(如 1400)以避免分片问题:
ip link set dev wg0 mtu 1400
使用内核参数抑制(较不常用)
调整网络栈参数,减少 GRO 的合并行为:
sysctl -w net.core.gro_normal_batch=1
如何验证冲突是否解决?
- 测试传输大文件(如 scp 或 iperf3),观察是否稳定
- 监控错误计数:
ip -s link show wg0 # 查看 RX/TX errors/dropped
- 抓包对比:在 WireGuard 接口两端抓包,检查数据包大小是否在 MTU 范围内且无异常分片
特别注意
- 某些云服务(如 AWS、GCP)的虚拟化环境中,可能无法直接操作物理网卡的卸载设置,此时建议在 QuickQ 的配置文件中添加关闭 TSO/GRO 的脚本(如
post-uphook)。 - 部分较新的 Linux 内核(5.10+)对 WireGuard 的 TSO/GRO 支持有所改进,但依然建议主动关闭以避免不可预测的问题。
虽然理论上 Linux 内核的新版本已针对 WireGuard 优化了 TSO/GRO 的兼容性,但在生产环境中,主动关闭物理网卡的 TSO/GRO 是解决 WireGuard 连接问题的最可靠手段。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。