标签 mtu 下的文章

google cloud platform(gcp)的一个关于网络的坑

gcp这个网络坑是vm网卡的mtu是1460,一般其他vps或云服务的都是1500。

在gcp上使用更换付费账号的方式重新撸了300刀一年,其实在15/16年就用过一年,当时台湾服务器还没被草烂,联通直连能跑满带宽,后来用的人越来越多,很多ip被墙了,到期之后就没再用。

最近发现gcp新放出来一批ip,识别地址是美国,还没有被各大视频网站(Netflix,hbo,hulu等)加入黑名单,所以又撸了一年,先用着。

之前用gcp只是用ss,没有碰到mtu的问题。这次用gcp做落地机出现了问题。
境内路由器隧道到阿里云香港然后隧道到gcp香港,再出去,由于隧道的原因链路最小mtu是1390,小于gcp网卡1460,所以没有问题。

我的苹果设备需要一个ikev2服务器访问美国服务,按之前的一键脚本一路下来很顺利,却打不开谷歌的各种服务,但是ping正常,telnet正常,刚开始以为是dns问题,一键脚本默认是8.8.8.8,服务器是169.254.169.254的内网ip,修改dns服务器地址之后依然不行。然后想到是不是gcp对nat有什么限制,遍历gcp设置,各种查文档,改配置也是一无所获。

ikev2建立连接后,客户端通过telnet发现是可以建立tcp连接的,然后通过curl -v去请求测试,发现curl -v google.com可以收到301状态码,但是curl -v www.google.com卡在tcp建立连接后接收http报文,curl -v https://www.google.com 卡在tls协商,其实从这基本可以确定是mtu问题了,因为卡住之前都是小包碰不到分片或丢包,到接收http报文或者tls协商都是大包,超过mtu都是要分片或丢包,由于关于mtu的问题很久没有遇到了,一时没想起来。

惆怅迷惑之际拿起了wireshark抓包,curl -v www.google.com后,wireshark出现“tcp previous segment not captured”,终于意识到大包被丢包了,可能是mtu问题。ifconfig发现imac的ipsec0接口mtu是1400,sudo ifconfig ipsec0 mtu 1200 up,问题解决。但是不能每个客户端都修改mtu,ios怎么修改mtu?

查询文档,谷歌建议vm网卡使用1460,说是全球链路中最大1460,先不管了修改vm网卡为1500,vm只作中转不从vm直接上传什么应该问题不大。

gcp关于strongswan的文档根本没有提到mtu问题。

使用ping测试路径里设备的mtu

使用ping测试路径里设备的mtu,mac ping -s 1472 -D 192.168.1.1,linux ping -s 1472 -M do 192.168.1.1,windows ping -f -l 1472 192.168.1.1,如果不通则mtu小于1500
1472是ping数据大小,要加上icmp控制8字节和20字节的ip包头,等于1500字节。

MTU 到底是怎么来的
MTU, 是 Maximum Transmission Unit 的缩写, 根据 Wikipedia 的定义, MTU 指的是在 Network Layer (因处 OSI 第三层, 后以 L3 代替)上传输的最大数据报单元, 而 MTU 的大小一般由 Link Layer (因处 OSI 第二层, 后以 L2 代替) 设备决定. 比如生活中使用最广泛的以太网(Ethernet, IEEE 802.3)的帧大小是 1518 字节, 根据 Ethernet Frame 的定义, L2 Frame 由 14 字节 Header 和 4 字节 Trailer 组成, 所以 L3 层(也就是 IP 层)最多只能填充 1500 字节大小, 这就是 MTU 的由来.

802.3 Ethernet MTU
Dest MAC(6)Src MAC(6)Eth Type/Len(2)PayloadCRC Trailer(4)

所以说, 当使用 Ethernet 介质时确定只能传最大 1518 字节的帧后, 减去 18 字节的 L2 头和尾, 留给 IP 层的就只有 1500 字节了.

PS: 标准文档中中所说的 LLC 层因为在实际应用中基本不存在, 所以 802.3 标准 MTU 是 1492, 但是实际使用中的 MTU 是 1500.

L2, L3 示意图
IP Layer(1500)
Link Layer(1518)

PPPoE MTU
另一个典型的 MTU 是拨号上网( PPPoE )的 1492 字节, 通过以太网接入的 PPPoE 的封包结构上会在 L2 和 L3 之间插入两层, 一层 PPP 协议和一层 PPPoE 协议. 但是因为传输的底层仍然使用的是以太网, 所以上层包大小仍然受 L2 大小限制. MTU 这样算, Link Layer 长 1518 字节, 所以 PPPoE Layer 最长 1500 字节, 然后 PPPoE 头占用 6 字节, PPP 头占用 2 字节, 所以留给 IP 层的最大空间就剩下了 1492 字节:

IP Layer(1492)
PPP Layer(1494)
PPPoE Layer(1500)
Link Layer(1518)

VLAN(802.1Q) MTU
VLAN (IEEE 802.1Q) 的实现是在 L2 头部扩展了一个 4 字节大小的字段, 分别是 2 字节协议识别码(TPID)和 2 字节的控制信息(TCI), 这导致了 L2 的头和尾加起来的长度变成了 22 字节, 所以 L3 的 MTU 就被压缩到了 1496 字节:

IP Layer(1496)
Link Layer(1518)

然而在 802.3ac 标准之后的以太网帧大小则扩展到了 1522 字节, 也就是说在这个标准下的 Ethernet, MTU 也可以设定成 1500 字节了.

IP Layer(1500)
Link Layer(1522)

TCP MSS
MSS (Maximum Segment Size)是 TCP Layer (L4) 的属性, MSS 指的是 TCP payload 的长度. 当在 MTU 1500 的网络上传输时, MSS 为 1460 (即 1500 减去 20 字节 IP 头, 20 字节 TCP 头).

为什么 L3 有 MTU 后 L4 还要 MSS 呢?
MTU 和 MSS 的功能其实基本一致, 都可以根据对应的包大小进行分片, 但实现的效果却不太一样.

L3 (IP) 提供的是一个不可靠的传输方式, 如果任何一个包在传输的过程中丢失了, L3 是无法发现的, 需要靠上层应用来保证. 就是说如果一个大 IP 包分片后传输, 丢了任何一个部分都无法组合出完整的 IP 包, 即是上层应用发现了传输失败, 也无法做到仅重传丢失的分片, 只能把 IP 包整个重传. 那 IP 包越大的话重传的代价也就越高.

L4 (TCP) 提供的是一个可靠的传输方式, 与 L3 不同的是, TCP 自身实现了重传机制, 丢了任何一片数据报都能单独重传, 所以 TCP 为了高效传输, 是需要极力避免被 L3 分片的, 所以就有了 MSS 标志, 并且 MSS 的值就是根据 MTU 计算得出, 既避免了 L3 上的分片, 又保证的最大的传输效率.