iptables 是 Linux 系统中功能强大的防火墙工具,通过配置规则可以实现对网络流量的精细控制,包括对 DNS 流量的限制,DNS(域名系统)是互联网中用于将域名解析为 IP 地址的核心服务,限制 DNS 流量可能出于安全防护、访问控制或带宽管理等目的,以下将详细介绍如何使用 iptables 限制 DNS 流量,包括基本规则配置、常见场景实现及注意事项。
iptables 限制 DNS 流量的基本原理
iptables 通过在网络层(三层)和传输层(四层)检查数据包的源/目的 IP、源/目的端口、协议类型等信息,匹配规则后执行允许(ACCEPT)、拒绝(REJECT)或丢弃(DROP)等操作,DNS 流量通常基于 UDP 协议,端口号为 53,部分场景下(如 DNS over TLS/DoT、DNS over HTTPS/DoH)也会使用 TCP 端口 53 或其他自定义端口,限制 DNS 流量需重点关注协议类型和端口匹配。
在配置规则前,需明确 iptables 的表(table)和链(chain)结构:
- filter 表:默认用于数据包过滤,包含 INPUT(入站)、OUTPUT(出站)、FORWARD(转发)链,是限制本地 DNS 流量的主要表。
- nat 表:用于网络地址转换,若涉及 DNAT(目标地址转换)或 SNAT(源地址转换)的 DNS 流量控制,需在此表配置。
- mangle 表:用于修改数据包的 TOS、TTL 等字段,一般不直接用于 DNS 流量限制。
限制 DNS 流量的核心逻辑包括:
- 限制来源 IP:仅允许特定客户端访问 DNS 服务,或阻止恶意 IP 发起 DNS 请求。
- 限制目的端口:仅允许访问标准的 DNS 端口(53),或阻止非标准端口的 DNS 流量。
- 限制协议类型:明确允许或拒绝 UDP/TCP 协议的 DNS 流量。
- 限制接口:绑定特定网络接口(如内网网卡)处理 DNS 流量,避免公网直接暴露。
iptables 限制 DNS 流量的常见场景配置
(一)场景1:仅允许本地主机访问特定 DNS 服务器
为防止本地主机使用恶意或不可信的 DNS 服务器,可限制其仅允许访问指定的 DNS 服务器(如 8.8.8.8、114.114.114.114),假设本地主机 IP 为 192.168.1.100,DNS 服务器为 8.8.8.8 和 114.114.114.114,配置如下:
# 1. 允许本地主机访问 8.8.8.8 的 UDP 53 端口 iptables -A OUTPUT -p udp -d 8.8.8.8 --dport 53 -j ACCEPT # 2. 允许本地主机访问 114.114.114.114 的 UDP 53 端口 iptables -A OUTPUT -p udp -d 114.114.114.114 --dport 53 -j ACCEPT # 3. 拒绝其他所有 UDP 53 端口的出站流量 iptables -A OUTPUT -p udp --dport 53 -j REJECT
说明:
-A OUTPUT
:添加到 OUTPUT 链,控制本地主机发出的流量。-p udp
:匹配 UDP 协议。-d
:指定目的 IP。--dport 53
:匹配目的端口为 53。-j ACCEPT/REJECT
: ACCEPT 允许流量通过,REJECT 拒绝并发送拒绝信息(DROP 则直接丢弃,不发送信息)。
(二)场景2:限制外部客户端访问本地 DNS 服务
若本地主机运行 DNS 服务(如 bind、dnsmasq),需限制仅内网客户端(192.168.1.0/24)可访问,公网流量拒绝,假设 DNS 服务监听在 eth1 内网接口:
# 1. 允许内网客户端访问 UDP 53 端口 iptables -A INPUT -i eth1 -p udp -s 192.168.1.0/24 --dport 53 -j ACCEPT # 2. 允许内网客户端访问 TCP 53 端口(用于大包 DNS 查询) iptables -A INPUT -i eth1 -p tcp -s 192.168.1.0/24 --dport 53 -j ACCEPT # 3. 拒绝其他所有 UDP 53 端口的入站流量 iptables -A INPUT -p udp --dport 53 -j REJECT # 4. 拒绝其他所有 TCP 53 端口的入站流量 iptables -A INPUT -p tcp --dport 53 -j REJECT
说明:
-i eth1
:匹配从 eth1 接口流入的流量。-s 192.168.1.0/24
:匹配源 IP 为内网网段。- 需同时考虑 UDP 和 TCP 协议,避免部分 DNS 查询因 TCP 被拒绝而失败。
(三)场景3:限制 DNS 流量频率(防 DDoS 攻击)
为防止 DNS 服务被 DDoS 攻击(如大量伪造源 IP 的 DNS 请求),可使用 limit
模块限制单位时间内的连接数,限制每秒允许 100 个新连接,超过则临时拒绝:
# 1. 限制 UDP 53 端口每秒 100 个新连接,触发时拒绝 iptables -A INPUT -p udp --dport 53 -m conntrack --ctstate NEW -m limit --limit 100/s --limit-burst 100 -j ACCEPT iptables -A INPUT -p udp --dport 53 -m conntrack --ctstate NEW -j REJECT # 2. 限制 TCP 53 端口每秒 50 个新连接(TCP 连接建立开销更大) iptables -A INPUT -p tcp --dport 53 -m conntrack --ctstate NEW -m limit --limit 50/s --limit-burst 50 -j ACCEPT iptables -A INPUT -p tcp --dport 53 -m conntrack --ctstate NEW -j REJECT
说明:
-m limit
:加载 limit 模块,用于流量限速。--limit 100/s
:平均速率限制(100 个数据包/秒)。--limit-burst 100
:突发量限制(允许一次性通过 100 个数据包,超出后按--limit
速率处理)。-m conntrack --ctstate NEW
:匹配新建立的连接状态。
(四)场景4:基于时间段的 DNS 流量限制
若需在特定时间段(如工作时间 9:00-18:00)允许 DNS 访问,非工作时间拒绝,可结合 time
模块实现:
# 1. 允许工作时间段(周一至周五 9:00-18:00)的 UDP 53 端口访问 iptables -A INPUT -p udp --dport 53 -m time --timestart 09:00 --timestop 18:00 --weekdays Mon,Tue,Wed,Thu,Fri -j ACCEPT # 2. 拒绝其他时间的 UDP 53 端口访问 iptables -A INPUT -p udp --dport 53 -j REJECT
说明:
-m time
:加载 time 模块,需确保内核支持(通常默认支持)。--timestart/--timestop
:定义时间范围。--weekdays
:定义生效的星期几。
(五)场景5:记录被限制的 DNS 流量(便于排查)
为分析被拦截的 DNS 流量,可使用 LOG
目标记录日志,再执行拒绝操作:
# 1. 记录拒绝的 UDP 53 端口访问日志(前缀为 DNS_BLOCK) iptables -A INPUT -p udp --dport 53 -m limit --limit 5/min -j LOG --log-prefix "DNS_BLOCK: " # 2. 拒绝 UDP 53 端口访问 iptables -A INPUT -p udp --dport 53 -j REJECT
说明:
-m limit --limit 5/min
:限制日志记录频率,避免日志被刷爆。--log-prefix
:为日志添加自定义前缀,便于过滤。
iptables 规则管理与注意事项
(一)规则保存与持久化
不同 Linux 发行版的规则保存方式不同:
- CentOS/RHEL:
service iptables save
(保存至/etc/sysconfig/iptables
)。 - Ubuntu/Debian:
iptables-save > /etc/iptables/rules.v4
(需安装iptables-persistent
包)。
(二)规则顺序与优先级
iptables 规则按顺序匹配,一旦匹配即执行对应动作,不再检查后续规则,需将“允许”规则置于“拒绝”规则之前,避免流量被误拦截。
(三)默认策略配置
建议将 INPUT 链的默认策略设置为 DROP,仅明确允许必要的流量:
iptables -P INPUT DROP
但需谨慎操作,避免导致远程连接中断(如 SSH 访问被拒)。
(四)DNS over TLS/DoH 流量的特殊性
DoT(DNS over TLS)和 DoH(DNS over HTTPS)使用加密传输,标准端口分别为 853(DoT TCP)和 443(DoH HTTPS),若需限制此类流量,需匹配相应端口和协议:
# 拒绝 DoT 流量(TCP 853) iptables -A INPUT -p tcp --dport 853 -j REJECT # 拒绝 DoH 流量(TCP 443,需结合目的 IP 或域名进一步过滤) iptables -A INPUT -p tcp --dport 443 -j REJECT
但需注意,DoH 流量与普通 HTTPS 流量无法通过 iptables 直接区分,需结合更高级的工具(如 nftables、eBPF)或应用层过滤。
(五)测试与回滚
配置规则前,建议通过 SSH 远程连接测试,避免因规则错误导致无法远程管理,若规则导致网络异常,可通过以下方式紧急恢复:
# 清空所有规则(默认策略除外) iptables -F iptables -X iptables -t nat -F iptables -t nat -X
相关问答FAQs
Q1:使用 iptables 限制 DNS 流量后,本地域名解析失败,如何排查?
A:首先检查 iptables 规则顺序,确保允许 DNS 流量的规则位于拒绝规则之前,可通过 iptables -L -v --line-numbers
查看规则详情及匹配数据包数,其次确认 DNS 服务器 IP 和端口是否正确(如是否为 UDP 53),若使用非标准端口或 DoT/DoH,需调整规则匹配条件,最后检查网络接口和源/目的 IP 限制,例如是否误将 OUTPUT 链的源 IP 限制为特定网段。
Q2:如何区分并限制恶意 DNS 流量(如 DNS 隧道)?
A:DNS 隧道攻击通过将恶意数据封装在 DNS 请求中传输,可通过以下方式识别和限制:
- 限制 DNS 数据包大小:标准 DNS 查询通常小于 512 字节,可通过
--length
参数限制大包:iptables -A INPUT -p udp --dport 53 -m length --length 512: -j REJECT
- 限制 DNS 域名长度:异常长的域名可能指示 DNS 隧道,需结合正则表达式(需
string
模块)匹配:iptables -A INPUT -p udp --dport 53 -m string --string "examplelongdomain" --algo bm -j REJECT
- 监控 DNS 查询频率:单个 IP 短时间内发起大量 DNS 请求,可通过
recent
模块封禁:iptables -A INPUT -p udp --dport 53 -m recent --name dns_attack --update --seconds 60 --hitcount 10 -j REJECT iptables -A INPUT -p udp --dport 53 -m recent --name dns_attack --set -j ACCEPT
上述规则表示:60 秒内同一 IP 发起 10 次以上请求则拒绝,否则允许。