DNS解析是几乎所有网络访问的第一步,而在防火墙上做精细化管控时,DNS流量的放行策略往往是最容易被忽视、也最容易出错的一环。不少人以为只要开放了UDP 53端口就万事大吉,结果业务系统依然出现域名解析失败、访问时快时慢的诡异现象。这篇文章围绕DNS白名单的配置展开,从端口与协议层面讲到基于域名的策略对象,最后梳理常见故障的排查方法。

一、DNS白名单到底要放行哪些流量
首先要明确一点:DNS并非只走UDP 53。标准的DNS报文如果超过512字节,客户端会改用TCP 53重新发起查询,这在启用EDNS或DNSSEC验证的场景下非常常见。如果防火墙只放行了UDP 53,一旦出现需要TCP回退的查询,解析就会莫名失败。因此一条完整的DNS白名单至少应包含UDP 53和TCP 53两个协议端口。
其次要区分"放行去哪里的DNS"。白名单的意义在于限制,如果策略里放行的目的地址是any,那么内网主机可以把任意公网DNS当作解析入口,这等于绕过了企业统一的DNS架构,也留下了DNS隧道外传数据的隐患。更稳妥的做法是:源地址限定为内网网段或DNS服务器所在区域,目的地址限定为企业指定的上游DNS服务器,比如运营商递归服务器、公共DNS或自建转发器的地址。
另外别忘了DNS服务器本身的区域传输流量。如果内网有多台DNS服务器,主从服务器之间的AXFR/IXFR同步使用TCP 53,这部分流量如果不在白名单内,从服务器会长时间拿不到区域数据。以iptables为例,一条典型的DNS白名单规则可以这样写:
# 放行内网客户端到指定DNS服务器的UDP/TCP 53查询 iptables -A FORWARD -s 192.168.10.0/24 -d 223.5.5.5 -p udp --dport 53 -j ACCEPT iptables -A FORWARD -s 192.168.10.0/24 -d 223.5.5.5 -p tcp --dport 53 -j ACCEPT # 放行DNS主从之间的区域传输 iptables -A FORWARD -s 192.168.1.10 -d 192.168.1.11 -p tcp --dport 53 -j ACCEPT # 其余53端口流量默认拒绝 iptables -A FORWARD -p udp --dport 53 -j DROP iptables -A FORWARD -p tcp --dport 53 -j DROP
注意规则的顺序很重要。iptables是自上而下匹配,ACCEPT规则必须放在兜底的DROP之前,否则白名单形同虚设。
二、基于域名的白名单:FQDN对象的原理与配置
在应用层管控需求越来越多的今天,很多防火墙支持直接以域名作为策略匹配条件,也就是所谓的FQDN地址对象。它的原理并不复杂:防火墙自身充当DNS客户端,周期性地解析对象中配置的域名,把解析结果缓存成IP列表,再把这些IP动态填充到安全策略中。这样管理员不需要手动维护IP地址,域名背后的服务器变更地址后规则也能自动更新。
以某商用防火墙的配置思路为例,一般分三步:第一步创建FQDN对象,填入需要放行的域名,例如update.ippipp.com;第二步确认防火墙自身用于解析的系统DNS配置正确,因为FQDN对象依赖这个DNS去做递归查询;第三步在安全策略中把该对象作为目的地址绑定,动作设为允许。命令行风格的配置大致如下:
# 创建基于域名的地址对象
config firewall address
edit "fqdn-update-server"
set type fqdn
set fqdn "update.ipipp.com"
set comment "补丁服务器域名"
next
end
# 在安全策略中引用
config firewall policy
edit 100
set srcintf "lan"
set dstintf "wan"
set srcaddr "internal-net"
set dstaddr "fqdn-update-server"
set service "HTTP" "HTTPS"
set action accept
next
end
FQDN对象虽然方便,但也有几个坑需要警惕。其一是TTL问题:域名记录的TTL如果设得很短(比如30秒),防火墙的解析刷新周期跟不上,缓存的IP可能已经失效;其二是CDN域名解析出来的IP是动态调度的,不同时间、不同出口拿到的结果可能不一致,导致放行了A时刻的IP却拦下了B时刻的IP;其三是DNS缓存污染,如果客户端绕过防火墙指定的DNS自行解析,拿到的IP与防火墙解析的IP不一致,FQDN策略同样会误拦。
三、规则不生效时的排查思路
配置完成后如果出现解析异常,建议按"由外到内"的顺序逐层排查。第一步确认客户端的DNS指向是否在白名单允许的范围内,很多故障其实源于客户端配置了8.8.8.8之类未在白名单内的服务器,查询被默认拒绝策略拦截。可以在客户端执行nslookup验证当前使用的DNS服务器是否正确。
第二步检查防火墙的会话表和策略命中计数。几乎所有防火墙都提供策略命中数的统计,如果白名单策略的计数一直是零,说明流量根本没有匹配到这条规则,可能是源地址对象定义错误,或者前面有一条更宽泛的拒绝规则抢先命中了。此时应该抓包确认流量的真实五元组,再对照策略的条件逐项核对。常用的排查命令示例如下:
# 在防火墙或Linux网关上抓取DNS流量确认是否到达 tcpdump -i eth0 -nn port 53 # 查看iptables各规则的命中计数 iptables -L FORWARD -n -v --line-numbers
第三步留意DNS相关的ALG和应用层处理。某些防火墙默认开启DNS ALG功能,会对DNS报文做深度检测甚至改写,遇到EDNS扩展报文时可能处理异常导致截断。如果抓包发现请求正常发出但应答没有回来,可以尝试临时关闭DNS ALG再观察。此外DoH(DNS over HTTPS)和DoT(DNS over TLS)的普及也带来新问题:客户端把DNS藏在443端口或853端口里,传统的53端口白名单完全看不到这些流量,企业若要统一管控DNS,还需要在出口策略上处理853端口的DoT,并在上网行为管理层面识别DoH。
四、搭建一套合理的DNS白名单体系
综合来看,一套健壮的DNS白名单架构建议遵循三个原则:客户端只允许访问指定的内部递归DNS服务器;内部递归服务器只允许向上游白名单DNS发起查询;所有53端口的越界流量默认拒绝。这种分层设计既保证了解析链路清晰可审计,也压缩了DNS隧道攻击的生存空间。
最后要强调的是日志。DNS查询日志是排查访问问题和发现异常外联的重要数据源,建议在防火墙或递归服务器上开启日志记录,定期审查是否有主机在向白名单之外的地址发起53端口连接。白名单不是配完就结束的一次性工作,随着业务域名和上游DNS的变更,定期回顾和收紧规则才能让这套机制持续发挥作用。