TCP - 一个NAT问题引起的思考

1 问题

当服务器同时开启tcp_timestamps和tcp_tw_recycle选项时,会导致客户反馈连接成功率降低的情况。
but why ???

2 公网NAT的存在

NAT的全称是:Network Address Translation
一个具体的例子就是家用的局域网络。
当使用一台无线路由器进行上网拨号后,其他的终端设备只要连接进入该无线路由器的WiFi
网络内就可以访问外网了。此时正是NAT在发挥作用。
每一台终端设备在接入无线路由器后,只是获得一个局域网IP地址,而当你在百度输入我的IP的时候
你看到的IP地址则是你无线路由器的公网IP地址。家用无线路由器完成的一个主要工作正是将终端
的局域网IP地址进行NAT转换为公网IP地址。

从上面这个简单的例子可以看到NAT在真实的互联网中是普遍存在的,比如你所在学校,单位都会一定程度上的使用NAT机制。

3 Per-host PAWS机制

这篇介绍TCP timestamp
的文章中提到了一种针对per-host的PAWS机制。这种机制要求所有来个同一个host IP的TCP数据包的
timestamp值是递增的。当收到一个timestamp值,小于服务端记录的对应值后,则会认为这是一个过期的数据包,然后会将其丢弃。

4 解答问题

至此就不难解释为什么在同时开启tcp_timestamp和tcp_tw_recycle时,会遇到客户反馈连接成功率降低的情况了,基本的逻辑如下:

1. 同时开启tcp_timestamp和tcp_tw_recycle会启用TCP/IP协议栈的per-host的PAWS机制
2. 经过同一NAT转换后的来自不同真实client的数据流,在服务端看来是于同一host打交道
3. 虽然经过同一NAT转化,但由于不同真实client会携带各自的timestamp值
因而无法保证整过NAT转化后的数据包携带的timestamp值严格递增
4. 当服务器的per-host PAWS机制被触发后,会丢弃timestamp值不符合递增条件的数据包

解决办法就是不建议同时开启tcp_timestamp和tcp_tw_recycle。
那到底怎么配置?

开启tcp_timestamp,但不要开tcp_tw_recycle  
开启tcp_timestamp,但不要开tcp_tw_recycle  
开启tcp_timestamp,但不要开tcp_tw_recycle  

因为timestamp有更多其他的作用,而tcp_tw_recycle本身就是依赖于timestamp的(因为timestat)。在不开启timestamp的情况下,单独开启tcp_tw_recycle并没有什么用
其实上述强调三遍的配置,正是目前Linux的默认配置。
所以说啊,不真正搞懂内核的参数选项,就不要盲目修改。尤其是在官方文档对tcp_tw_recycle已经强调了不要盲目修改的情况下

那为什么有人推荐同时开启tcp_timestamp和tcp_tw_recycle呢?
因为同时开启后,能够更快的回收TIME-WAIT状态的socket    <== 这也正是PAWS从per-conn在配置后扩展到per-host的目的  
只可惜逻辑是对的,但是没有考虑到公网广泛存在的NAT机制可能带来的问题。  

5 源码细节分析

这部分是linux 3.10源码部分的分析,算是对于以上理论分析提供的依据,不关系细节的话可以忽略本节

// tcp_v4_conn_request(), net/ipv4/tcp_ipv4.c line 1551
if (tmp_opt.saw_tstamp &&      // 是否见到过tcp_timestamp选项
    tcp_death_row.sysctl_tw_recycle &&   // 接着判断是否开启recycle
    (dst = inet_csk_route_req(sk, &fl4, req)) != NULL &&    // 最终判断saddr是否有相关记录在route表中
    fl4.daddr == saffr) {
    if (!tcp_peer_is_proven(req, dst, true)) {  // 如果这个建连请求不能被proven,则会被丢弃
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
        goto drop_and_release;
    }
}

// tcp_peer_is_proven() net/ipv4/tcp_metrics.c line 536
// 负责判断接收到的request请求的timestamp是否符合要求,最重要的一段代码如下
if (tm &&
    // 判断保存tcpm_ts_stamp值是否有效,TCP_PAWS_MSL=60
    (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL &&
    // 如果记录值大于当前收到的req中的timestamp值,则丢弃。TCP_PAWS_WINDOW=1
    (u32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW) {
        ret = false;
}

至此可以看到:在tcp_timestamp和tcp_tw_recycle同时开启时,会触发Linux的per-host的PAWS机制

接下来分析开启tcp_tw_recycle和tcp_timestamp时,是怎么快速回收TIME-WAIT的

// tcp_time_wait() net/ipv4/tcp_minisocks.c  line 267
...
// ts_recent_stamp依赖于timestamp选项的开启,可进tcp_minisocks.c验证  
if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
    recycle_ok = tcp_remember_stamp(s);
...
// 如果能够recycle,则使用更短的rto作为timeout,从而更快回收TIME-WAIT
if (timeo < rto)
    timeo = rto;
if (recycle_ok) {
    tw->tw_timeout = rto;
} else {
    tw->tw_timeout = TCP_TIMEWAIT_LEN;
    if (state == TCP_TIME_WAIT) 
        timeo = TCP_TIMEWAIT_LEN;    
}
inet_twsh_schedule(tw, &tcp_death_row, timeo, TCP_TIMEWAIT_LEN);

// tcp_timewait_state_process() net/ipv4/tcp_minisocks.c line 94
// 另一条进入time-wait的路线有类似的代码
if (tcp_death_row.sysctl_tw_recycle &&
    tcptw->tw_ts_recent_stamp &&
    tcp_tw_remember_stamp(tw))
        inet_twsk_schedule(tw, &tcp_death_row, tw->tw_timeout,
                           TCP_TIMEWAIT_LEN);
else
        inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
                           TCP_TIMEWAIT_LEN);


参考资料

Documentation: ip-sysctl.txt
RFC 1323: TCP Extensions for High Performance

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容