打开tcp_tw_recycle引起的一个问题

今天普空说了一个问题就是如果设置了tcp_tw_recycle ,那么如果客户端是NAT出来的,那么就可能会出现连接被直接rst的情况。然后我google了下,在内核列表也有人说了这个问题 https://lkml.org/lkml/2008/11/15/67

The big problem is that both are incompatible with NAT. So if you
ever talk to any NATed clients don’t use it.

源码之前了无秘密,我们来看代码,为什么会出现这种问题,我这里是3.4.4的内核。核心代码是在tcp_v4_conn_request中,这个函数是什么时候被调用呢,是当listen socket收到syn包的时候被调用。直接来看涉及到tw_recycle的代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

#define TCP_PAWS_MSL    60      /* Per-host timestamps are invalidated

                     * after this time. It should be equal

                     * (or greater than) TCP_TIMEWAIT_LEN

                     * to provide reliability equal to one

                     * provided by timewait state.

                     */

#define TCP_PAWS_WINDOW 1       /* Replay window for per-host

                     * timestamps. It must be less than

                     * minimal timewait lifetime.

        /* 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_death_row.sysctl_tw_recycle &&

            (dst = inet_csk_route_req(sk, &fl4, req)) != NULL &&

            fl4.daddr == saddr &&

            (peer = rt_get_peer((struct rtable *)dst, fl4.daddr)) != NULL) {

            inet_peer_refcheck(peer);

            if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&

                (s32)(peer->tcp_ts - req->ts_recent) >

                            TCP_PAWS_WINDOW) {

                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);

                goto drop_and_release;

            }

        }

可以看到当满足下面所有的条件时,这个syn包将会被丢弃,然后释放相关内存,并发送rst。
1 tcp的option有 time stamp字段.
2 tcp_tw_recycle有设置。
3 在路由表中是否存在完全相同的流(如果打开了xfrm的话,还要比较端口,默认xfrm应该是打开的),如果存在则直接返回.
4 并且数据包的源地址和新请求的源地址相同.
5 根据路由表以及源地址能够查找到保存的peer(这个可以看我以前的blog,也就是保存了一些连接统计信息).
6 当前时间(接收到syn)比最后一次的时间(time stamp)小于60秒.
7 已经存在peer的最近一次时间戳要大于当前请求进来的时间戳.

从上面可以看到,上面的条件中1/2都是 server端可以控制的,而其他的条件,都是很容易就满足的,因此我们举个例子。

如果客户端是NAT出来的,并且我们server端有打开tcp_tw_recycle ,并且time stamp也没有关闭,那么假设第一个连接进来,然后关闭,此时这个句柄处于time wait状态,然后很快(小于60秒)又一个客户端(相同的源地址,如果打开了xfrm还要相同的端口号)发一个syn包,此时linux内核就会认为这个数据包异常的,因此就会丢掉这个包,并发送rst。

而现在大部分的客户端都是NAT出来的,因此建议tw_recycle还是关闭,或者说server段关闭掉time stamp(/proc/sys/net/ipv4/tcp_timestamps).

时间: 2024-08-30 03:33:20

打开tcp_tw_recycle引起的一个问题的相关文章

打开tcp_tw_recycle引起的一次投诉分析

背景: 我们有个基于oauth2.0协议给第三方授权以及信息的业务,年前对接入层.业务层做了次迁移.业务架构简单介绍下: lvs接入---> nginx ---> tomcat 问题: 迁移完第1天,接到好几个合作商的投诉,其中有家说在他们业务集群中,有20%左右的失败率,日志显示连接被拒绝. 定位: 和开发商调试,telnet我方端口正常.curl发测试请求也正常.没办法,请开发商的运维同学tcpdump抓了几分钟的数据, 发过来分析.如下图打开一看全是灰色...怪吓人的.从抓包看被serv

Window.open 实现导航与打开窗口,导航到一个特定链接地址,也可以打开一个新的浏览器窗体

语法 window.open(strUrl,strWindowName,strWindowFeatures ,replace) strUrl: 打开资源的地址 strWindowName: 表示窗体名称.如果该参数指定了一个已经存在的窗口,那么open()方法就不再创建一个新窗口,而只返回对指定窗口的引用.在这样情况下 fratures 将被忽略. strWindowFeatures :新窗口要显示的标准浏览器的特征 replace: 一个可选的布尔值.规定了装载到窗口的 URL 是在窗口的浏览

u014133182[chang_bo推荐] EXCEL每次打开文件都会出现一个空白...[Office应用]

s掖及4等悔2陈矢w谌辖http://blog.sina.com.cn/s/blog_17b85d6f90102xea6.html3底巴z卑雌5思扇b毯坠http://blog.sina.com.cn/s/blog_17b63170f0102x3li.htmlc纱抵u寥卧q端掠s友驴http://blog.sina.com.cn/s/blog_17bbc6b610102y3j7.htmlx宜补1浦乓9氨戏z址沿http://blog.sina.com.cn/s/blog_17bb1af12010

打开文件对话框 保存一个txt文件 比较简单用的时候省的搜索了

SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "Text (*.txt)|*.txt|All Files (*.*)|*.*"; sfd.FileName = "板材清单" + DateTime.Now.ToShortDateString().Replace('/', '-'); sfd.FileOk += Sfd_FileOk;//注册保存按钮的点击事件 sfd.ShowDialog(); stri

net.ipv4.tcp_tw_recycle

原创 2016-03-07 CFC4N 运维帮 本文为翻译英文BLOG<Coping with the TCP TIME-WAIT state on busy Linux servers>,(http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html)但并非完整的翻译,译者CFC4N对原文理解后,进行了调整,增加了相关论点论据,跟原文稍有不同.翻译的目的,是为了加深自己知识点的记忆,以及分享给其他朋友,或许对他们也有

TCP参数tcp_tw_recycle调整

最近一直在开发移动端的接口,在内部测试的时候发现这么个奇怪现象: 现象: 一部Android手机访问服务器响应没什么问题,当使用两部Android手机同时访问的时候会出现有一部手机访问不了接口的现象. 解决思路: 遇到这种问题首先想到的是使用linux命令查看下TCP连接数量,netstat -n|grep 8888 发现每当两部手机同时打开APP时只有一个TCP连接,那问题应该是在建立TCP连接上,于是带着疑问百度了一下,果然网上有很多这个样的解决方案: 关闭服务器的tcp_tw_recycl

Raspberry pi,一个好玩的派:第五季 无线网卡

Raspberry pi的板子由于成本原因是没有加无线模块的,不想被网线束缚的我们,需要自备USB无线模块.在购买板子时,看见官方推荐EDUP无线网卡,价格还算合适,就直接入手了. 采用REALTEK8188芯片,802.11n,传输速度150Mbps,适用范围130平方米. 将其插到任一U口即可,如下图: 由于外壳阻碍了电源插孔,所以只好先裸着了,图中已经加电,HDMI的另一头是电视机. 接下来的任务就是如何让这个无线网卡工作,连接到我已经开启的无线路由器. 一.wpa_gui 在进入Rasp

AS-->创建项目(慢)和打开项目(慢)等需要注意的问题

Android Studio 创建新项目的时候,会在进度条的界面滞留很久. 有时候一天都卡在这. 打开其它项目有些时候,也会出现这种情况. 主要的原因就是, 此过程正在 下载对应版本的 gradle. 如果网络杯具的话, 呵呵-(千万别砸电脑) 查看对应的gradle版本: 如果是打开其它项目, 那么这个版本查看的方式是: 项目根目录下的gradle文件夹:  找到gradle-wrapper.properties文件:  打开这个文件:  可以看到, 当前项目使用的版本是 2.10-all;

www.beishuo.net 网站打开异常慢的原因

现象:客户投诉http://www.beishuo.net/ 网站在移动线路下打不开或者打开异常缓慢(墨绿色是服务器向客户端发送数据的时间,显得非常耗时)分析:这个CASE比较有意思,我在用科来分析数据包的时候发现服务器的重传率非常高,普遍达到12%以上,如下图,一个450K的内容,花了整整1分3秒种才接收完毕,重传率高达12%,这也上上图墨绿色客户端接收时间超长的原因由此我判断,要么是服务器自身问题,要么是线路问题导致丢包:那么如何做进一步判断呢?步骤1:我尝试在电信线路下面尝试打开该网站发现