西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页 → 业内动态 → 业内资讯 → SSH连得上却传不动大文件,MTU 1500卡在哪一步?

SSH连得上却传不动大文件,MTU 1500卡在哪一步?

相关软件相关文章发表评论 来源:本站整理时间:2026/11/2 22:15:51字体大小:A-A+

Xshell6.0.0204电脑版
  • 类型:服务器区大小:40.7M语言:中文 评分:10.0
  • 标签:
立即下载

上周帮一个客户排查「服务器远程桌面连得上,但拖一个 800MB 的安装包过去,进度条走到 12% 就再也不动了」的问题。远程控制软件会断线重连,重连后一切正常,所以现象看着特别随机。ping 一下公网 IP 完全正常,nc 测试端口也通,防火墙、日志、磁盘全是干净的。折腾了两个多小时,最后抓包才看清楚:链路中间某一段的 MTU 比两端网卡小,而 TCP 没把「不分片」这个信息正确带过去。

正在折腾云服务器网络、或者需要长期传大文件的朋友,可以先看看这两家:狗云DOGYUN(高性价比云服务器,多机房可选)、RackNerd(全球VPS,特价常推)。选网络线路稳定、机房带宽不掐脖子的机器,比到家再折腾参数省事得多。下面把整个排查过程完整写出来,你按顺序走一遍基本都能定位。

机房网络设备特写:网线插入交换机端口,指示灯闪烁,链路协商由此开始

一、先说结论:MTU 到底是谁定的

MTU(Maximum Transmission Unit,最大传输单元)是单个 IP 包在某一跳链路上允许的最大字节数,默认通常是 1500,其中 20 字节给 IP 头,20 字节给 TCP 头,所以一个 TCP 包能带 1460 字节的应用数据(这就是 MSS)。

关键在于每一跳的 MTU 都可以不一样。以太网是 1500,PPPoE 拨号线路是 1492,VPN 隧道封装后要减掉外层头,常见 1480 甚至 1420,GRE 隧道更狠,可能只剩 1400 出头。你的电脑网卡 MTU 1500,运营商接入的那段是 1492,中间某个交换机出口是 1480这些数字不一致时,就埋下了雷。

之所以平时不出事,是因为 IP 协议有个兜底机制:包太大就分片(fragmentation),拆成小块分别传输,到目的地再重组。但这里有个致命细节IPv4 的分片只有第一片带 TCP 头,后面几片不带头。而很多防火墙、NAT 设备、负载均衡器出于安全考虑,直接丢弃带 DF(Don't Fragment,不要分片)标志的大包。这就是所谓的 PMTU 黑洞:包没到终点,被静默丢弃,发送方那边却毫无察觉。

数据在链路上被切分成多个数据块依次传输的三维示意,MTU决定每个块的大小

二、为什么表现是「连得上但传不动」

这是这个故障最迷惑人的地方,也解释了为什么很多人第一反应是「服务器有问题」。

SSH 协议的握手阶段全是小包。典型的 SSH 握手包几十字节到几百字节,远小于任何一条链路的 MTU,所以它能顺利通过。客户端认证、打开终端,这些交互包也都很小,一切正常。你敲个 ls、看个日志,输出就几 KB,压根用不到大包,所以完全无感。

直到你开始传文件。scp/sftp 传大文件时,TCP 窗口一打开就会塞满 MSS 大小的数据段(默认 1460 字节),每个包都顶着链路上限跑,第一个超过实际 PMTU 的包直接被中间设备丢了。发送方等不到 ACK,重传一次,还是丢,再重传于是进度条就停在某个百分比反复横跳,最后超时断开。

还有个更细的表现差异:如果你的网络路径里恰好有能协商 MSS 的机制(比如 TCP MSS clamping),问题可能根本不出现。所以「昨天还好好的今天就坏了」这种描述往往是错的多半是某台中间设备重启、或者路由路径切换了,clamping 没了而已。

三、动手排查:三条命令定位

第一步,看两端协商出的 MTU。

ip link show eth0
Linux 上直接看网卡的 MTU,云服务器通常是 1500。

cat /sys/class/net/eth0/mtu
想要一个纯数字结果就用这个。

Windows 上是 netsh interface ipv4 show subinterfaces,能看到每个网卡的 MTU 和当前接收/发送的包大小分布。

第二步,用带 DF 标志的 ping 试探真实 PMTU。这是最关键的一步,很多人只知道普通 ping,那只能测通不通,测不出 MTU。

ping -M do -s 1472 1.2.3.4
含义是:这个包带 DF 标志不许分片,IP 头 20 + ICMP 头 8 之外再塞 1472 字节用户数据,正好凑满 1500。发出去不丢,说明链路吃得下 1500。

ping -M do -s 1400 1.2.3.4
如果上面那条丢了,这条能通,那真实 PMTU 就在 1428 左右(1400 + 28)。用二分法往下试,很快就能卡出那个临界值。Windows 没有 -M do 这个参数,可以用 ping -f -l 1472 IP,效果等价。

第三步,抓包确认。很多人跳过这步,其实它能一眼定位。

tcpdump -i eth0 -n host 客户端IP and tcp port 22 -w /tmp/ssh.pcap
传文件的同时抓,然后 tcpdump -r /tmp/ssh.pcap -n -c 50 看窗口大小和重传情况。如果看到大量「同一个序号的重传」,且每次重传的包长度都一样,那就是典型的 PMTU 黑洞特征包被丢了,而不是被拒了。

笔记本终端窗口中的文件传输进度条停在某个百分比,排查从终端日志入手

四、怎么修:分场景对症下药

场景一:客户端或服务器某一端 MTU 配小了。直接改对就行,Linux 上:

ip link set dev eth0 mtu 1480
临时生效,重启失效。要永久生效,把这行写进网卡的配置文件(Debian 系是 /etc/network/interfaces,CentOS 系是 /etc/sysconfig/network-scripts/ifcfg-eth0 里加 MTU=1480)。

场景二:中间链路 MTU 未知且不可控(比如运营商、别人的网络)。这时候只能在端上想办法降低 MSS,让 TCP 不要发那么大的包。最常用的做法是在网关上做 MSS clamping当转发出去的包大于路径 PMTU 时,自动把 TCP 头里的 MSS 字段改小。这一步对普通用户来说有点门槛,通常在路由器或云网络的 NAT 网关上做。

纯 Linux 主机上可以用 iptables:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
这行的意思是:在转发路径上,遇到 SYN 包就把 MSS 夹到当前路径的 PMTU 值。关键是加在转发链路上,只对本机出站流量无效,本机自己发的流量要另外处理。

场景三:应用层能配置的地方。这个最省事,很多场景直接就解决了。

  • SSH/SCP:OpenSSH 有个 IPQoS 选项,默认会设置 DSCP 标记,某些 QoS 策略下会引入额外开销。排查时可以先试 ssh -o IPQoS=none user@host,能通就说明问题出在 QoS 标记被中间设备重写或丢弃。
  • rsync:加 --mss-include 不是选项,rsync 本身不控制 MTU,但加 --protocol=TCP_NODELAY 有时能改善小包堆积的表象。
  • 数据库同步/备份:大对象传输常常可以调小 chunk size,比如 mysqldump 的 --max_allowed_packet、pg_dump 的 --compress 配合更小的块,本质都是在应用层把大包拆小了。

还有一个务实的做法:改用中转方案。如果链路是跨运营商或者跨境,中间设备多到你搞不清,直接上 WireGuard 或 frp 之类的隧道协议,让流量封装在你自己的可控路径里走。带宽会少一点(封装有开销),但稳定性通常好得多。我那个客户最后就是老老实实把客户端 MTU 降到 1400 收工,十分钟解决。

五、写在最后:别忘了向上游确认

MTU 这个问题最麻烦的地方在于,你很难从服务器内部看到全貌。链路中间那一段不属于你,也不归你管。所以排查的顺序应该是:先在本地确认两端 MTU 配置,再测两端之间的 PMTU,最后去问中间链路是谁的设备在管。

如果测出来 PMTU 是 1400 这种「非标准值」,基本可以确定是 VPN 或 PPPoE 造成的;如果是 1472 或者 1480,那就是 PPPoE 或隧道封装;如果是 1500 但仍然传不动大文件,那就别再往 MTU 上想了,去查 QoS、连接数限制或者中间设备的 ACL 策略。

最后留一句实操建议:新买的服务器第一件事,先跑一遍 ping -M do 的二分测试把这条链路的 PMTU 记下来,写进自己的运维文档。以后再遇到「连得上但传不动」的问题,不用重新排查,30 秒就能定位。这点小麻烦,省下的是一整晚的抓瞎。

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶顶
    • 1 难过难过
    • 5 囧囧
    • 3 围观围观
    • 2 无聊无聊

    发表评论

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲