You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Nginx中使用动态DNS而非IP地址配置访问白名单?

如何在Nginx中使用动态DNS而非IP地址配置访问白名单?

这个问题我之前也碰到过,Nginx本身确实不支持直接在allow指令里写动态域名——一方面allow只认IP/IP段,写域名会直接报配置错误;另一方面就算能解析,Nginx也只会在启动或重载配置时把域名解析成IP缓存起来,之后不会自动刷新,完全满足不了动态IP的需求。下面给你两个可行的解决方案,优先推荐第一个,不用折腾额外模块:

方法一:用Geo模块+定时脚本自动更新白名单

这是最通用的方案,利用Nginx原生的geo模块配合定时任务,定期解析动态DNS的IP并更新Nginx配置,然后重载服务。

步骤1:创建动态IP的Geo配置文件

先新建一个专门的配置文件来存储动态IP的判断规则,比如/etc/nginx/conf.d/geo_work_ip.conf

geo $is_work_ip {
    default 0;
    # 这里的IP会由脚本自动生成,初始为空也没关系
}

步骤2:修改虚拟主机配置

在你的站点配置里,用satisfy any来结合固定白名单和动态IP判断(satisfy any表示只要满足任意一个允许条件就放行):

server {
    # 你的其他配置(监听端口、根目录等)...

    # 开启"任意条件满足即允许"模式
    satisfy any;

    # 固定IP白名单(原来的静态IP)
    allow 127.0.0.1;
    allow 192.168.1.0/24;
    allow 123.456.789.102/32;
    deny all;

    # 动态IP判断:如果是工作IP则允许
    if ($is_work_ip = 1) {
        allow all;
    }

    error_page 403 =444;
    # 其他配置...
}

步骤3:编写自动更新IP的脚本

创建一个shell脚本/usr/local/bin/update_work_ip.sh,用来解析动态DNS域名、更新Geo配置并重载Nginx:

#!/bin/bash

# 替换成你的动态DNS域名
DDNS_DOMAIN="dansworkip.ddnsfree.com"
# 刚才创建的Geo配置文件路径
GEO_CONF="/etc/nginx/conf.d/geo_work_ip.conf"

# 安装dig命令(如果没装的话)
if ! command -v dig &> /dev/null; then
    apt update && apt install -y dnsutils
fi

# 获取动态域名对应的所有IPv4地址
WORK_IPS=$(dig +short $DDNS_DOMAIN | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$')

# 备份原配置,防止出错
cp $GEO_CONF ${GEO_CONF}.bak

# 重新生成Geo配置内容
echo "geo \$is_work_ip {" > $GEO_CONF
echo "    default 0;" >> $GEO_CONF
for ip in $WORK_IPS; do
    echo "    $ip 1;" >> $GEO_CONF
done
echo "}" >> $GEO_CONF

# 先测试Nginx配置是否合法,没问题再重载
if nginx -t; then
    systemctl reload nginx
    echo "$(date): 成功更新工作IP并重载Nginx" >> /var/log/update_work_ip.log
else
    # 如果配置出错,恢复备份
    cp ${GEO_CONF}.bak $GEO_CONF
    echo "$(date): 配置错误,已恢复备份" >> /var/log/update_work_ip.log
fi

然后给脚本添加执行权限:

chmod +x /usr/local/bin/update_work_ip.sh

步骤4:设置定时任务自动执行脚本

crontab -e打开定时任务编辑器,添加一行让脚本每5分钟执行一次(时间间隔可以根据你的IP更新频率调整):

*/5 * * * * /usr/local/bin/update_work_ip.sh >> /var/log/update_work_ip.log 2>&1

保存退出后,定时任务就会自动运行了,最多5分钟就能同步新的工作IP。

方法二:使用Nginx第三方模块(需编译)

如果你的场景需要更实时的IP解析,可以用ngx_http_rdns_module这个第三方模块,它能在每次请求时实时解析域名并匹配。不过这个模块需要你重新编译Nginx,对于Ubuntu系统来说步骤比较繁琐,适合有一定编译经验的用户:

  1. 先安装编译依赖:apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev
  2. 下载对应版本的Nginx源码和ngx_http_rdns_module模块源码
  3. 编译Nginx时加上--add-module=路径/ngx_http_rdns_module参数
  4. 编译安装后,在配置里用rdns指令来匹配动态域名:
server {
    # 其他配置...
    allow 127.0.0.1;
    allow 192.168.1.0/24;
    allow 123.456.789.102/32;
    rdns on;
    if ($host ~* dansworkip.ddnsfree.com) {
        allow all;
    }
    deny all;
    # 其他配置...
}

不过这种方法会增加每次请求的延迟(因为要实时解析域名),而且需要维护自定义编译的Nginx,不如第一种方案省心。


备注:内容来源于stack exchange,提问作者DanRan

火山引擎 最新活动