也谈wifi断流问题 (by quqi99)

版权声明:本文为博主原创文章,如需转载,请注明出处! https://blog.csdn.net/quqi99/article/details/82346840

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (作者:张华 发表于:2018-09-03)

问题

笔者最近应该是遇到了常听大家说起的wifi断流问题, 新入一款安卓原生系统手机, 但是在使用wifi上网时会感觉到某些APP上网不流畅, 尤其是使用京东APP搜索商品时会总说找不着网络, 但此时显然是有网络的. 为此, 笔者先做了一系统排除性实验:

  • 排除法测试, 使用京东APP搜索商品时说找不着网络, 但使用京东APP的其他功能没有问题, 并且使用京东以外的其他APP也没问题
  • 排除法测试, 切换为4G网络使用京东APP搜索商品正常, 仅仅只是使用WIFI网络时才会出问题.
  • 排除法测试, 去麦当劳使用WIFI确认无问题, 但速度也不快, 但能打开页面.
  • 排除法测试, 难道是家里的WIFI有问题吗? 但换个手机型号使用京东APP搜索商品却又正常.
  • 排除法测试, 难道是VPN的问题? 关掉VPN, 恢复DNS国内设置依然有问题.
  • 排除法测试, 继续换一个没有VPN的干净的OpenWRT路由器依然有问题, 可惜家里没有Non-OpenWRT路由器可供测试.
  • 排除法测试, 路由器上修改802.11g, 802.11n, 802.11ac等设置后问题依旧.
  • 排除法测试, 检查了路由器上的MAC地址是否与其他机器重复, 未发现异常
  • 排除法测试, 使用114.114.114.114作为DNS, 问题依旧
  • 排除法测试, OpenWRT路由器使用tcpdump抓包, 干扰条目过多, 未深入
  • 排除法测试, 现在问题看起来只是发生在这款特定手机型号与特定的OpenWRT路由器与特定的某些APP如京东, 手机刷机到android 8.1与7.1两个版本问题依旧.
  • 排除法测试, google搜索大量京东或别的某些应用在各种手机型号上出问题的帖子, 试着更改帖子中的各种切换手机配置的操作, 如不对京东使用电源优化,问题依旧.
  • 排除法测试, 绝大多数时候打不开京东的这个搜索商品的功能, 但极少数情况又能打开, 但非常慢, 使用别家的wifi网络时也是非常慢, 很难说清楚现象.

解决

上述一系列排除性测试让我相信该问题仅和我使用特定的手机型号, 使用特定的OpenWRT路由器, 使用特定的某些APP如京东有关.
京东APP, 一个上层应用而已, 理论上只有下列几个因素会影响到上层应用:

  • DNS
  • IPv6/IPv4 fallback
  • MTU
    理论让我将目光回到MTU, 修改OpenWRT路由器WAN口的MTU=1492后问题依旧.继续深挖:
  • 路由器背后的手机操作系统应该有/proc/sys/net/ipv4/ip_no_pmtu_disc=0让手机可以根据pmtu来确实应用所需的mss值. 遗憾地是, 手机没有root, 无法检查此项值.
  • OpenWRT路由器tcpdump抓包, 看到的mss值确实不小. 既然无root权限无法修改手机的ip_no_pmtu_disc参数, 那有没有方法直接修改OpenWRT路由器强迫修改mss值呢?
    OK, 在路由器上添加如下两个命令, 问题就这么解决了:
#iptables -A FORWARD -j ACCEPT
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

root@OpenWrt:~# iptables-save |grep mss
:mssfix - [0:0]
-A FORWARD -j mssfix
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A mssfix -o pppoe-wan -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "wan (mtu_fix)" -j TCPMSS --clamp-mss-to-pmtu

root@OpenWrt:~# tcpdump -ni br-lan src host 192.168.99.194 and dst host 111.13.24.129 and dst port 443
06:37:42.085674 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [S], seq 140081180, win 65535, options [mss 1460,sackOK,TS val 8629819 ecr 0,nop,wscale 8], length 0
06:37:42.092397 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [.], ack 2370816066, win 343, length 0
06:37:42.095245 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [P.], seq 0:173, ack 1, win 343, length 173
06:37:42.141194 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [.], ack 1453, win 354, length 0
06:37:42.141396 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [.], ack 2905, win 365, length 0
06:37:42.141536 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [.], ack 3472, win 377, length 0
06:37:42.147373 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [P.], seq 173:491, ack 3472, win 377, length 318
06:37:42.185607 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [P.], seq 491:1736, ack 3714, win 388, length 1245
06:37:42.194932 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [P.], seq 1736:1767, ack 4065, win 388, length 31
06:37:42.195258 IP 192.168.99.194.39494 > 111.13.24.129.443: Flags [R.], seq 1767, ack 4065, win 388, length 0

总结

这款手机的操作系统没有设置ip_no_pmtu_disc参数去协商mss值, 而OpenWRT路由器刚好缺一条iptables rule (iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu), 这样遭遇了pppoe的1492 MTU问题.
换句话说, 当我外出时, 如果所连的路由器没有加这条设置, 那么这个问题仍然又遇到. 手机操作系统ip_no_pmtu_disc设置才能彻底解决某些应用wifi网络不能上网的问题.

另一个案例

openstack虚机上再创建docker容器, 因为是vxlan网络虚机的mtu=1450, docker0的mtu如果为1500时将导致docker container无法通信.
当mtu配置不正确时此时需要依赖mss, 此时计算节点充当的是路由器它发现此情况(不能将docker container发出的mtu=1500的包发出时)应该发ICMP error到docker container, 或者openstack vrouter应当做这件事情.

docker container错误的具体表现是无法下载, 此时, 最可能的情况时, 最大的包到达openstack vrouter后, 它从external interface收到mtu=1500的包并尝试分片发给虚机, 失败后将发ICMP error到外部下载服务器. 此时:

1, 当non-DVR时, l3-agent上的snat-xxx确实向外部下载服务器发出了ICMP error:

11:45:04.873959 fa:16:3e:c5:b3:ed > fe:54:00:36🆎b4, ethertype IPv4 (0x0800), length 590: 100.64.1.1 > 120.146.233.220: ICMP 103.245.215.9 unreachable - need to frag (mtu 1450), length 556

2, 当DVR时, FIP移到了计算节点上, 此时是qrouter-xxx, 但是这个ns没有default route,

root@maas-node02:~# ip -n qrouter-1752c73a-be9f-4326-97cc-99dbe0988b3c rule show
0:	from all lookup local 
32766:	from all lookup main 
32767:	from all lookup default 
57481:	from 103.245.215.14 lookup 16 
80000:	from 103.245.215.0/28 lookup 16 

root@maas-node02:~# ip -n qrouter-1752c73a-be9f-4326-97cc-99dbe0988b3c route show table 16
default via 169.254.106.115 dev rfp-1752c73a-b 

root@maas-node02:~# ip -n qrouter-1752c73a-be9f-4326-97cc-99dbe0988b3c route show 
103.245.215.0/28 dev qr-ec03268e-fb proto kernel scope link src 103.245.215.1 
169.254.106.114/31 dev rfp-1752c73a-b proto kernel scope link src 169.254.106.114 

只有再添加下列默认路由之后, DVR qrouter-xxx’s才能将ICMP error发出去, 这样才可能去使用mss,

root@maas-node02:~# ip -n qrouter-1752c73a-be9f-4326-97cc-99dbe0988b3c route add default via 169.254.106.115 dev rfp-1752c73a-b 

所以这样造成的问题就是, non-DVR虚机上运行docker container没问题, 而DVR虚机上运行docker container有问题. 解决办法有三个:

1, 修改docker0的mtu=1450, 我们不能修改bridge的mtu, 但可以往docker0里再添加一个tap, 这样bridge的mtu将取决于tap mtu的最小值.
2, 计算节点上运行:

iptables -t mangle -A FORWARD -o ens3 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu

3, to increase the global-physnet-mtu to 1550 to allow the real tenant network MTU to be 1500.
注: 沿路的交换机也要配置相应的MTU, 特别是如果交换机配置的MTU过小, 那么ICMP error直接就没有提示就被drop( 千万注意: 过来的包的MTU如果大于设备的MTU值才会分片分段, 如果是小于的话直接就DROP掉了, 这个参数net.ipv4.tcp_mtu_probing也可以探测这种情况)了这样导致MTU没配对之后也无法利用MSS, 这种问题更不好查. 另外, 也发现IPv6情况下的ICMPv6没有被ip6table rule允许的情况.

阅读更多
换一批

没有更多推荐了,返回首页