背景:
在业务灰度环境交付后,QA同事通过windows 拨号自建V**线路方式去访问该环境(通过v**线路分流/区域解析),可以正常测试国内的N个业务的接口,但无法通过v**线路访问www.sina.com.cn,然后试着访问海外的业务接口(不同机房),打开非常缓慢,于是尝试各种站点【百度, 腾讯视频,支付宝等】。发现有的可以打开,有的无法打开,有的第一次打开很慢,第二次打开很快。
问题分析和跟踪:
不断地尝试和记录发生的现象,总结发现存在以下规律:
1.通过v**访问同机房的应用没有问题
2.通过v**无法访问外部第三方站点: https://www.sina.com.cn
3.通过v**可以访问外部第三方站点: https://www.163.com
4.通过v**访问外部第三方站点:
https://v.qq.com,https://api-nusdk.service.boltrend.com/ , 第一次缓慢,第二次快。
由于之前碰到HTTPS 故障也不少了, 最开始怀疑SSL因素(客户端SSL加密套件不兼容/客户端SNI问题等), 通过抓包很快就定位到是MTU的问题。windows PPTP客户端的MTU为1400 【可以通过netsh interface查看】,而v** server端的MTU为1396,当TLS握手阶段,服务器端发送SSL证书的时候,由于 证书的TCP Segment ip头 超过MTU这个大小的时候,将无法完成SSL握手。问题虽然解决了,但上面的现象无法解释。
通过仔细分析抓包后,很快发现PMTU问题。
先查看 www.163.com
图1
图2
再观察www.sina.com.cn
图3
再观察 api-nusdk.service.boltrend.com
图4
以上三个站点抓包的结果中,v**-server都发送了icmp差错报文。除了www.sina.com.cn无法打开外,其他2个站点都可以正常打开。
V**-Server发出code=3,type=4的ICMP差错报文, 差错报文中带上了MTU of next hop【当前设备支持的MTU,见图2】。
经过翻阅RFC1191相关文档,明确了PMTU的行为,当收到ICMP差错报文的时候,ICMP带有 MTU of next hop的值 ,主机应该根据此值从新计算TCP MSS。
RFC191 中 描述,PMTU并不会改变三次握手时候TCP 的扩展字段MSS的大小(TCP三次握手会在syn,syn-ack TCP包的扩展字段带上支持的MSS),但协议栈收到PMTU产生的ICMP报文必须做出减少的动作。
当路由节点收到DF标识 但又必须分片(超过MTU)的报文,有3种动作,
- 发送符合RFC792的ICMP报文 (不带失败链路MTU)
- 发送符合RFC1191的ICMP报文(带失败链路的MTU,如上图中的ICMP差错报文)
- 丢弃该报文,什么都不做。【该路由器称为PMTU黑洞路由器】
如果中途碰到PMTU黑洞路由器,会怎么解决呢?在主机层有tcp_mtu_probing 机制解决这个问题。
当TCP重传超过设置的 内核参数sysctl_tcp_retries1,会触发tcp_mtu_probing 。当 tcp_mtu_probing计算MTU的时候,会参考net.ipv4.tcp_base_mss的值 和mtu动态探测算法计算出MSS值,取2者中的最小值,从而解决MTU问题。主机层net.ipv4.tcp_mtu_probing的默认值为0, 所以主机层默认并没有开启TCP MTU的探测(意味着遇到ICMP路由黑洞无法自适应tcp MSS)。
除此之外,主机层有一个参数net.ipv4.ip_no_pmtu_disc跟PMTU有很大的关系(强依赖),该值决定是否在IP报文中是否设置DF标识,centos6/7的net.ipv4.ip_no_pmtu_disc默认值为0(即设置DF标识),所以默认情况下主机层是支持PMTU。
回到上述几个现象的原因:
1.通过v**访问同机房的应用没有问题
同机房所有设备都支持PMTU, 不存在ICMP黑洞路由, 所以即使MTU大小不对,也可以通过PMTU协商出适当的MTU。
2.通过v**无法访问外部第三方https://www.sina.com.cn
去往新浪服务器的icmp(code=3,type=4)的报文并未达到源主机,PMTU机制无法运行(同时主机层并没有开启net.ipv4.tcp_mtu_probing).
3.通过v**可以访问外部第三方https://www.163.com
去往163.com的服务器链路上不存在icmp路由黑洞,163的服务器协议栈实现了RFC1191
4.通过v**访问外部第三方https://v.qq.com, https://api-nusdk.service.boltrend.com/ , 第一次缓慢,第二次快。
除了防火墙规则限制外,一般路由器(运营商/骨干)不会限制icmp(code=3,type=4)(但可能会由于QOS策略,例如限速导致丢弃ICMP) ,PMTU可以正常完成TCP MSS自适应(需要消耗一定的时间), 站点涉及到多台服务器,每个服务器都需要来一次这个过程,第一次会慢,
但centos6/centos7 有MTU的路由缓存(内核于3.6废弃route cache,centos6/centos7的内核<3.6, 缓存时间由NET_IPV4_ROUTE_GC_TIMEOUT确定), 所以第二次很快。