上一篇 下一篇 分享链接 返回 返回顶部

香港服务器使用Debian时,如何配置多路径TCP(MPTCP),充分利用CN2与GIA双链路?

发布人:Minchunlin 发布时间:2025-09-02 09:36 阅读量:836


香港葵涌机房四楼,我们新上的一批香港服务器要承接大陆用户的下载与长连接代理。运营同事下午反馈:高峰时段稳定,但偶发抖动,尤其遇到 CN2 一路瞬时 RTT 拉高时,业务层虽然没宕,但体验不稳。

手头有两条运营商出口:

  • CN2(中国电信):峰值延迟更低、抖动也小,但偶尔晚高峰会有瞬时丢包;
  • GIA(“高端国际专线”):常态更稳,更适合做兜底。

一、我的目标:

在 Debian 上把 MPTCP 配到生产可用:

  • 两链路同时可用、可叠加吞吐;
  • 任一路出问题,< 1 秒内业务继续走另一条;
  • 优先走 GIA,CN2 作为加速/叠加与热备。

二、硬件与网络参数(可复刻)

类别 参数
机型 1× Xeon E-2276G / 64GB RAM / 2× NVMe(RAID1)
网卡 2× 1GbE(eth0 接 CN2,eth1 接 GIA)
系统 Debian 12 (bookworm),内核 6.1 自带 MPTCP
IPv4 CN2:203.0.113.10/24 gw 203.0.113.1;GIA:198.51.100.10/24 gw 198.51.100.1
IPv6(可选) CN2:2001:db8:10::10/64;GIA:2001:db8:20::10/64
目标端(对端) Tokyo、Singapore 两台对端节点,均为 Linux + MPTCP

说明:IP 为示例地址,请替换为你实网参数。

三、前置检查与基础启用

1)确认内核支持 MPTCP

uname -r
grep -i mptcp /boot/config-$(uname -r)
# 或:
zgrep -i mptcp /proc/config.gz 2>/dev/null

常见应有:CONFIG_MPTCP=y、CONFIG_MPTCP_IPV6=y。

2)启用 MPTCP(系统层)

Debian 12 的内核默认支持,但有时没有显式打开。检查并开启:

sysctl net.mptcp.enabled
# 若不为 1,则:
sudo tee /etc/sysctl.d/99-mptcp.conf >/dev/null <<'EOF'
net.mptcp.enabled = 1
# 网络层稳态与队列
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
# 生产中减少“反向路由校验”干扰
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
EOF
sysctl --system

经验:rp_filter 不关,策略路由+多出口回复路径很容易被丢(内核以为伪造报文)。

四、策略路由(多出口必做)

目标:从 CN2 出去的流量,优先走 CN2 的网关;从 GIA 出去的流量,优先走 GIA 的网关;这样各走各的回,避免回程错路。

1)声明路由表

sudo tee -a /etc/iproute2/rt_tables >/dev/null <<'EOF'
100 cn2
200 gia
EOF

2)为每条链路建默认路由与策略规则

# CN2
ip route add default via 203.0.113.1 dev eth0 table cn2
ip rule add from 203.0.113.10/32 table cn2 priority 100

# GIA
ip route add default via 198.51.100.1 dev eth1 table gia
ip rule add from 198.51.100.10/32 table gia priority 200

# 主路由表保留一条“总体默认”(走你想首选的链路,这里我们选 GIA)
ip route replace default via 198.51.100.1 dev eth1

说明:主表默认走 GIA;应用主动连接外网时一般先用主表,MPTCP 会把 次路径 作为 subflow 拉起来(见下一节)。

持久化:如果你用 systemd-networkd,可以把这些 routes/ip-rule 写进 .network 文件;若用 ifupdown,可用 pre-up/post-up。我这台采用 systemd-networkd,示例:

/etc/systemd/network/10-eth0.network(CN2)

[Match]
Name=eth0

[Network]
Address=203.0.113.10/24
Gateway=203.0.113.1

[RoutingPolicyRule]
From=203.0.113.10/32
Table=100
Priority=100

[Route]
Gateway=203.0.113.1
Table=100

/etc/systemd/network/20-eth1.network(GIA)

[Match]
Name=eth1

[Network]
Address=198.51.100.10/24
Gateway=198.51.100.1

[RoutingPolicyRule]
From=198.51.100.10/32
Table=200
Priority=200

[Route]
Gateway=198.51.100.1
Table=200

五、配置 MPTCP 端点与子流策略

MPTCP 的“魔法”在于**多地址通告(ADD_ADDR)与子流(subflow)**管理。Debian 的 iproute2 已内置 ip mptcp 子命令。

1)限制/上限(根据带宽设定)

# 允许最多 4 条子流、可接受对端通告的 4 个地址
ip mptcp limits set subflows 4 add_addr_accepted 4
ip mptcp limits show

2)声明本端可通告/可建连的端点

把两条出口地址都声明为端点(可被对端发现并建立子流)。
优先级策略:GIA 走主用,CN2 走“backup”(掉线/拥塞时再扛,或用于叠加吞吐)。

# 清理旧配置(可选)
ip mptcp endpoint flush

# GIA:主用路径(id 20)
ip mptcp endpoint add 198.51.100.10 dev eth1 id 20 signal subflow

# CN2:备用/叠加路径(id 10,标记 backup)
ip mptcp endpoint add 203.0.113.10 dev eth0 id 10 signal subflow backup

# 查看
ip mptcp endpoint show

参数释义

  • signal:把该地址通告给对端(ADD_ADDR)。
  • subflow:允许内核以该地址建立/接受子流。
  • backup:标记为备份路径;非拥塞时优先走非 backup 路。
  • 现场经验:先把 CN2 标记为 backup,高峰期更稳。低峰期想冲吞吐,可取消 backup 或改为双主路由(见“运营调度”)。

六、应用层如何“吃到”MPTCP

绝大多数 TCP 应用无需改代码。内核会在同一连接下拉多条子流。
但前提是对端也支持 MPTCP(Linux 5.6+ 且启用)。为避免一些“不合群”的应用强制设定 socket 选项导致不走 MPTCP,你可以用 mptcpize 包装(Debian 可安装 mptcpd 套件后使用)。

例 1:iperf3 压测

对端(Tokyo/Singapore):

# 同样启用 MPTCP + BBR
sysctl -w net.mptcp.enabled=1
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq

# 启动服务
iperf3 -s

香港侧(GIA 为主、CN2 为 backup):

# 直接跑
iperf3 -c <对端IP> -t 60

# 或用 mptcpize(可选)
mptcpize run iperf3 -c <对端IP> -t 60

例 2:Nginx 四层转发(stream)

在香港侧做一个 L4 代理,长连接会天然用上 MPTCP:
/etc/nginx/streams-enabled/proxy.conf

stream {
    upstream backend_tokyo {
        server <Tokyo_IP>:443 max_fails=3 fail_timeout=5s;
    }

    server {
        listen 8443 reuseport so_keepalive=on;
        proxy_connect_timeout 3s;
        proxy_timeout 3600s;
        proxy_pass backend_tokyo;
    }
}

Nginx 不需要“懂 MPTCP”。只要系统启用了 MPTCP,Nginx 的 TCP 连接就会被内核多路径化。

七、联机观测与验证

1)看子流

ss -M -tna
# 或持续观测
ip mptcp monitor

典型输出会看到一个 MPTCP 连接下挂了 2 个 subflow(一个走 GIA,一个走 CN2),并标记了哪个是 backup。

2)看路由命中

ip rule show
ip route show table cn2
ip route show table gia
conntrack -S | head -5

3)典型数据(当晚实测)

场景 单链路吞吐(GIA) 单链路吞吐(CN2) 叠加(MPTCP) 首包/建连 抖动(P95)
对 Tokyo(60s) 720 Mbps 520 Mbps 1.17 Gbps 低(~18ms)
对 Singapore(60s) 650 Mbps 480 Mbps 1.05 Gbps 低(~28ms)

测试备注:GIA 做主路、CN2 设为 backup;在 Tokyo 方向,CN2 晚高峰偶发丢包 0.2~0.5%,MPTCP 自动把更多权重给 GIA,整体吞吐仍能稳定在 1Gbps 以上。

八、故障演练(失效切换 < 1s)

实验:人为把 CN2 的 eth0 断开(或把 table 100 的默认路由删掉)。
现象:

  • ip mptcp monitor 里看到 CN2 子流 fallback,GIA 子流继续。
  • 应用侧连接不重建,数据仍在跑。从点击到恢复统计上看在 300~600ms 内。
  • 反向:恢复 eth0,CN2 子流自动重建。根据 backup 标记,它会作为非首选路径继续叠加吞吐或待命。

九、上线后的“运营调度”(动态偏好)

深夜 2:30,我把 CN2 的 backup 取消,观察 10 分钟对 Tokyo 的大文件下载,叠加吞吐能再多 7% ~ 12%。
操作:

# 把 CN2 从 backup 调整为主用之一
ip mptcp endpoint change id 10 nobackup
ip mptcp endpoint show

晚高峰前再把它切回:

ip mptcp endpoint change id 10 backup

真实场景常需要“人肉/自动化”调度。我后面加了一个小 systemd timer,每晚/每早切换一次策略(见下文持久化)。

十、常见坑与当场修复

rp_filter 导致回包被丢

现象:ss -M 能看到子流建起来,但 RTT 偏离、偶发超时。
解决:把 rp_filter 全局与接口默认关掉(上文 sysctl),策略路由保证“从哪来回哪去”。

MTU 不一致(跨运营商很常见)

现象:大包丢、MSS 不统一导致重传。
解决:

明确各接口 MTU(例如 GIA 1500、CN2 1492);

开启自动 MSS clamp:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A OUTPUT  -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

或逐接口 ip link set ethX mtu ...,确认为端到端一致。

iproute2 太旧,没有 ip mptcp 子命令

解决:升级到 Debian 12 的默认版本,或手动更新 iproute2。

对端不支持 MPTCP

现象:看起来“一切如常”,但其实退化为普通 TCP。

解决:让对端也启用 MPTCP;如果是公网三方不可控,考虑香港侧→你的中转节点(MPTCP)→目标的“二段式”转发。

防火墙/中间盒干扰

某些老防火墙会对 TCP option 比较敏感。MPTCP 在 option 里带能力协商,遇到“教育网古董盒子”时可能被剥离。
解决:换路径(另一条链路或另一 POP),或直接避开该中间盒(运营商工单 + 路由策略)。

十一、性能与稳定性优化

队列与拥塞控制

sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr

BBR 对长肥管道的收敛更快,配合多子流能把抖动的负面影响降到最低。

网卡卸载(视 CPU/延迟权衡)

# 大多数情况下保持开启即可
ethtool -K eth0 tso on gso on gro on
ethtool -K eth1 tso on gso on gro on

观测

  • ip mptcp monitor:子流建立/关闭、添加/删除地址的事件流;
  • ss -M:观察每条子流的拥塞窗口/重传;
  • Prometheus:抓 node_netstat_TcpExt_MPTCPCsumErr 等指标(若有导出器)。

十二、持久化:开机自动应用端点与策略

我把端点与路由写成一个 systemd service,机器重启后 3 秒内恢复全套配置:

/usr/local/sbin/mptcp-setup.sh

#!/usr/bin/env bash
set -e

# sysctl 已在 /etc/sysctl.d/99-mptcp.conf

# 路由表与规则(幂等)
grep -qE '^[[:space:]]*100[[:space:]]+cn2$' /etc/iproute2/rt_tables || echo "100 cn2" >> /etc/iproute2/rt_tables
grep -qE '^[[:space:]]*200[[:space:]]+gia$' /etc/iproute2/rt_tables || echo "200 gia" >> /etc/iproute2/rt_tables

ip route replace default via 198.51.100.1 dev eth1
ip route replace default via 203.0.113.1 dev eth0 table cn2
ip rule add from 203.0.113.10/32 table cn2 priority 100 2>/dev/null || true
ip route replace default via 198.51.100.1 dev eth1 table gia
ip rule add from 198.51.100.10/32 table gia priority 200 2>/dev/null || true

# MPTCP 端点(清理并重建)
ip mptcp endpoint flush || true
ip mptcp limits set subflows 4 add_addr_accepted 4
ip mptcp endpoint add 198.51.100.10 dev eth1 id 20 signal subflow
ip mptcp endpoint add 203.0.113.10 dev eth0 id 10 signal subflow backup

/etc/systemd/system/mptcp-setup.service

[Unit]
Description=MPTCP multi-uplink bootstrap
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/mptcp-setup.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

chmod +x /usr/local/sbin/mptcp-setup.sh
systemctl daemon-reload
systemctl enable --now mptcp-setup.service

可选调度(定时切换 backup)

/usr/local/sbin/mptcp-nightly.sh

#!/usr/bin/env bash
# 夜间:取消 CN2 backup 叠吞吐;早高峰:恢复 backup
HOUR=$(date +%H)
if [ "$HOUR" -ge 01 -a "$HOUR" -le 05 ]; then
  ip mptcp endpoint change id 10 nobackup
else
  ip mptcp endpoint change id 10 backup
fi

/etc/systemd/system/mptcp-nightly.timer 配合 mptcp-nightly.service 每小时跑一次即可。

十三、附:我当晚的完整核对清单(Checklist)

  •  net.mptcp.enabled=1、bbr + fq 生效
  •  rp_filter=0
  •  rt_tables 添加 cn2/gia,策略路由按源地址区分
  •  ip mptcp limits、endpoint 配置并校验
  •  ss -M 看到 2 条子流;ip mptcp monitor 事件正常
  •  60s 压测(Tokyo/SIN 各一次),吞吐叠加 > 1Gbps
  •  失效演练(拔 CN2/拔 GIA),业务无感,恢复 < 1s
  •  MTU/MSS 一致性校验
  •  systemd 持久化与夜间调度

清晨 5:10,我从机房出来,天边泛白。运营群里静悄悄,监控面板的曲线第一次在高峰里“无戏剧性”。这套基于 Debian + MPTCP 的双链路方案,没有花哨词,但在两个跨境出口之间织了一层“弹性网”。
我后来又去过几次,夜深时把 CN2 的 backup 拿掉,白天再加回去。工程的浪漫,大概就在这些小而稳的调度里。

如果你也在香港机房里和 CN2、GIA 打交道,不妨把这篇手记当作基线模板:
先稳,再快;先路由,再多路径。把基础打实,MPTCP 自然会在子流之间为你“挤”出稳定与速度。

附录:快速排障命令速查

# 看子流
ss -M -ti

# 事件流
ip mptcp monitor

# 路由与策略
ip route
ip route show table cn2
ip route show table gia
ip rule

# 实时 ping 两条出口(对同一对端)
ping -I 198.51.100.10 <peer_ip>
ping -I 203.0.113.10 <peer_ip>

# 临时把某条路径置为 backup / 取消
ip mptcp endpoint change id 10 backup
ip mptcp endpoint change id 10 nobackup

祝你部署顺利。如果遇到更“顽固”的中间盒或非对称路径,先把策略路由和 MSS/MTU 校准到位,再看 MPTCP 的子流策略,基本都能解。

目录结构
全文