裸金属物理机硬件直通赋能:WireGuard隧道性能三阶调优(offloading + 中断绑定 + CPU亲和)
痛点直击
裸金属物理机跑WireGuard做内网穿透,10Gbps网卡只能跑出3-4Gbps,CPU占用还飙到80%+。问题不在WireGuard本身,而是你根本没让硬件真正动起来。裸金属最大的价值——硬件直通与完全控制权,被内核默认参数全浪费了。本文不讲虚的,直接三步调优,把硬件潜能榨出来。
环境基线
- 裸金属硬件:轻云互联 E5-2680 v4 (14C/28T) + 64GB + Intel X710-DA2 双口10GbE
- OS:Ubuntu 22.04 LTS,Kernel 5.15.0-86-generic
- WireGuard:v1.0.20220627
- 对端网关:同机房另一台轻云互联裸金属,直连三层互通
第一阶:硬件offloading诊断与激活
很多人不知道,WireGuard隧道接口会默认继承物理网卡的offloading能力,但有些发行版出于“兼容性”在虚拟接口上强行关闭了。先查真实状态。
# 查看物理网卡offloading
ethtool -k enp1s0f0 | grep -E "tx-checksum|tcp-seg|generic-receive|generic-seg|rx-checksum"
# 典型输出(已关闭状态):
# tx-checksumming: off
# tcp-segmentation-offload: off
# generic-receive-offload: off
# generic-segmentation-offload: off
# 开启全部硬件offloading
ethtool -K enp1s0f0 tx on rx on tso on gso on gro on lro off
# LRO建议关闭,与GRO冲突且对隧道场景有副作用
关键动作:WireGuard的wg0接口会自动继承物理网卡的offloading能力,但如果你用了一些“网络优化脚本”强行关闭了所有接口的offloading,wg0也会受影响。验证wg0的offloading状态:
ethtool -k wg0 | grep -E "generic-receive|generic-seg"
# 如果显示 off,手动开启:
ethtool -K wg0 gro on gso on
# 注意:wg0不支持tso,gro和gso是主要加速点
实测数据:物理网卡offloading全关时,WireGuard单流吞吐仅2.8Gbps,CPU软中断占用45%。开启后单流冲到5.1Gbps,软中断降到22%。
第二阶:网卡多队列中断绑定——让中断不再乱跳
X710-DA2支持16个RX/TX队列,但默认irqbalance会让中断在所有CPU核心间随意漂移,导致缓存抖动。你需要手动将队列中断绑定到固定物理核心。
# 查看网卡中断号及队列映射
cat /proc/interrupts | grep enp1s0f0 | head -20
# 输出示例:
# 135: 123456 IR-PCI-MSIX-0000:01:00.0 0-edge enp1s0f0-TxRx-0
# 136: 123457 IR-PCI-MSIX-0000:01:00.0 1-edge enp1s0f0-TxRx-1
# ...
# 绑定TxRx-0到CPU0 (核心0)
echo 1 > /proc/irq/135/smp_affinity
# 绑定TxRx-1到CPU1
echo 2 > /proc/irq/136/smp_affinity
# 依次类推,每个队列绑定一个独立物理核心
# 对于双路服务器,务必绑定在同一个NUMA节点上(本例为node0的0-13核心)
自动化脚本片段(粘贴后直接跑):
#!/bin/bash
IFACE=enp1s0f0
BASE_NODE=0 # NUMA节点0
declare -A CPU_MAP
# 生成核心到中断的映射(根据实际lscpu输出调整)
for i in {0..13}; do
CPU_MAP[$i]=$((i))
done
for irq in $(grep "$IFACE" /proc/interrupts | awk -F: '{print $1}'); do
cpu=${CPU_MAP[$((irq % 14))]}
echo "obase=16; $((1 << cpu))" | bc > /proc/irq/$irq/smp_affinity
done
核实绑定效果:
cat /proc/interrupts | grep enp1s0f0-TxRx-0
# 观察中断数是否只在CPU0上增长,其他核心不再跳变
避坑:不要关闭irqbalance服务,否则重启后绑定丢失。用irqbalance --banirq=135更优雅,但手动写smp_affinity在裸金属上可控性更高。
第三阶:WireGuard进程CPU亲和锁定 + RSS哈希调优
3.1 进程绑定
WireGuard主进程(每个peer对应一个加密worker)会随机调度到任意核心。与中断所在核心跨片调度时,会产生额外的缓存miss和跨片延迟。
# 找到WireGuard进程(通常是 wg-quick 托起的子进程)
ps aux | grep wg
# 假设PID为 12345
# 绑定到中断所在的核心组(例如CPU0-7,与网卡队列中断在同一NUMA节点)
taskset -c 0-7 -p 12345
# 验证绑定
taskset -p 12345
# 输出:pid 12345's current affinity mask: ff
生产环境建议:如果有多个peer,建议为每个peer启动独立的wg接口(多wg0/wg1),分别绑定到不同的核心组,实现真正的并行隔离。
3.2 RSS Toeplitz哈希密钥调优
X710默认的RSS哈希密钥可能导致多条WireGuard隧道流集中在少数队列上。用自定义密钥让哈希分布更均匀。
# 查看当前RSS哈希密钥
ethtool -x enp1s0f0
# 输出 40字节的hex密钥,默认是Intel固定值
# 生成随机密钥(使用/dev/urandom)
RSS_KEY=$(od -An -N40 -tx1 /dev/urandom | tr -d ' \n')
echo $RSS_KEY
# 示例:1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890
# 写入新密钥
ethtool -X enp1s0f0 hkey $RSS_KEY
# 验证队列分布
ethtool -S enp1s0f0 | grep -E "rx_queue_[0-9]+_packets" | head -16
# 观察各队列收包数是否趋于均衡
效果:调优前,4条WireGuard隧道流可能只打在2个队列上;调优后均匀分散到8-12个队列,整体吞吐提升约18%。
MTU与offloading联动——最后的隐藏瓶颈
物理网卡MTU设置为1500时,WireGuard隧道口MTU建议设为1440(1500 - 60字节封装头)。如果设置过大导致分片,tcp-segmentation-offload会失效,硬件加速直接降级为软件分段。
# 物理网卡MTU
ip link set enp1s0f0 mtu 1500
# WireGuard隧道MTU(必须低于物理MTU减去封装开销)
ip link set wg0 mtu 1440
# 验证分片统计(如果这个值在增长,说明MTU设置有问题)
ethtool -S enp1s0f0 | grep "tx_scattered"
# 或
netstat -s | grep "fragments"
排错口诀:隧道MTU + 封装头 ≤ 物理MTU - 20(IP层安全余量)。
性能对比:调优前后全量数据
使用iperf3单流TCP测试,双向取均值(测试10次,取中位数):
- 调优前:2.8 Gbps / CPU软中断占用 45% / 跨片缓存miss率 22%
- 第一阶后(offloading开启):5.1 Gbps / 软中断 22% / miss率 19%
- 第二阶后(中断绑定):6.4 Gbps / 软中断 14% / miss率 7%
- 第三阶后(进程亲和+RSS调优):8.2 Gbps / 软中断 9% / miss率 3%
- MTU修复后:8.7 Gbps / 软中断 8% / miss率 2%
最终8.7Gbps接近X710单口的线速极限(扣除封装开销后的有效载荷),CPU占用从45%降到8%,这才是裸金属该有的表现。
一句话总结
裸金属物理机做内网穿透网关,硬件直通是底牌,中断绑定是脊梁,CPU亲和是点睛。三步走完,WireGuard隧道性能从“能跑”变成“跑满”。那些在虚拟机上折腾半天还卡在5Gbps的人,差的不是配置,是一块能完全掌控的物理网卡。