Chinaunix首页 | 论坛 | 博客
  • 博客访问: 439063
  • 博文数量: 71
  • 博客积分: 26
  • 博客等级: 民兵
  • 技术积分: 1246
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-23 14:46
个人简介

linux --- 一切皆文件

文章分类

全部博文(71)

文章存档

2021年(1)

2019年(2)

2018年(4)

2017年(7)

2016年(11)

2015年(1)

2014年(2)

2013年(33)

2012年(10)

分类: C/C++

2017-11-10 10:46:46

Client发送SYN包后收到ACK而不是SYN/ACK

拓扑如下:

异常现象:

Client偶尔出现到Server的链接异常。Client发送SYN包,在FW内网侧抓包,没有任何回应报文,在FW外网侧抓包,发现Server回了一个ACK报文,并且SEQ和ACK号异常。

问题排查与确认:

由此可推断出,FW丢弃了Server回应的ACK报文。经过与防火墙公司确认,此公司确实会丢弃此类ACK报文,将此类报文放行即可解决问题。

原因分析:

Client1  ip:1.1.1.1:12345请求到server ip:222.222.222.80。到达防火墙之后,将Client1的ip/port改成10.10.10.10:12345。(虽然NAT使用了动态端口模式,但是如果12345这个端口在会话表中没有,则防火墙还是将12345作为源端口,并不会重新选择随机端口,当12345源端口正在使用,则防火墙重新随机选择新端口作为源端口。)

Client1发送http请求,请求结束后,Server主动关闭链接发送FIN/ACK报文,最终Server进入TIME-WAIT状态(Linux等待60秒)。但是FW会很快将此会话超时掉,此FW time-wait默认超时时间为1秒。

Server端会话 10.10.10.10:12345 222.222.222.222:80此会话正在Time-wait状态超时时。在时间隔大于1秒小于60秒时间中,Client2又以12345端口发送请求,会话信息如下:1.1.1.2:12345 222.222.222.222:80。此syn包到达FW,FW会进行SNAT,转换为10.10.10.10:12345 222.222.222.222:80(此时Client1使用12345端口的会话在FW上已经超时了,所以转换出去源端口还是12345)。

但是,此时Server端还是处于Time-Wait状态,收到一个syn包,Server会做如下操作:

1)        如果此syn包的SEQ号大于Server端此会话收到最后一个包的SEQ号,则新建会话,回应SYN-ACK报文

2)        如果此syn包的SEQ号小于Server端此会话收到最后一个包的SEQ号,则Server认为是此会话之前的报文,只是延迟到达而已。则返回一个ACK报文。

异常情况下,就是发送的SYN包的SEQ小于Server端此会话收到最后一个包的SEQ号,Server在Time-out状态下返回ACK报文。但是此时FW则认为此ACK报文异常,则将此报文丢弃。

如果防火墙规则不丢弃此ACK报文:

如果此ACK报文通过FW,回到了Client2,Client2则认为此ACK包异常,并且此链接也异常,则Client2直接会反弹RST报文到Server,Server收到RST报文后,立即将Time-wait状态的会话释放。此时Client2继续会发送一个相同源端口的SYN包到到Server。会话建立成功。


参考资料:
    

注意:

1.此问题只针对Server主动关闭链接的场景。

2.如果Server上的会话在ESTABLISH状态,收到syn包,也会回应ACK报文。

3.可给Client1和Client2各分配一个NAT公网地址,作为应急方案。



阅读(4962) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~