在长距离、高延迟的线路上(例如东京、首尔或莫斯科的 VPS 服务欧洲或中国大陆用户),单条 TCP 连接的速度往往卡在内核的套接字缓冲区和拥塞控制算法上,而不是 500 Mbps 的端口。本文介绍如何算出这个上限,应用一套安全的 sysctl 配置(更大的 TCP 缓冲区、BBR + fq),排查隧道上的 MTU/MSS 问题,用 iperf3 做前后对比,以及如何完整回滚。
为什么距离会限制单连接速度
TCP 同一时间只能有一定量“已发出但未确认”的数据在路上,这个量就是带宽时延积(BDP):带宽 × 往返时间(RTT)。如果缓冲区允许的窗口小于 BDP,连接就得停下来等确认,端口再快也跑不满。
计算示例:500 Mbps 端口,RTT 为 180 ms。
- BDP = 500,000,000 bit/s × 0.18 s = 90,000,000 bit,约 11.25 MB。
- Linux 常见的默认最大接收缓冲区(
tcp_rmem)为 6 MB,其中一部分还要留作开销。6 MB ÷ 0.18 s 理论上最多约 280 Mbps,实际单连接往往只有 150–200 Mbps。 - 把上限调到 32 MB 后,180 ms 下的理论上限超过 1 Gbps,在 500 Mbps 端口上缓冲区就不再是瓶颈。
丢包会让情况更糟:传统的 CUBIC 算法每遇到一次丢包就大幅降速,在长距离线路上要很久才能恢复。BBR 则根据估算的带宽和 RTT 来发送,对国际线路上偶发的丢包耐受度高得多。RTT 取决于用户所在位置,请用 ping 实测。
关于线路本身:JUSTG 莫斯科机房使用中国电信 CN2 GIA,到中国大陆的路径更干净;东京和首尔使用亚洲优化线路。好的线路能减少丢包和抖动,但 RTT 由物理距离决定,所以无论哪个机房,调优缓冲区都有帮助。
第 1 步:查看当前设置
uname -r
sysctl net.ipv4.tcp_congestion_control net.ipv4.tcp_available_congestion_control
sysctl net.core.default_qdisc net.core.rmem_max net.core.wmem_max
sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem net.ipv4.tcp_mtu_probing
ip -br link
tc qdisc show
记下内核版本、当前拥塞控制算法(通常是 cubic)、默认队列(通常是 fq_codel)、缓冲区数值以及网卡名称(eth0、ens3 等,下文的 eth0 请替换成你的网卡名)。
第 2 步:备份并检查冲突的配置文件
sudo sysctl -a 2>/dev/null | grep -E 'tcp_(rmem|wmem|congestion_control|mtu_probing|notsent_lowat)|core\.(rmem_max|wmem_max|default_qdisc|somaxconn)' | sudo tee /root/sysctl-before.txt
grep -rnE 'congestion|qdisc|rmem|wmem' /etc/sysctl.conf /etc/sysctl.d/ 2>/dev/null
第一条命令把当前数值保存到 /root/sysctl-before.txt,方便以后恢复;第二条列出已经设置了相同参数的其他文件。/etc/sysctl.d/ 下的文件按文件名顺序加载,/etc/sysctl.conf(如果存在)最后加载,那里的旧配置可能会悄悄覆盖你的新文件。请删除或注释掉重复项。
/etc/sysctl.conf,这也是建议把配置放在 /etc/sysctl.d/ 下的原因之一。第 3 步:创建调优配置
sudo tee /etc/sysctl.d/99-network-tuning.conf > /dev/null <<'EOF'
# Queueing discipline and congestion control
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# Socket buffer ceilings (32 MB) for high-RTT paths
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 16384 33554432
# Recover from PMTU black holes
net.ipv4.tcp_mtu_probing = 1
# Keep unsent data in the send buffer small (lower latency)
net.ipv4.tcp_notsent_lowat = 131072
# Larger accept queue for busy services
net.core.somaxconn = 4096
EOF
echo tcp_bbr | sudo tee /etc/modules-load.d/bbr.conf
各部分的作用:
default_qdisc = fq和bbr:拥塞控制使用 BBR,队列使用 fq 做平滑的发包节奏控制。从内核 4.13 起 BBR 不依赖 fq 也能工作,但两者搭配仍是推荐做法。rmem_max/wmem_max与tcp_rmem/tcp_wmem:三个数字分别是每个套接字的最小值、默认值和最大值(字节)。Linux 自动调优只在连接需要时才扩大缓冲区,32 MB 上限不代表每条连接都占用 32 MB。mini 套餐(512 MB 内存)可以改用16777216(16 MB),在 RTT 约 150 ms 以内仍能跑满 500 Mbps。tcp_mtu_probing = 1:内核检测到路径 MTU “黑洞”(大包被悄悄丢弃)时,会为该连接降低包大小,而不是一直卡住。tcp_notsent_lowat:限制套接字里排队等待发送的数据量,在不影响吞吐的前提下降低交互流量和 HTTP/2 的延迟。somaxconn = 4096:连接接受队列上限。内核 5.4 及以上默认已经是 4096,这一行只对老系统有影响,同时也表明配置意图。
最后一行确保开机时先加载 tcp_bbr 模块,再应用 sysctl 参数。
第 4 步:应用并验证
sudo modprobe tcp_bbr
sudo sysctl --system
sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc net.ipv4.tcp_rmem net.ipv4.tcp_wmem
输出中应能看到 bbr、fq 和新的缓冲区数值。修改 default_qdisc 只影响之后新建的队列,现有网卡在重启前仍使用旧队列。如需立即切换:
sudo tc qdisc replace dev eth0 root fq
tc -s qdisc show dev eth0
然后新建一条连接(例如重新打开 SSH 或开始一次下载),用 ss 查看,IP 填对端地址:
ss -tin dst 203.0.113.20
输出会显示每条连接的 bbr、实测 rtt 和当前拥塞窗口。修改之前建立的连接要重新连接后才会使用新设置。
第 5 步:排查并解决 MTU/MSS 问题
MTU 问题的表现和缓冲区太小完全不同,典型症状有:
- ping 和小请求正常,但大文件下载或上传传了几 KB 就卡住;
- SSH 能登录,但命令输出一多就卡死;
- 部分 HTTPS 网站只加载一半或打不开,多见于 VPN、WireGuard、GRE 或 PPPoE 链路。
原因通常是链路上某一段 MTU 小于 1500,而 ICMP “需要分片”消息又被拦截了。用“禁止分片”参数测试:1472 字节数据加 28 字节包头正好是 1500 字节:
ping -c 3 -M do -s 1472 203.0.113.20
ping -c 3 -M do -s 1400 203.0.113.20
tracepath -n 203.0.113.20
ip link show dev eth0
如果 1472 不通而 1400 能通,就逐步调小直到能通,能通的最大值加 28 就是路径 MTU。tracepath 也会显示沿途的 pmtu。不要在防火墙里屏蔽全部 ICMP,路径 MTU 发现依赖它。
如果服务器为其他设备转发流量(WireGuard 或其他 VPN 服务端、GRE 隧道、NAT 网关),请对转发的连接做 TCP MSS 钳制,让两端协商出适合隧道的分段大小。使用 nftables(Debian 12/13 和 Rocky/Alma 9 的默认方案):
sudo tee /etc/nftables-mssfix.nft > /dev/null <<'EOF'
table inet mssfix
delete table inet mssfix
table inet mssfix {
chain forward {
type filter hook forward priority mangle; policy accept;
tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu
}
}
EOF
sudo nft -f /etc/nftables-mssfix.nft
sudo nft list table inet mssfix
这条规则会把 SYN 包里的 MSS 改成与出口路由 MTU 相符的值。Debian/Ubuntu 上要在重启后保留,请在 /etc/nftables.conf 末尾加入 include "/etc/nftables-mssfix.nft",并执行 sudo systemctl enable nftables。Rocky/Alma 如果使用 firewalld,不要另外启用 nftables 服务,请改用下面 WireGuard 的 PostUp 方法。同样的规则用 iptables 写法如下(如未安装请先安装 iptables 软件包):
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
WireGuard 最简单的持久化方式是写进 wg-quick 配置(例如 /etc/wireguard/wg0.conf),规则会随隧道启动和关闭自动添加、删除:
[Interface]
MTU = 1420
PostUp = iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = iptables -t mangle -D FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
1420 是 WireGuard 的默认 MTU,在普通 1500 字节的路径上是安全值。IPv4 下 TCP 的 MSS = MTU − 40,所以 1420 对应的 MSS 是 1380。如果服务器只收发自身流量、不为别人转发,一般不需要钳制:内核会根据网卡 MTU 选择 MSS,剩下的交给 tcp_mtu_probing。
第 6 步:用 iperf3 做前后对比
在修改前后各跑一次相同的测试,尽量选在一天中相近的时段。两端都需要安装 iperf3(apt install iperf3 或 dnf install iperf3):
# On the VPS (allow TCP 5201 in the firewall only for the test)
iperf3 -s
# On your own computer
iperf3 -c 203.0.113.10 -t 20 # upload: you -> VPS
iperf3 -c 203.0.113.10 -t 20 -R # download: VPS -> you
iperf3 -c 203.0.113.10 -t 20 -R -P 4 # download, 4 parallel streams
如何解读结果:
-R是网站访客和下载用户实际体验到的方向,因为此时 VPS 是发送方,VPS 上的拥塞控制和发送缓冲区影响最大。-P 4会同时开 4 条连接。如果 4 条加起来比 1 条快很多,说明单连接受窗口大小或丢包限制,这正是缓冲区和 BBR 要解决的问题。如果两者都一样慢,就要看线路、客户端本地网络或客户端的接收缓冲区。- 在
-R模式下你的电脑是接收方,它的接收缓冲区同样有影响。新版 Windows、macOS 和 Linux 都会自动调整,但你这边的老旧路由器或 VPN 仍可能成为瓶颈。
iperf3 -s,并重新关闭 5201 端口。长时间满速测试会消耗流量,长期占用共享端口 70% 以上也违反合理使用规则。第 7 步:如需回滚
最干净的回滚方式是删除这两个文件并重启:
sudo rm /etc/sysctl.d/99-network-tuning.conf /etc/modules-load.d/bbr.conf
sudo reboot
只删除文件再执行 sysctl --system 不会恢复原值,这些参数会一直生效到重启为止。如果不想重启,请按备份文件里的数值手动设置。当前 Debian/Ubuntu 内核的常见默认值如下:
cat /root/sysctl-before.txt
sudo sysctl -w net.ipv4.tcp_congestion_control=cubic net.core.default_qdisc=fq_codel
sudo sysctl -w net.ipv4.tcp_rmem="4096 131072 6291456" net.ipv4.tcp_wmem="4096 16384 4194304"
sudo sysctl -w net.core.rmem_max=212992 net.core.wmem_max=212992
如果还添加了 MSS 规则,用 sudo nft delete table inet mssfix 删除(iptables 则把命令中的 -A 换成 -D),并从配置中去掉 include 行或 PostUp/PostDown 行。
FAQ
这些设置能降低 ping 值吗?
不能。RTT 由距离和路由决定。缓冲区和 BBR 让单条连接在这个 RTT 下用上更多带宽,fq 加 tcp_notsent_lowat 能在高负载时减少排队延迟,但基础延迟不会变。
1 GB 套餐用 32 MB 缓冲区安全吗?
正常业务下是安全的。这些数值是每个套接字的上限,自动调优只在连接确实需要时才扩大缓冲区,内核的全局 tcp_mem 上限也会根据内存大小自动设定。512 MB 的 mini 套餐建议用 16 MB。
调优后速度还是慢,应该给客服提供什么?
请在 Technical support 部门提交工单,附上服务器 IP、带时区的时间、带与不带 -R、-P 4 的 iperf3 结果,以及双向的 mtr 结果。收集方法见测速教程。JUSTG 提供 7×24 小时 AI 客服(工单),需要人工处理的问题会由工程师跟进。