一个诡异的 letsencrypt well-known/acme-challenge/ 404 Error

在为 ondutyapp.com 增加SSL支持的时候,照例选择了免费好用的letsencrypt。但在执行命令 sudo certbot --nginx 后,却出现了报错信息。大意就是无法访问well-known/acme-challenge/ 下面的文件,服务器返回404 error,域名无法通过验证。

之前在同一台服务器上为另外一个域名 iduty.me 创建SSL certification的时候,一切顺利。我尝试在Mac chrome上,访问 http://ondutyapp.com/a.html 一切正常,但在服务器console下运行curl -I http://onduty.com/a.html 就返回404。可以确认cerbot失败的原因就是无法访问到ondutyapp.com下面的资源。

第一反应就是检查nginx配置文件,把配置精简到最少,看上去也一切正常,但是问题任然存在。并且在笔记本上访问一切正常,在服务器内部访问就会报404错误。

接下来检查nginx access.log,一条字符串引起了我的注意。

在服务器内部访问网页的时候,客户端请求地址是一个IPv6地址;在Mac浏览器上访问网页的时候,则是正常的IPv4地址。至此,原因找到了。nginx的配置当中没有支持IPv6访问。在nginx配置文件中加入listen [::]:80,就一切正常了。

想到之前,把域名服务器从dnspod迁移到linode,而linode DNS server又是支持IPv6的。google了一把,发现ubuntu下面有一个配置,可以让客户端在访问网站时选择IPv6或者IPv4优先。而在我的这台linode服务器上,默认IPv6优先。所以之前域名服务器选择dnspod的时候,只有对IPv4的支持,一切正常。ubuntu上配置文件在/etc/gai.con, 取消注释以后,就会优先选择IPv4了。

顺便提下,把dns server从dnspod迁移到linode后,解析速度确实快了很多,用https://latency.apex.sh/测试了一下,目测时间从平均800ms减少到300ms。