云主机供应商防火墙导致的TCP连接无法建立问题

今天遇到一个非常诡异的问题。具体表现如下(两台机器分别用src和dst表示,两台机器在不同的数据中心,连接需要走公有网络)

  1. 在src主机,访问dst的8181端口,发现连接无法建立。
  2. src访问dst的非8181端口,连接正常建立
  3. 在src主机所在的集群,访问dst的8181端口,连接正常建立
  4. 在其它外网设备访问dst的8181端口,连接正常
  5. 通过内网访问dst的8181端口,连接正常
  6. 两个服务器都没有设置防火墙

于是在两边的节点分别抓了包,包的内容如下:

这是在src节点抓的包

云主机供应商防火墙导致的TCP连接无法建立问题

这是在dst节点抓的包

云主机供应商防火墙导致的TCP连接无法建立问题


乍一看,非常唬人,两边的节点都在收发rst包。那看来问题应该就是为什么会有rst包了。

重新组织包收发过程

这个时候就应该看图说话了,wireshark打开的包是两边分别抓到的,我们需要重新构建包发送的流程。我们以(8181, 54335)这一组画一下时序图

云主机供应商防火墙导致的TCP连接无法建立问题

上图编号是对应抓包方在wireshark中显示的包号,黑色包号是发出的包,红色包号是收到的包。

可以看到在客户端,其实是按照基本法来的,三次握手,握手之后发一个数据包,然后在收到rst之后重置连接。

但是在服务端,就没有按照基本法来了。三次握手,第二次握手发出去之后,就收到了四个rst包,而且这四个rst包在客户端没有抓到。由于rst包的原因,之后客户端再发来的两个包,就都被认为非法,返回了rst。

由此可见,客户端收到的包,都是服务器发出来的。只是服务器这里,收到了四个莫名其妙的包。

问题处理

实际上没啥好处理的。这个很明显,就是中间有防火墙作祟,发了好几个rst包回来。

给两边云主机服务商提工单,要求检查路由,防火墙等,之后自然是恢复了,只是由于这个rst包不能判断从哪里发出来(至少我的能力范围内不行),同时没有进一步路由信息(当时制作了ping路由测试),所以两边陷入无休止扯皮中。我估计是某一方的防火墙出了问题,收到工单后悄咪咪修复了,不肯告知原因吧。

倒是阿里给我回了一个建议,下次遇到这个问题,可以使用traceroute进行节点测试:

能ping通是节点端口可用性检查

这个大概就是用traceroute实现节点监测。嗯,看起来好像很科学,但是实际上不行。

首先来看看traceroute的执行原理。

traceroute原理

相当大部分人,都懂traceroute是设置了ip层的ttl来生成这个路由表的。但是进一步,如果用traceroute,怎么探测tcp端口可用呢?很简单,还是设置ttl,只不过这个时候上层不再使用ICMP的ping请求,而是发tcp的syn报文。

然后如果收到路由返回ICMP的ttl exceeded报文,说明节点没有拦截这个请求。如果被drop掉了或者返回了rst,那可能就是防火墙拦截了。

但是如果收到正常恢复的syn+ack呢?实际上这个时候traceroute就发送rst报文了。他并没有完成完整的三次握手。而从上面的抓包来看,客户端的三次握手,是正常的,所以这个时候,traceroute并不能帮助我们解决问题。

更新

在我把traceroute原理怼回去之后,对方乖乖跟我要了包,跟我方承认是防火墙拦截了。到此,再回复一句质疑下对方防火墙的设计,就打完收工了