前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >细说TCP的MSS选项(2)

细说TCP的MSS选项(2)

作者头像
glinuxer
发布2019-04-10 14:58:16
2.4K0
发布2019-04-10 14:58:16
举报
文章被收录于专栏:专注网络研发专注网络研发

上周因为发烧没办法坚持每“周一”更 —— 再次感叹“每周一更”这个名字,先给大家道声抱歉。

在上一篇细说TCP的MSS选项(1)中给出的了影响MSS的因素:一般都是由出口路由的MTU决定。但这只是TCP的syn报文的情况,今天就要分析syn+ack报文中的MSS的情况。

首先我们做个实验,检测本地的MTU是否会影响到对端的MSS。

  1. 本地的出口网卡MTU默认为1500时,访问www.baidu.com。抓包结果如下:

我本地出口网卡的MTU为1500,减去40,即syn报文中MSS值,1460。 而百度服务器回复syn+ack报文的mss为1400。

  1. 使用ifconfig设置本地网卡的MTU为1000时,再次访问www.baidu.com。抓包结果如下:

我本地出口网卡的MTU为1000,减去40,即syn报文中MSS值,960。 而百度服务器回复syn+ack报文的mss值也为960?!

从这个测试结果看,syn+ack报文的MSS值还要受到syn报文的MSS值影响,可能会取本地计算结果的MSS值和syn报文中的MSS值中的较小值。

为了确定这个结果,让我们从内核源码中寻找答案。函数tcp_make_synack是用于生成syn+ack报文,其中

tcp_mss_clamp用于获得syn+ack报文的mss值。

而tcp_mss_clamp仅是使用user_mss(该TCP套接字配置的MSS选项)与抽口dst的MSS进行对比。只有设置了user_mss,且其值又小于dst的MSS时,才会使用user_mss,否则syn+ack报文就是dst的MSS值——也就是前文中所述,出口路由的MTU-40。

这样分析,syn+ack报文的MSS值,在通常情况下,也是由出口网卡的MTU决定,即MTU-40。那么为什么我修改本地的MTU,会影响到百度服务器的syn+ack报文中的MSS值呢? —— 说实话,我为这个问题困扰了半天,来回的翻看内核的相关代码,担心遗漏了其它情况。但是内核回复syn报文的逻辑还是相对清晰的,从入口函数tcp_v4_conn_request开始,直到tcp_v4_send_synack,只有这个函数与syn+ack的MSS值相关。这时,就要相信自己对代码的分析没有问题。

原始内核产生的syn+ack中的MSS同样只跟出口dst的MTU有关。

为了验证自己的想法,在本地用nc来做个简单的服务端,进行测试。抓包结果如下:

客户端的网卡MTU依然是1000,所以syn报文中的MSS还是960。但是syn+ack报文中的MSS没有变化,仍然是默认MTU1500-40,即1460。通过简单的测试,真相也就大白了。

总结一下:

  1. 标准的内核syn+ack报文中的MSS也是由出口路由的MTU-40;
  2. 目前百度公司对syn+ack的MSS做了自己的修改,会取syn报文的MSS和其实际MSS的较小值;BAT中只有百度做了这个修改,其它互联网公司如sina,sohu也没有做这个修改。
  3. 关于百度对MSS的这个修改,我觉得见仁见智。从RFC中的MSS定义上看,MSS是单向生效的。但一般来说,PMTU的值双向基本相同,所以百度做这个修改,是为了更好的兼容性,保证TCP的双方通信正常。当发现对端有较小的MSS值,本端也做最谨慎的处理,判断PMTU会小于本地的MTU。

专注于网络技术开发,坚持“每周一更”~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 LinuxerPub 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档