一个NAT引发的血案

背景:

      内网有一台nginx服务器提供外网服务,时常出现访问异常或者重连现象,此故障出现均在外网不在内网,内网访问一切正常,未出现此类故障:

      当开启NAT时丢弃数据包增加。

   客户端显示:

nginx服务器显示

 

分析处理过程:

1、内网和外网访问的区别在于内网访问使用私网地址直接访问nginx服务器,外网和内网之间使用一台防火墙进行连接,nginx和公网地址在防火墙上做了地址映射。

 

2、怀疑是出口防火墙的问题,经过防火墙的厂家进行了检查,分三部分:

      > 内到外的地址映射是正常的,没出现任何异常。

      > 同为映射的邮件,DNS等服务器没出现此类问题。

      > 异常的就集中在和nginx之间的tcp连接异常,经常丢包造成。

  在中间进行抓包分析情况如下:

 

 

 

 抓包显示中间的异常数据包只有去往nginx的数据包却没有会回来的数据包。

 

3、后联合厂家和nginx管理人员沟通提出可能是由于防火墙的NAT时间戳造成的,nginx服务器端修改tcp_tw_recycle状态为down后恢复正常。

 

4、通过参考网上的资料,我们定位到问题发生的原因:我们的Web ServerLinux内做过调整,开启了net.ipv4.tcp_tw_recycle,在防火墙只做NAT的情况下,触发了大量的TCP建连失败。

 

tcp_tw_recycle

Enable fast recycling of TIME-WAIT sockets. Enabling this option is not recommended since this causes

problems when working with NAT (Network Address Translation).

 

启用TIME-WAIT状态sockets的快速回收,这个选项不推荐启用。在NAT(Network Address Translation)网络下,会导致大量的TCP连接建立错误。

 

下面我们来具体说下,首先解释下TCPTIME_WAIT状态:

  •    通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态。
  •    比如,客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2MSL时间(后有MSL的解释),进入CLOSED状态。
  •          TIME_WAIT状态的作用是为了保证连接正常关闭,且不影响其他新建的链接。

 

  

开启net.ipv4.tcp_tw_recycle的目的,就是希望能够加快TIME_WAIT状态的回收,当然这个选项的生效也依赖于net.ipv4.tcp_timestamps的开启(缺省就是开启的)。

当开启了tcp_tw_recycle选项后,当连接进入TIME_WAIT状态后,会记录对应远端主机最后到达分节的时间戳。如果同样的主机有新的分节到达,且时间戳小于之前记录的时间戳,即视为无效,相应的数据包会被丢弃

 

当防火墙启用NAT模式时,客户端TCP请求到达防火墙,修改目的地址(IP+端口号)后便转发给后端服务器,而客户端时间戳数据没有变化。对于后端Web Server,请求的源地址是防火墙,所以从后端服务器的角度看,原本不同客户端的请求经过LVS的转发,就可能会被认为是同一个连接,加之不同客户端的时间可能不一致,所以就会出现时间戳错乱的现象,于是后面的数据包就被丢弃了。

 

5、问题解决。

解决办法是Linux内核引入 tcp_tw_timeout 开关,该开关可以动态设置TIME_WAIT 时间,加速回收TIME_WAIT 状态,从而可以关闭tcp_tw_recycle ,避免上述问题。

 

参考链接:

https://blog.csdn.net/zhuyiquan/article/details/68925707

 

posted @ 2020-06-03 15:24  大安技术随笔  阅读(609)  评论(0编辑  收藏  举报