tcp_tw_recycle引起的TCP握手失败

标签: linux

背景

测试环境的一台Nginx服务器,最近一直被前端同事吐槽网络有问题,经常出现访问HTTP请求时超时,哪怕是静态文件也经常超时。

刚开始以为是公司网络抽风了,也就没放在心上,但持续了一个星期,而且复现率很高,这才反应过来应该不是网络的锅。于是在请求客户端与Nginx服务器上均作了抓包。

本地客户端抓包结果如下图1,请求Nginx服务器TCP握手时超时。结果似乎很明朗,客户端TCP握手的SYN请求丢包导致多次重试,直到重试超时而TCP握手失败。看上去似乎就是网络问题,但这复现率也太高了,于是在服务器上也做了一次抓包。

图2为Nginx服务器抓包图,显示服务器接收到了TCP握手请求,但是未做应答,直到客户端重试超时结束。很明显,并不是网络丢包而导致的TCP握手失败,而是某种机制导致的服务器直接抛弃了客户端的请求报文。

在这里插入图片描述

复现

准备

准备两个Client机器(192.168.50.150、192.168.50.160)以及一个Server机器(118.24.117.115),并且两个Client机器均处于同一个NAT网关下(116.239.x.x)。

在这里插入图片描述

启用两个Client机器TIME-WAIT连接快速回收,编辑文件/etc/sysctl.conf,添加或修改以下参数:

net.ipv4.tcp_tw_recycle = 1

然后执行命令使sysctl.conf的参数生效:

[root@VM_0_10_centos ~]# /sbin/sysctl -p
[root@VM_0_10_centos ~]# cat /proc/sys/net/ipv4/tcp_tw_recycle 
1

复现步骤

  1. Client1机器请求Server,Client1抓包和Server抓包如下两张图,TCP握手成功:

在这里插入图片描述

在这里插入图片描述

  1. Client2机器请求Server,Client2抓包和Server抓包如下两张图,TCP握手成功:

在这里插入图片描述

在这里插入图片描述

  1. Client1机器再次请求Server,Client1抓包和Server抓包如下两张图,TCP握手失败,复现成功:

在这里插入图片描述

在这里插入图片描述

通过netstat -s命令查看网络统计时,可以发现每次复现出TCP握手失败后,如下的一行统计值都会对应增长。

[root@VM_0_10_centos ~]# netstat -s | grep timestamp
    2143 packets rejects in established connections because of timestamp

原理

PAWS机制

Per-host PAWS机制

PAWS uses the same TCP Timestamps option as the RTTM mechanism described earlier, and assumes that every received TCP segment (including data and ACK segments) contains a timestamp SEG.TSval whose values are monotone non-decreasing in time. The basic idea is that a segment can be discarded as an old duplicate if it is received with a timestamp SEG.TSval less than some timestamp recently received on this connection.

PAWS机制是基于客户端IP而非客户端IP+端口号的,当服务端开启了net.ipv4.tcp_tw_recycle后,服务端会对SYN报文做时间戳检查。每当快速回收TIME_WAIT连接后,会在60秒缓存该客户端IP的TSval时间戳。在这60秒内如果同一个IP再发起SYN请求时,会校验新请求的TSval是否大于缓存的TSval,保证同一个请求方IP的TSval时间戳是递增的。而对于非递增的SYN请求则直接丢弃处理。

TSval并非真正的时间戳,而是由时间戳依据一定算法算出来的一个值,与时间戳有同等的特性,即随时间单调递增;

如上复现操作时的图,由于Client1和Client2处于同一个NAT网关下,对于Server来说,Client1和Client2的IP相同均为NAT网关的IP。

  1. 当Client1请求Server时,IP(116.239.x.x)的时间戳值TSval为1853021;
  2. 当Client2请求Server时,IP(116.239.x.x)的时间戳值TSval为1927141;
  3. 当Client1再次请求Server时,IP(116.239.x.x)的时间戳值TSval为1864558;

当步骤3请求时,对于Server来说,IP(116.239.x.x)的TSval时间戳小于上次请求的时间戳,因此该SYN请求直接被丢弃了,导致TCP握手失败。

Linux内核的实现

Linux内核源码中,对于PAWS机制的实现很简单,如果客户端的TCP报文中启用了timestamp option,且服务端启用了net.ipv4.tcp_tw_recycle,则会触发PAWS机制检查。

tcp_ipv4.c

int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
...

    /* VJ's idea. We save last timestamp seen
     * from the destination in peer table, when entering
     * state TIME-WAIT, and check against it before
     * accepting new connection request.
     *
     * If "isn" is not zero, this request hit alive
     * timewait bucket, so that all the necessary checks
     * are made in the function processing timewait state.
     */
    if (tmp_opt.saw_tstamp &&   // TCP报文中启用了timestamp option
        tcp_death_row.sysctl_tw_recycle &&  // 开启了net.ipv4.tcp_tw_recycle
        (dst = inet_csk_route_req(sk, &fl4, req)) != NULL &&
        fl4.daddr == saddr) {   // 仅判断源IP相同,不区分端口号
    	if (!tcp_peer_is_proven(req, dst, true)) {
    		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
    		goto drop_and_release;
    	}
    }

...
}

tcp_metrics.c

bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check)
{
	struct tcp_metrics_block *tm;
	bool ret;

	if (!dst)
		return false;

	rcu_read_lock();
	tm = __tcp_get_metrics_req(req, dst);
	if (paws_check) {
		if (tm &&
		    // peer 信息保存的时间离现在在60秒(TCP_PAWS_MSL)之内
		    (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL &&
		    // peer 信息中保存的timestamp 比当前收到的SYN报文中的timestamp大1(TCP_PAWS_WINDOW)
		    (s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW)
			ret = false;
		else
			ret = true;
	} else {
		if (tm && tcp_metric_get(tm, TCP_METRIC_RTT) && tm->tcpm_ts_stamp)
			ret = true;
		else
			ret = false;
	}
	rcu_read_unlock();

	return ret;
}

解决

关闭TCP的TIME_WAIT快速回收功能即可:编辑文件/etc/sysctl.conf,添加或修改以下参数:

net.ipv4.tcp_tw_recycle = 0

然后执行命令使sysctl.conf的参数生效:

[root@VM_0_10_centos ~]# /sbin/sysctl -p
[root@VM_0_10_centos ~]# cat /proc/sys/net/ipv4/tcp_tw_recycle 
0

疑问

查看Linux内核源码后发现,触发PAWS机制检查的前提条件之一是客户端的TCP请求携带了timestamp option,如下图1。但是当使用Windows操作系统时,客户端默认关闭了timestamp option,通过抓包也显示TCP请求中未携带timestamp option,却依然触发了PAWS机制,如下图2。

在这里插入图片描述

在这里插入图片描述

参考

  1. Linux内核协议栈丢弃SYN报文的主要场景剖析
  2. Tcp tw recycle打开导致60s内不能两个用户同时登录
  3. 开启tcp_tw_recycle内核参数在NAT环境会丢包
版权声明:本文为sz85850597原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sz85850597/article/details/107580686

智能推荐

TCP握手协议及相关的参数

TCP握手协议及相关的参数 转载:https://blog.csdn.net/justinhuo/article/details/90744624 问题描述:笔者在进行压力测试的时候遇到了奇怪的问题,压力机的环境是win7的环境,在进行压力测试的时候发现了系统的端口一直被占用,无法释放开来,进行了接口的查找发现了大量的端口处于time_wait的状态,处于未被释放的状态,在这里进行总结下,以后续出...

wireshark实践TCP的三次握手

1 前言 环境 源博客: http://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html 2 实践与分析 和我本机通信的网址是:http://www.cnblogs.com/tankxiao 通过观察wireshark的包,得到通信网址的IP是101.37.225.58 所以wireshark的过滤条件是: wireshark截图: ...

使用WireShark查看TCP的三次握手

    WireShark是一种非常方便的网络抓包工具,下面演示,使用WireShark来抓取TCP的三次握手过程。 一、TCP的三次握手过程如下:     1)客户端发送***为Seq = c的SYN数据包给服务器;     2)服务器接到该包后,响应(或返回)一个***为Seq = s,确认号为 Ack = c+1的SYN+ACK数据...

TCP协议及三次握手的过程

在这里插入代码片@TOC TCP协议以及三次握手 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 TCP协议以及三次握手 1、TCP协议是什么? 2、TCP协议的作用 3、TCP工作模式 *4、TCP三次握手 第一次握手 第二次握手 第三次握手 分析握手过程中字段的变化 1、TCP协议是什么? 传输控制协议(Transmission Control Protocol,T...

Java中动态代理的两种方式JDK动态代理和cglib动态代理以及区别

上篇介绍了一下静态代理:Java中的代理模式——静态代理以及分析静态代理的缺点 也分析了一下静态代理的缺点: 1、由于静态代理中的代理类是针对某一个类去做代理的,那么假设一个系统中有100个Service,则需要创建100个代理类 2、如果一个Service中有很多方法需要事务(增强动作),发现代理对象的方法中还是有很多重复的代码 3、由第一点和第二点可以得出:静态代理的重...

猜你喜欢

圆周长-数学问题

导读:2020.5.9号面试,其中笔试有另外这样的一道题,让我瞬间卡住了,结果回来给弟弟解,他解出来,弟弟的解题思路真的棒,因此这里记录一下解图过程,及验证一下答案是否正确。 文章目录 题目 弟弟解题过程 总结 题目 甲从A点开始按照圆形逆时针方向行走,乙从B点开始按照圆形顺时针方向行走,甲乙均匀速行走,甲乙第一次会面点在C点, 第二次会面点在D点,其中AB是圆的直径,BD弧长60米,BC弧长10...

项目优化2-调整终端大小,居中显示

项目优化2 调整终端大小 优化成“居中显示”...

几何着色器(二) 表面法线可视化

从之前的介绍,我们已经了解了几何着色器的基本知识,现在介绍一下如何用几何着色器实现表面法线的可视化 如果是第一次了解几何着色器,可以先了解基本知识:几何着色器(一) 效果图: 首先我们先了解一下绘制流程:     1.**顶点着色器和片元着色器     2.正常绘制模型     ...

剑指offer--- 数值的整数次方

题目描述: 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0 。 解题思路: 方法1: 当exponent为偶数时,例如exponent=4,result=(base2) 2; 当exponent为奇数时,例如exponent=5,result=(base2) 2 *base; 从而可以进行简单的...

11.FPGA_Verilog 奇分频

功能:根据系统时钟50M,产生一个频率信号为系统时钟的五分频 描述:分别通过时钟的上升沿和下降沿产生一个计数到5的计数器,两个计数器再分别产生一个占空比为60%的方波,相与即可。 如下图为时序图: 仿真波形:...