调整网络后安卓手机出现上网“卡”问题的解决

家里网络使用光猫桥接模式,通过RouterOS路由进行拨号,开启了IPv6。



原来一直使用第1种方案,下接一个WIFI无线路由器,无线路由是接到其WAN口上的,电脑和手机上网一直很正常。

近期调整网络,先是用方案2,无线路由改接到其LAN口上的;又用了AC+AP方式,通过方案3,将AP直接接在路由器下。方案2、3都遇到一个问题,就是安卓手机浏览器打开网页,微博、知乎等加载图片视频的速度都明显变慢,体验起来就像是网络时延变大,变得很“卡”。

检查发现在方案2、3下,在RouterOS上关闭了IPv6后变正常了,看起来像是开启IPv6造成的,由于IPv6访问速度较慢导致,但奇怪的是原来方案1也是一直使用IPv6的,却一直很正常的。

找区别,方案1手机上网是使用了RouterOS和WIFI的两次NAT,IPv4 DHCP和IPv6无状态分配都是使用WIFI无线路由器自带的;方案2、3是下级设备LAN接入上级设备LAN,直接使用RouterOS的NAT、IPv4 DHCP和IPv6 ND。NAT、ND感觉不是问题,疑问指向了DHCP。

RouterOS在IP>DNS中设置了2个IPv4和2个IPv6的DNS;IP>DHCP Server中配置了2个IPv4的DNS;IPv6>ND开启进行无状态地址分配,同时启用了Advertise DNS。




我是小米的安卓手机,在这种情况下,接入WIFI后会获取到RouterOS中IP>DHCP Server中配置的2个IPv4 DNS,还会叠加获取到IP>DNS中设置的2个IPv6的DNS;由于这2个IPv6 DNS响应比较慢,就导致手机感觉的“卡”。而Windows10不受这个影响,只会获取到IP>DHCP Server中配置的2个IPv4 DNS。安卓手机可以使用WiFiman APP在“状态”中查看当前手机获取到的配置情况。

简单说,由于启用了IPv6,当安卓手机的网络和APP都支持IPv6时,如果IPv6 DNS响应慢导致域名解析受影响,最后就出现手机上网的各种“卡”。之前关闭IPv6,导致IPv6链路失效,RouterOS也不会下发IPv6的DNS了,一切回归IPv4,所以也就正常了。

保留IPv6且不卡的解决方法,在RouterOS上配置,三选一
1、IP>DNS删除IPv6的DNS
2、IPv6>ND关闭Advertise DNS
3、寻找更好的IPv6 DNS替换IP>DNS设置


如何在BIND9中彻底禁用递归,限制只解析本机域名

作为域名NS记录指向的DNS服务器,不同于开放给公众的DNS服务器,不需要提供本机配置域名之外的域名解析。当DNS解析的域名本机中没有的时候,就会发起递归(recursion)或者转发(forward)到远程DNS去查询。

递归:本机直接从根服务器上寻找对应域名的NS记录,再由本机到NS指向的服务器中查询记录
转发:本机将解析请求转发到指定的服务器去解析,将转发服务器的响应结果直接反馈给查询者

BIND9默认打开递归查询和关闭转发功能,如何彻底关闭递归,就成了主要问题,设置中还发现一些有趣的问题。

测试平台:Debian 5.0.4
BIND9版本:BIND 9.5.1.dfsg.P3-1+lenny1

配置文件:/etc/bind/named.conf.options
1、只设置“recursion no;”
C:\>nslookup
> server 192.168.99.104
> www.google.com
Server: [192.168.99.104]
Address: 192.168.99.104

Name: www.google.com
Served by:
- K.ROOT-SERVERS.NET
- I.ROOT-SERVERS.NET
- L.ROOT-SERVERS.NET
- B.ROOT-SERVERS.NET
- M.ROOT-SERVERS.NET
- G.ROOT-SERVERS.NET
- F.ROOT-SERVERS.NET
- A.ROOT-SERVERS.NET
- J.ROOT-SERVERS.NET
- C.ROOT-SERVERS.NET


服务器虽然没有进行递归查询,但是还是响应了客户端根服务器的地址。如何彻底关闭呢,这个问题折腾了很久,未果。BIND9的文档(http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html)中有这样的描述:

recursion
If yes, and a DNS query requests recursion, then the server will attempt to do all the work required to answer the query. If recursion is off and the server does not already know the answer, it will return a referral response. The default is yes. Note that setting recursion no does not prevent clients from getting data from the server's cache; it only prevents new data from being cached as an effect of client queries. Caching may still occur as an effect the server's internal operation, such as NOTIFY address lookups. See also fetch-glue above.

allow-recursion
Specifies which hosts are allowed to make recursive queries through this server. If not specified, the default is to allow recursive queries from all hosts.
Note that disallowing recursive queries for a host does not prevent the host from retrieving data that is already in the server's cache.

可问题是,这个cache如何关闭呢?文档里没有详细描述,找了很久,发现个配置allow-query-cache,这个似乎在官方的文档中没有呢?


2、同时设置“recursion no;”和"allow-query-cache { none; };"
C:\>nslookup
> server 192.168.99.104
> www.google.com
Server: [192.168.99.104]
Address: 192.168.99.104

*** [192.168.99.104] can't find www.google.com: Query refused

彻底关闭了递归查询,拒绝响应,达到目的。


3、只设置"allow-recursion { none; };"
测试结果同2

这是在后来改配置的时候偶尔发现的,allow-recursion貌似不需要关闭cache。一直认为allow-recursion和recursion是完全一样的,看来不是这样。当然,这个也许是我的测试有限。


附1:转发BIND9默认是关闭的,如果需要声明可以在named.conf.options这样写
forwarders {};
forward only;

附2:如何关闭BIND9对于ls命令功能,对于有slave或者特殊需要的,用ip替换none即可
allow-transfer { none; };