Nginx+Keepalived实现高可用内网DNS负载均衡的关键是:Nginx通过stream模块四层转发UDP/TCP 53端口请求,Keepalived配置非抢占式VIP漂移与TCP健康检查,后端DNS服务器需一致监听0.0.0.0:53并放行防火墙。

用 Nginx + Keepalived 实现高可用内网 DNS 负载均衡集群,关键在于明确角色分工:Nginx 不直接处理 DNS 协议(UDP 53 端口),而是作为四层 TCP/UDP 负载均衡器转发 DNS 请求;Keepalived 提供虚拟 IP(VIP)漂移能力,保障单点故障时服务不中断。整个方案适用于企业内网中部署多个 BIND、CoreDNS 或 dnsmasq 实例的场景。
确认 DNS 服务部署模式
内网 DNS 集群需先确保后端至少两台 DNS 服务器已就绪,且配置一致(如相同的 zone 文件、ACL 策略、递归/转发设置)。每台 DNS 服务必须:
- 监听 UDP/TCP 53 端口(DNS 查询主要走 UDP,区域传输等走 TCP)
- 绑定到本机所有接口(
0.0.0.0:53)或指定内网地址 - 禁用防火墙拦截(或放行 UDP/TCP 53)
- 可通过
dig @192.168.1.101 example.com +short单独验证响应正常
Nginx 配置为四层 DNS 转发器
Nginx 从 1.9.13 开始支持 stream 模块,用于 TCP/UDP 代理。需确认编译时已启用:nginx -V 2>&1 | grep -o with-stream。在 /usr/local/nginx/conf/nginx.conf 末尾添加:
stream {
upstream dns_backend {
hash $remote_addr consistent; # 按客户端 IP 哈希,提升缓存命中率
server 192.168.1.101:53 weight=3;
server 192.168.1.102:53 weight=3;
server 192.168.1.103:53 weight=2;
}
<pre class="brush:php;toolbar:false;">server {
listen 53 udp reuseport;
proxy_pass dns_backend;
proxy_timeout 1s;
proxy_responses 1;
}
server {
listen 53 tcp reuseport;
proxy_pass dns_backend;
proxy_timeout 3s;
}}
注意:reuseport 提升多核并发处理能力;proxy_responses 1 是 UDP 代理必需项,表示每个请求只等待一个响应包。
Keepalived 配置 VIP 与健康检查
两台 Nginx 节点均安装 Keepalived,并配置非抢占式主备(避免脑裂)。以主节点为例(/etc/keepalived/keepalived.conf):
global_defs {
router_id dns-lb-01
}
vrrp_script chk_nginx_dns {
script "/bin/bash -c 'timeout 1 bash -c \"echo -n > /dev/tcp/127.0.0.1/53\" 2>/dev/null && exit 0 || exit 1'"
interval 3
weight -5
fall 2
rise 2
}
vrrp_instance VI_DNS {
state BACKUP
interface eth0
virtual_router_id 53
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass dns123456
}
virtual_ipaddress {
192.168.1.200/24 dev eth0 label eth0:1
}
track_script {
chk_nginx_dns
}
}
说明:
- 所有节点设为
BACKUP+nopreempt,靠priority决定初始 Master - 健康检查使用 TCP 连通性探测(DNS 服务监听 TCP 53 即可反映基本可用性)
- VIP
192.168.1.200作为内网客户端统一配置的 DNS 地址
内网客户端与验证要点
将内网所有终端、服务器的 /etc/resolv.conf 中 nameserver 改为 VIP:
nameserver 192.168.1.200
验证方式:
- 用
dig @192.168.1.200 example.com +short测试解析是否成功 - 停掉主节点 Nginx:
systemctl stop nginx,观察 3–5 秒内 VIP 是否自动漂移到备节点(ip a s eth0查看) - 持续
watch -n1 'dig @192.168.1.200 example.com +short',确认无解析失败 - 抓包验证:在 VIP 所在节点执行
tcpdump -i any port 53 -n,应看到请求被分发到不同后端











