4

一次MTU问题导致的RDS访问故障

 1 year ago
source link: https://blog.51cto.com/u_15714439/5890754
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

导语

VPN是一种通过公网连接两个或多个私网站点的专用网络,使得这些站点仿佛是通过专线连接在一起。IPSec是一套协议框架,用于保证数据传输的私密性,完整性,真实性。但是VPN网络经常会带来一些连通性上的问题,通常与MTU设置的不合理有关。本文通过一个实际案例,来具体分析解决这个问题。

作者:陆信宇

一、环境拓扑

  1. 链路中,各个设备接口的MTU为1450
    MTU是数据链路层的概念,限制的是数据链路层payload的大小,即上层协议大小(包括上层协议头),例如设置主机接口mtu为1450。则在一个TCP报文中,1450 = 20字节IP头 + 20字节TCP头 + 1410TCP数据。
  2. RDS为京东智联云云数据库实例,实例中创建有400个数据库。
  3. SH_MariaDB_VM是一台上海地域的云主机,部署了mariadb服务,数据和RDS实例相同。
  4. BJ_VPNGW和SH_VPNGW分别是北京VPC和上海VPC的vpn网关
  5. bj_client所在子网和RDS所在子网通信时,下一跳为各自所在地域的vpn网关
一次MTU问题导致的RDS访问故障_MTU

二、现象描述

  1. bj_client通过BJ_VPNGW连接RDS。执行show databases时,一直卡住无返回。
  2. bj_client通过BJ_VPNGW连接SH_MariaDB_VM。执行show databases正常,没有卡住的现象。

三、排查过程

  1. bj_client可以ping通RDS,telnet RDS 3306端口正常,使用mysql客户端也可以正常连接。
  2. 在BJ_VPNGW和SH_VPNGW上抓包分析。发现RDS回包正常到达SH_VPNGW,但是没有到达BJ_VPNGW。数据包在SH_VPNGW被丢弃。怀疑是MTU问题,导致丢包。
  3. 继续抓包分析RDS和SH_MariaDB_VM回包的区别。发现SH_VPNGW都给RDS和SH_MariaDB_VM回了一个IMCP Error报文,报文中指定了​​MTU next hop: 1374​​ 。但是RDS的重传报文中,ip层的Total Length一直是1450。SH_MariaDB_VM在首次被丢包后,重传报文的Total Length为1374。判断ICMP Error报文没有被正常转发给RDS服务端。后核实RDS前面还有一层LB,该LB没有转发ICMP Error。
  4. 调整bj_client接口mtu为1374之后,问题解决。

四、问题原因

由于bj_client、RDS、SH_MariaDB_VM的mtu都是1450,所以bj_client与RDS、SH_MariaDB_VM进行TCP三次握手时,协商的MSS大小为1410(MTU - 20B ip头 - 20B tcp头)。即后续发送的TCP报文的数据部分,最大不能超过1410字节,且IP头中DF置位,不允许报文分片。

bj_client连接RDS执行show databases命令。由于请求包较小,所以请求报文可以正常通过vpn网关到达RDS。RDS收到报文后开始响应。由于RDS中数据库很多,所以响应报文会拆分成多个进行发送,每个报文的TCP数据部分是1410字节。报文到达VPN网关后,VPN网关在原数据包基础上再次封装ESP、UDP、IP,封装之后的报文大小超过了VPN网关出接口的mtu值,又因为数据包不允许分片,导致VPN网关丢弃报文。VPN网关丢弃报文之后,会向RDS发送一个ICMP Error,指明mtu of next hop: 1374 ,告知RDS以1374为最大mtu发包。但是因为RDS实例前面还有一层LB,且这个LB不会转发ICMP Error报文,导致ICMP Error报文并没有到达真正的RDS服务端,最终导致RDS没有调整数据包大小就直接重传,数据包再次被vpn网关丢弃,进入死循环。

五、解决方案

根据以上分析,有三种解决方法。

  1. 调小服务端或者客户端mtu,让两端在建立三次握手协商mss时,以更小的mss收发数据。可以设置为ping探测的路径MTU值。
  2. 在VPN网关配置​​iptables -t mangle -A FORWARD -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu​​ 。两端建立三次握手的报文到达vpn网关时,修改MSS值,使MSS自适应PMTU(Path MTU)
  3. 保证icmp error报文可达
  1. 什么是MTU
    MTU是数据链路层的概念,限制的是数据链路层payload的大小,即上层协议大小(包括上层协议头)
    例如设置主机接口mtu为1450。则在一个TCP报文中,1450 = 20字节IP头 + 20字节TCP头 + 1410TCP数据。
  2. 什么是MSS
    MSS最大报文段,是TCP中一个选项,用于在TCP连接建立时,收发双方协商通信时每一个报文段所能承载的最大数据长度(注意不包含TCP头部大小)
  3. 如何探测路径MTU值
    Linux主机中: 执行​​​ping x.x.x.x -s 1422 -M do​​​ ,x.x.x.x是目标地址,-s指明icmp报文的数据部分大小(不包含icmp 8字节头部)。​​-M do​​​ 表示不允许分片。多试几次,找到临界点。以mtu为1450为例,1450 = 20字节IP头 + 8字节icmp头 + 1422数据,则-s指定为1422可以正常通过
    Windows主机中: 执行​​​ping x.x.x.x -l 1472 -f​​ ,x.x.x.x是目标地址,-l指明icmp报文的数据部分大小(不包含icmp 8字节头部)。-f表示不允许分片。
  4. 如何查看MTU

Linux: ifconfig

一次MTU问题导致的RDS访问故障_MTU_02

windows: netsh interface ipv4 show  subinterfaces

一次MTU问题导致的RDS访问故障_MTU_03
  1. 如何设置MTU

Linux: ifconfig
windows: netsh interface ipv4 show  subinterfaces


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK