Nginx 反代 DDNS 域名后 IP 变化访问失效解决方案
家里 NAS 有公网 IP 但不是固定的,使用 DDNS + 云服务器反代后,每次 IP 变化需要手动 reload nginx 的问题及解决方法。
问题场景
- 家里 NAS 有公网 IP,但是动态的(每次重启光猫/路由器就变)
- 在 NAS 上配置DDNS,将动态 IP 绑定到域名
- 在云服务器上用 1Panel + OpenResty/Nginx 做反向代理
- 问题:每次家里 IP 变化后,网站就访问不了了,必须手动 reload nginx 才恢复
原因:Nginx 在启动/重载时会解析域名并缓存 IP 地址,之后一直使用缓存的 IP,不会重新查询 DNS。
问题根源
Nginx 在启动/重载时会解析域名并缓存 IP 地址,之后就一直使用这个缓存的 IP,不会重新查询 DNS。
流程如下:
DDNS 更新 → 域名解析到新 IP → 但 nginx 还在用旧 IP → 访问失败
↓
手动 reload nginx → nginx 重新解析域名 → 恢复正常
解决思路:让 nginx 自动重新解析域名,无需手动干预。
解决方案:使用 resolver + 变量
核心原理
Nginx 的 resolver 指令可以配置 DNS 解析器,配合变量使用 proxy_pass 时,会按照 valid 参数指定的时间重新解析域名。
第一步:在 nginx.conf 中添加 resolver
编辑 /usr/local/openresty/nginx/conf/nginx.conf(1Panel 默认使用 OpenResty):
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# ... 其他现有配置保持不变 ...
# 添加这两行(在 include conf.d 之前)
resolver 223.5.5.5 8.8.8.8 valid=30s ipv6=off;
resolver_timeout 5s;
include /usr/local/openresty/nginx/conf/conf.d/*.conf;
include /usr/local/openresty/1pwaf/data/conf/waf.conf;
# ... 后续配置 ...
}
参数说明:
| 参数 | 说明 |
|---|---|
223.5.5.5 |
阿里云 DNS(国内推荐) |
8.8.8.8 |
Google DNS(备用) |
valid=30s |
DNS 缓存有效期 30 秒,超时后重新解析 |
ipv6=off |
禁用 IPv6 解析(避免不必要的查询) |
第二步:修改反代配置,使用变量
找到反代配置文件(通常在 /usr/local/openresty/nginx/conf/conf.d/ 目录下),或在 1Panel 中:网站 → 反向代理 → 编辑
修改前:
location ^~ / {
proxy_pass http://your-ddns-domain.com:port; # 直接写域名,会缓存 IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# ... 其他配置
}
修改后:
location ^~ / {
# 用变量存储目标地址
set $upstream "your-ddns-domain.com:port";
# proxy_pass 引用变量
proxy_pass http://$upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_http_version 1.1;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
proxy_ssl_server_name off;
proxy_ssl_name $proxy_host;
add_header Strict-Transport-Security "max-age=31536000";
}
关键改动:
set $upstream "your-ddns-domain.com:port";proxy_pass http://$upstream;
第三步:测试并重载 nginx
# 1. 测试配置语法是否正确
docker exec 1panel-openresty nginx -t
# 2. 重载 nginx 使配置生效
docker exec 1panel-openresty nginx -s reload
如果是 1Panel 直接管理,也可以在面板上点击「重载」按钮。
验证效果
配置完成后,当家里 DDNS 更新 IP 后:
- 等待最多 30 秒(
valid=30s设置的时间) - nginx 会自动重新解析域名
- 访问恢复正常,无需手动 reload
手动测试方法:
# 在云服务器上查看当前解析的 IP
dig your-ddns-domain.com +short
# 等家里 IP 变化后,再执行一次
dig your-ddns-domain.com +short
# 然后直接访问网站,应该能正常打开
curl -I https://your-proxy-domain.com
其他方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| resolver + 变量(本文方案) | 配置一次,自动生效;无需额外脚本 | 需要修改 nginx 配置 |
| DDNS 更新后 SSH reload | 不改 nginx 配置;逻辑简单 | 需配置 SSH 免密;每次更新都 reload |
| 使用 IP 而非域名 | 最简单 | IP 变化就失效,不实用 |
推荐度:resolver + 变量 ⭐⭐⭐⭐⭐
常见问题
Q1: valid 时间设多少合适?
30s- 推荐值,平衡响应速度和 DNS 查询频率10s- 更灵敏,但 DNS 查询更频繁60s- 减少查询,但 IP 变化后等待时间更长
Q2: 可以用其他 DNS 服务器吗?
可以,常见的有:
- 阿里云:
223.5.5.5 - 腾讯云:
119.29.29.29 - 114 DNS:
114.114.114.114 - Google:
8.8.8.8
Q3: 配置后访问变慢了?
理论上每次请求不会重新解析(有 30 秒缓存),不应该有明显影响。如果确实变慢,检查:
- DNS 服务器是否可达
resolver_timeout是否设置合理(默认 5s)- 云服务器网络是否正常
总结
核心就三步:
- nginx.conf 加
resolver - 反代配置 用变量
set $upstream+proxy_pass http://$upstream - reload 一次生效
之后 DDNS 更新 IP,nginx 会在 30 秒内自动重新解析。
参考链接: