zoukankan      html  css  js  c++  java
  • 打开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).

  • 相关阅读:
    收藏网站制作常用经典css.div.布局.设计实例打包下载2
    下拉菜单 效果
    鼠标放在一个连接上,会显示图片(类似tooltip)
    收藏网站制作常用经典ajax.prototype.javascript实例打包下载2
    开发速查手册
    Visual Studio 2005 的 101 个示例(转)
    多行文本框限制输入字符长度(跳出窗体提示)
    发一个不用图片实现圆角代码,非常经典
    收藏网站制作常用经典css.div.布局.设计实例打包下载1
    Linux下php动态添加扩展
  • 原文地址:https://www.cnblogs.com/jdonson/p/4760080.html
Copyright © 2011-2022 走看看