安卓自定义转发客户端数据包不可达相关问题(MTU、MSS)

最近在开发PPTP服务器,客户端和服务器的通信已经可以,剩下数据包转发逻辑。为了验证这套转发逻辑是否有效,我在安卓开发了自定义转发客户端。由于是自己写的通信协议,我客户端和服务器直接使用udp传递数据包。udp内容就是ip数据包。
开始以为,udp理论支持65535个字节,数据超过MTU会自动使用ip的分片逻辑(不保证一定可达,但传递ip数据包性质一样,所以不太关心)。然而,出现的问题就在这天真的想法!

第一次设计后,测试了icmp、udp、tcp、http都能够转发。额,插一句,对于服务器如何转发数据包问题由于不是讨论的重点,所以这篇文章就不展开。简单来说,我是基于防火墙的nat来构建虚拟网,之后就是ip层协议开发(ip数据包发送和过滤)。
然而,当我投入压测时,发现https的请求都失败了!理论是不可能的,毕竟这是应用层上的东西,跟ip层转发无关啊。最后没办法,把服务器转发的pcap和客户端转发的pcap一一比较。结果发现服务器收到大于MTU的数据包(甚至超过两倍),而客户端缺失这些数据包。问题已经很明显,就是数据包缺失。为何服务器的大数据包无法到达客户端?后面我单独测试了服务器和客户端的udp传输,发现大于MTU的数据包都无法到达。换句话说,udp理论可行的ip分片不起作用。我看了客户端数据包的分片属性,都是指明不可分片!因此,出现不可达问题就是udp不支持分片(客户端),服务器无法发送大数据包给客户端,继而无法正常通信。
另外,先不管其它服务器返回大数据包问题,tcp通信时会基于MSS协商分片大小,为何失败后,没有减小数据包重传?这个就是另外一个重点,MTU大小!由于MSS是基于MTU计算的(去除头部大小后剩下的),在启动客户端时,若没有配置MTU,那么它就会使用网卡MTU。由于我是通过udp传递ip数据包的,若ip层不支持分片,那么转发的ip数据包只能是udp的数据体最大值(MTU-udp头部-ip头部),而这个也是客户端最大分片大小,即MTU。

第二次设计时,配置客户端的MTU等于或小于udp的数据体最大值(MTU-udp头部-ip头部),这时测试https就可以使用了。这里大家可能会疑惑,为何只在测试https时出现问题,其它不会。其实,在测试其它协议时,由于使用的数据包都非常小,间接避开了上面的问题。然而,https连接建立时,会传递证书(server hello过程),而这个证书恰恰超过MTU。同时,我测试一些服务器发现,它们第一次发送的数据包大小都不会按照协商的MSS,而是发送大数据包(超过双方MSS最大值)。当发现不可达时,才采用协商的MSS。由于我的服务器刚好支持分片,所以对方的大数据包能够达到我这边,然而我的就无法下发给客户端。

这里同时衍生一个很隐蔽的通信问题。之前开发时,有的服务器跟windows和android通信时,经常出现连接不可用,而换成mac和ios就可以。其中一个原因,就是服务器的分片策略和重传机制出现问题,导致经常发送大数据包给对方。这时,通信问题就被迫转移到客户端的大数据包支持上。这类问题需要服务器和客户端同时抓包比较才能判断。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值