最近发现我服务器的nginx有很多错误日志,日志显示的错误是请求上游服务错误,而上游服务的请求IP是ipv6,所以是因为上游不支持ipv6请求导致的错误。于是我经过了一系列求助,彻底解决了这个问题,在此记录一下。

问题现象

背景

首先来看看这个问题出现的背景。

我博客的图片都是使用七牛云当作图床,为了在引用图片的时候显示本地域名,我的服务配置文件中添加了一个配置块如下:

# 图床映射,添加自己的图床地址即可
location ^~ /cdn/ {
    proxy_pass http://pic.tendcode.com/;
}

正如配置注释的意思,我这里就是添加一个地址的反向代理,将 /cdn/ 开头的地址转到 http://pic.tendcode.com/ 去请求,就是一个很简单的地址转发。

也就说我博客里面类似这种地址 /cdn/article/2307/vmware-net-1.png 会被转发成 http://pic.tendcode.com/article/2307/vmware-net-1.png 进行请求。

报错

基于上面的配置,最近发现nginx日志里面有大量的错误日志,日志如下:

2023/08/03 14:35:35 [error] 22413#22413: *5920 connect() to [240e:97d:10:1401::40f]:80 failed (101: Network is unreachable) while connecting to upstream, client: 112.10.184.241, server: tendcode.com, request: "GET /cdn/article/2307/frp.png HTTP/1.1", upstream: "http://[240e:97d:10:1401::40f]:80/article/2307/frp.png", host: "tendcode.com", referrer: "https://tendcode.com/"

从这个日志很容易看到是请求 /cdn/ 这种地址的时候上游请求到了ipv6但是又请求不通导致的,也就是命中了我配置的那个规则,并且把域名解析成了ipv6去请求的。

所以这个问题的本质就是当反向代理的目标是域名的时候,可能把域名解析成ipv6,如果此时上游服务不支持ipv6请求,就会导致请求超时。

解决方案

解决思路

问题弄清楚了,我理解的解决思路有两个方向,第一就是想办法让域名不要解析成ipv6而是仅仅解析到ipv4,这个方向是我可以配置解决的;第二个方向是上游支持ipv6就行,这个方向明显不行,因为上游不是我的服务,我无法控制,直接放弃这个方案。

其实后来真正解决这个问题之后,我知道了其实是有三个解决方案的:

  1. 本地配置nginx,关闭域名解析的ipv6,保证每次请求域名只使用ipv4,方案验证可行
  2. 七牛云上面修改域名解析,只配置ipv4,方案可行,也是最终使用的方案
  3. 七牛云上游服务支持ipv6请求,🙅不可行,我无法控制,不过可能跟七牛云的人反馈能解决

nginx配置resolver

首先说一下第一种解决方案,就是nginx里面使用resolver配置,这个配置可以指定dns解析,以及配置是否开启ipv6,具体配置如下:

# 禁用域名解析成ipv6
resolver 8.8.8.8 valid=30s ipv6=off;


# 为了不解析成ipv6而设置
set $backend "pic.tendcode.com";

# 图床映射,添加自己的图床地址即可
location ^~ /cdn/ {
    proxy_pass http://$backend/;
}

这里第一个命令 resolver 8.8.8.8 valid=30s ipv6=off; 是配置了域名解析的dns,还有每次重新解析的间隔时间,然后就是关闭ipv6。

第二个命令 set $backend "pic.tendcode.com"; 非常有必要,这个为啥要把域名单独使用set赋值一下我不是很清楚,但是最开始我没有做这个事情而是只添加第一个命令的时候发现根本不起作用,后来在v2ex上面提问有人告诉我要set设置一下才行,大概就是保证每次请求域名的时候都是重新经过我设置的那个resolver规则,不然不会生效的。

经过验证,这个配置方案是可行的,所以如果遇到域名解析成ipv6导致请求失败的时候可以使用这种方案来关闭ipv6解析。

七牛云修改域名管理

虽然自己使用nginx配置的方式解决了问题,但是我看到v2ex的老哥跟我说可能七牛云上面有配置可以只设置ipv4,于是我去看了我的存储空间的配置,发现的确有配置可以仅使用ipv4,之前的配置默认是ipv4和ipv6都支持的。

进入空间管理的域名管理里面,查看域名详情就可以看到IP协议可以修改:

七牛云域名管理

我这里就是使用的这个方案解决的问题,算是从源头就解决吧。

七牛云上游支持ipv6

这个方案需要跟七牛云反馈,我问题都解决了,所以也就没联系七牛云的客服。

总结

这篇文章主要想分享的是使用nginx的resolver配置来自定义域名解析的IP协议,可以规避域名解析到ipv6导致访问失败的问题。并且,经过验证,这个配置不能单独配置,需要配置set将域名赋值给变量来使用。

版权声明:如无特殊说明,文章均为本站原创,转载请注明出处

本文链接:https://tendcode.com/subject/article/nginx-resolver/

许可协议:署名-非商业性使用 4.0 国际许可协议