如何用IPtables规则解决DNS解析IP频繁变更导致的连接超时问题
这个问题我在运维场景里碰到过好多次——本质就是IPtables的规则是静态绑定IP的,一旦域名解析的IP变了,旧规则就失效了,必须手动刷新。下面几个方案按实用性和复杂度排序,你可以根据自己的环境选:
方案1:用ipset + 定时任务动态更新IP(最推荐)
ipset是IPtables的扩展工具,能把一组IP放在一个集合里,IPtables规则直接匹配这个集合就行。我们可以写个脚本定期解析域名的IP,更新ipset集合,不用动IPtables主规则。
步骤:
安装ipset及解析工具:
- Debian/Ubuntu系:
sudo apt install ipset dnsutils(dnsutils提供dig命令用于解析域名) - CentOS/RHEL系:
sudo yum install ipset bind-utils
- Debian/Ubuntu系:
创建ipset集合:
sudo ipset create dynamic_dns hash:ip(如果需要支持IPv6,把集合类型改成
hash:ip6)添加IPtables规则匹配集合:
比如你要允许访问该域名的80/443端口,就添加这条规则(根据实际业务的链和端口调整):sudo iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set dynamic_dns dst -j ACCEPT要是需要允许外部访问到这个域名的IP(比如INPUT链场景),把
OUTPUT改成INPUT,dst改成src即可。编写自动更新脚本:
创建脚本文件/usr/local/bin/update_dns_ipset.sh,内容如下:#!/bin/bash DOMAIN="test.example.com" IPSET_NAME="dynamic_dns" # 获取域名当前的所有IPv4解析结果,过滤掉非IP内容 CURRENT_IPS=$(dig +short $DOMAIN | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$') # 清空集合里的旧IP sudo ipset flush $IPSET_NAME # 将新IP逐一添加到集合 for ip in $CURRENT_IPS; do sudo ipset add $IPSET_NAME $ip done给脚本添加执行权限:
sudo chmod +x /usr/local/bin/update_dns_ipset.sh设置定时任务自动运行:
用crontab配置定时执行,比如每5分钟更新一次:sudo crontab -e在打开的编辑器中添加一行:
*/5 * * * * /usr/local/bin/update_dns_ipset.sh
优点:
- 不需要重启IPtables,仅更新ipset集合,对业务无影响
- 支持多IP解析,能覆盖域名的所有解析结果
- 性能比频繁修改IPtables规则高很多
方案2:切换到nftables(内置动态DNS支持)
如果你还在用传统IPtables,不妨考虑升级到nftables——它是Linux内核官方推荐的下一代防火墙工具,支持直接匹配域名,并且会自动定期刷新DNS解析结果。
步骤:
安装nftables:
- Debian/Ubuntu系:
sudo apt install nftables - CentOS/RHEL系:
sudo yum install nftables
- Debian/Ubuntu系:
编写nftables规则:
编辑nftables配置文件(比如/etc/nftables.conf),添加对应规则:table ip filter { chain output { type filter hook output priority 0; policy accept; # 允许访问test.example.com的80/443端口 tcp dport {80, 443} dname "test.example.com" accept; } }若需要INPUT链规则,在对应的chain下添加即可。
重启nftables服务生效:
sudo systemctl restart nftables
注意:
- 需要Linux内核4.19以上、nftables版本0.9.3以上才能支持
dname域名匹配功能 - 规则会自动定期刷新域名解析IP,无需额外脚本维护
方案3:直接用脚本更新IPtables规则(临时应急备选)
如果暂时不想切换工具,也可以写脚本直接修改IPtables规则,但这种方法效率低,频繁修改规则可能影响防火墙性能,仅适合临时应急。
大致思路:
- 脚本定期解析域名的新IP
- 通过
iptables-save定位并删除旧的IP规则 - 添加新的IP规则
- 用crontab定时运行脚本
不过这种方法容易出现规则匹配错误,且每次修改都要刷新IPtables,稳定性不如前两个方案,不推荐长期使用。
内容的提问来源于stack exchange,提问作者Biks

