每天进步一点点:curl 与IPv6的问题

好久以前使用he.net的DDNS服务配合路由器的NAT功能实现在任何地方访问家里的网络,用起来还算方便,好多年过去,一直没让我失望。

image.png
(图源 :pixabay)

解析失败

不过因为这大半年一直没有出门,所以有半年多时间没有用过这个功能了,昨天无意中测试一下,发现竟然无法连接到家里的网络了,提示是拒绝连接。

要排查的第一个问题就是看一下DDNS解析出来的IP是否正确,命令行ping一下域名的IP,再与在线显示IP工具中显示的IP对比一下,果然不是同一个IP。那么问题来了,是什么原因导致的IP不一致呢?

脚本出错

回头看一下DDNS更新IP的脚本:

*/5 * * * * curl "https://dyn.dns.he.net/nic/update" -d "hostname=xxx.xxxx.com" -d "password=XXXXXX" -k

非常简单的脚本,并且一直很好用,不应该出问题才对。那么我直接执行一下试试看:

curl "https://dyn.dns.he.net/nic/update" -d "hostname=xxx.xxxx.com" -d "password=XXXXXX" -k

结果竟然出现如下错误:

curl: (7) Failed to connect to dyn.dns.he.net port 443: No route to host

排查错误

这看起来貌似是DNS解析的问题,然而我使用wget访问https://dyn.dns.he.net/nic/update却可以正常解析。这就让我很晕了,为啥curl找不到路由,而wget却可以?

不过看wget的提示信息,我注意到上述域名多了个IPv6地址,那么会不会是IPv6地址导致的呢?毕竟我的机器没有配置IPv6信息:

Reveal spoiler

image.png

于是测试了一下加-4参数来强制使用IPv4地址访问,发现返回信息一切正常。

curl -4 "https://dyn.dns.he.net/nic/update" -d "hostname=xxx.xxxx.com" -d "password=XXXXXX" -k

关于-4(--ipv4),手册中解释如下:

If curl is capable of resolving an address to multiple IP versions (which it is if it is IPv6-capable), this option tells curl to resolve names to IPv4 addresses only.

除此之外,我在另外一台OS版本较新的主机上测试(不加-4),提示信息为:noipv6,这个返回信息就友好多了。

解决问题

既然知道是IPv6的问题我又不想/也不知道如何配置IPv6,那么就在脚本中加上-4参数好了,问题就算是解决了。

至于为何之前脚本一直好用,我猜测可能是之前curl版本低或者是dyn.dns.he.net这个域名没有配置IPv6的缘故,也懒得去调查到底是谁的原因了。

略为遗憾的是,curl竟然不能像wget那样自动选择,导致我遇到这个问题,还浪费我大半天的时间。😡