解决电信 IPv6 访问部分网站异常
为什么折腾
广东电信已分配 IPv6 到宽带,拨号后可以拿到一段 /60 的 IPv6。在 NAS 上 yum 用外网源更新起来几乎能跑上百兆,真爽。
可是爽没多久就发现,国内网络出问题了。微信朋友圈图片经常刷不开,微信视频视频加载不出来。微博打开要等半天,IPv6 连接失败后回落 IPv4 才能打开,百度贴吧、腾讯、七牛 CDN 的部分节点 IPv6 也是有解析但 IP 不能连接。
例如 weibo.com 的连接情况如下:
> curl -v -k https://[2400:89c0:1053:3::18] --connect-timeout 5
* Trying 2400:89c0:1053:3::18:443...
* Connected to 2400:89c0:1053:3::18 (2400:89c0:1053:3::18) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* Operation timed out after 5001 milliseconds with 0 out of 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 5001 milliseconds with 0 out of 0 bytes received
放着这么好的国际线路真的不想放弃 IPv6,试了很多方案,最终敲定 PowerDNS 用来屏蔽电信 IPv6 解析结果来解决。
开工
DNS 最好是有两台,家里有一台 NAS,还有个吃灰树莓派,赶紧开起来安装 PowerDNS 递归服务器版本。
使用 yum 或者 apt 安装最新版本的 PowerDNS 递归版,recursor.conf 配置文件写
local-address=0.0.0.0
allow-from=192.168.0.0/16
lua-dns-script=ipv6.lua
观察一圈有问题的域名,解析出来的电信 IPv6 基本是 240e:: 的段以及 2400:89c0:: 和 2400:5280:: 这三个。使用 lua hook 取出 AAAA 解析结果,匹配前缀是这几个就把结果清空返回即可。代码如下:
function postresolve(dq)
if dq.qtype == pdns.AAAA then
local records = dq:getRecords()
for key, value in pairs(records) do
local ipv6 = value:getContent()
local prefix1 = string.sub(ipv6, 1, 4)
if prefix1 == "240e" then
dq.appliedPolicy.policyKind = pdns.policykinds.NODATA
return true
end
local prefix2 = string.sub(ipv6, 1, 9)
if prefix2 == "2400:89c0" or prefix2 == "2400:5280" then
dq.appliedPolicy.policyKind = pdns.policykinds.NODATA
return true
end
end
end
return false
end
上述代码需要在 PowerDNS 4.4 以上版本使用,搞定之后把 DHCP 的 DNS 设置到 NAS 和树莓派的内网 IP 上。现在开始享受超丝滑的 IPv4 + Ipv6 吧!
偶尔也给微博提个反馈提高提高他们的质量:)