BIND9 智能 DNS 配置实战:按运营商线路分流
把同一个域名按访问者的运营商(电信 / 联通 / 移动)解析到不同的 IP,让用户就近访问、提升体验。本文给出一份生产可用的 BIND9 智能 DNS 完整配置。
说明:文中所有 IP 均为 RFC1918 私有段示例(10.x.x.x / 192.168.x.x / 172.16.x.x),仅用于演示,请替换为您的真实线路 IP;域名
emporerlinux.com为示例域名,请替换为您自己的域名。
一、什么是智能 DNS
普通 DNS 对所有查询返回同一个 IP;智能 DNS(Smart DNS / View-based DNS)则会根据客户端的来源 IP(运营商、地域)返回不同的解析结果。
典型应用场景:
- 多线机房:电信用户解析到电信线路 IP,联通用户解析到联通 IP,避免跨网访问慢
- CDN 调度:把不同地区用户调度到最近的边缘节点
- 灰度/容灾:某条线路故障时,让对应运营商用户走备用 IP
BIND9 通过 view + acl 原生支持这种能力。
二、整体架构
┌─────────────────────────────────────┐
客户端 DNS 查询 ──▶│ BIND9 named │
│ ┌────────────────────────────────┐ │
│ │ view "ctc" ← 电信 ACL │──▶ 电信线路 zone
│ │ view "cuc" ← 联通 ACL │──▶ 联通线路 zone
│ │ view "cmcc" ← 移动 ACL │──▶ 移动线路 zone
│ │ view "any" ← 兜底(其他来源) │──▶ 默认 zone
│ └────────────────────────────────┘ │
└─────────────────────────────────────┘
匹配规则:named 按 view 声明顺序自上而下匹配,第一个命中的 match-clients 生效,因此兜底的 any 必须放在最后。
三、目录结构
配置按职责拆分到不同文件,便于维护:
/etc/named/
├── named.conf # 主配置:include 其它文件
├── conf/
│ ├── named.ca # 根域 hint
│ ├── acl.conf # 汇总所有 ACL(include 各 acl/*.acl)
│ └── view.conf # 汇总所有 view(include 各 view/*.view)
├── acl/
│ ├── ctc.acl # 电信 IP 段
│ ├── cuc.acl # 联通 IP 段
│ └── cmcc.acl # 移动 IP 段
├── view/
│ ├── ctc.view # 电信视图
│ ├── cuc.view # 联通视图
│ ├── cmcc.view # 移动视图
│ └── any.view # 兜底视图
└── zone/
├── emporerlinux.com/
│ ├── ctc.zone cuc.zone cmcc.zone any.zone # 各线路 zone(差异部分)
│ └── all.zone # 公共记录(被 $INCLUDE 复用)
└── emporerlinux.net/
├── ctc.zone cuc.zone cmcc.zone any.zone
└── all.zone
拆分原则:会变的(zone 记录)和不变的(ACL、view 结构)分开,改一条 A 记录不用碰 view 配置。
四、配置详解
1. 主配置 named.conf
只做 include,保持清爽:
include "conf/acl.conf"; # 加载所有 ACL
include "conf/view.conf"; # 加载所有 view
2. ACL 汇总 conf/acl.conf
把各运营商的 IP 段都 include 进来:
include "acl/cuc.acl";
include "acl/cmcc.acl";
include "acl/ctc.acl";
3. 运营商 ACL 定义 acl/ctc.acl 等
每个文件定义一个命名 ACL,里面是该运营商的 IP 段(CIDR)。
⚠️ 下面的 IP 全是 RFC1918 私有段,仅为示例占位。生产环境请替换为真实的运营商 IP 段(可从 CNNIC / apnic 公开数据获取,或用
whois -h whois.apnic.net查询)。
# acl/ctc.acl —— 电信(示例:用 10.0.0.0/10 代表电信地址段)
acl "ctc" {
10.0.0.0/10;
};
# acl/cuc.acl —— 联通(示例:用 10.64.0.0/10 代表联通地址段)
acl "cuc" {
10.64.0.0/10;
};
# acl/cmcc.acl —— 移动(示例:用 10.128.0.0/10 代表移动地址段)
acl "cmcc" {
10.128.0.0/10;
};
4. view 汇总 conf/view.conf
按顺序 include 各 view(顺序很重要,兜底 any 必须最后):
include "view/ctc.view";
include "view/cuc.view";
include "view/cmcc.view";
include "view/any.view";
5. 视图定义 view/ctc.view 等
每个 view 用 match-clients 匹配 ACL,并为每个域指定对应的 zone 文件:
# view/ctc.view —— 电信用户看到的解析
view "ctc" {
match-clients { "ctc"; };
zone "." {
type hint;
file "conf/named.ca";
};
zone "emporerlinux.com" {
type master;
file "zone/emporerlinux.com/ctc.zone";
};
zone "emporerlinux.net" {
type master;
file "zone/emporerlinux.net/ctc.zone";
};
};
# view/cuc.view —— 联通
view "cuc" {
match-clients { "cuc"; };
zone "." {
type hint;
file "conf/named.ca";
};
zone "emporerlinux.com" {
type master;
file "zone/emporerlinux.com/cuc.zone";
};
zone "emporerlinux.net" {
type master;
file "zone/emporerlinux.net/cuc.zone";
};
};
# view/cmcc.view —— 移动
view "cmcc" {
match-clients { "cmcc"; };
zone "." {
type hint;
file "conf/named.ca";
};
zone "emporerlinux.com" {
type master;
file "zone/emporerlinux.com/cmcc.zone";
};
zone "emporerlinux.net" {
type master;
file "zone/emporerlinux.net/cmcc.zone";
};
};
# view/any.view —— 兜底(其它所有来源,必须放最后)
view "any" {
match-clients { "any"; };
zone "." {
type hint;
file "conf/named.ca";
};
zone "emporerlinux.com" {
type master;
file "zone/emporerlinux.com/any.zone";
};
zone "emporerlinux.net" {
type master;
file "zone/emporerlinux.net/any.zone";
};
};
6. zone 文件(核心:差异 + 复用)
每个域下有 5 个 zone 文件:4 个线路文件(ctc/cuc/cmcc/any)+ 1 个公共文件(all.zone)。
线路文件只放「该线路不同的部分」,公共记录通过 $INCLUDE 复用:
# zone/emporerlinux.com/ctc.zone —— 电信线路专属记录
$TTL 600
@ IN SOA ns1.emporerlinux.com. admin.emporerlinux.com. (
2026072401 ; 序列号(每次改动 +1)
3600 ; 刷新
900 ; 重试
86400 ; 过期
600 ) ; 最小 TTL
IN NS ns1.emporerlinux.com.
IN NS ns2.emporerlinux.com.
; —— 电信线路专属:www 指向电信线路 IP(示例用 192.168.10.x)——
www IN A 192.168.10.100
; —— 公共记录(所有线路都一样)——
$INCLUDE "zone/emporerlinux.com/all.zone";
# zone/emporerlinux.com/all.zone —— 公共记录(所有线路共享,示例 IP)
ns1 IN A 10.0.0.53
ns2 IN A 10.0.0.54
mail IN A 172.16.0.25
@ IN MX 10 mail.emporerlinux.com.
这样设计的好处:
| 场景 | 传统做法 | 本方案 |
|---|---|---|
| 改 www 的电信 IP | 改 ctc.zone | 改 ctc.zone(一样) |
| 新增一条所有线路通用的记录 | 改 4 个 zone 文件 | 只改 all.zone 一处 |
| 新增运营商线路 | 大改 | 加一个 acl + view + zone 文件 |
五、验证配置
改完配置先检查语法,再 reload:
# 1. 检查主配置语法
named-checkconf /etc/named/named.conf
# 2. 检查 zone 文件语法(域名 + 文件路径)
named-checkzone emporerlinux.com /etc/named/zone/emporerlinux.com/ctc.zone
# 3. 重新加载配置(不中断服务)
rndc reload
# 或重载 named
systemctl reload named
六、测试智能解析
用 dig 指定不同源 IP 模拟各运营商查询:
# 模拟电信用户查询(-b 绑定本地源 IP,该 IP 属于电信 ACL 示例段 10.0.0.0/10)
dig @127.0.0.1 www.emporerlinux.com -b 10.0.0.100 +short
# 预期返回: 192.168.10.100(电信线路 IP)
# 模拟联通用户(10.64.0.0/10 段)
dig @127.0.0.1 www.emporerlinux.com -b 10.64.0.100 +short
# 不指定源 IP(走 any 兜底)
dig @127.0.0.1 www.emporerlinux.com +short
如果返回的 IP 和预期一致,说明 view 分流生效。
七、生产注意事项
- ACL 要定期更新:运营商 IP 段会调整,建议每月从 apnic 同步一次。
- 兜底 view 必须放最后:
any放前面会导致所有匹配都走兜底。 - view 间 zone 必须一致:每个 view 都要包含所有域,否则某些运营商查不到。
- 序列号要递增:zone 文件 SOA 序列号每次改动必须 +1,否则从 DNS 不同步。
- 配合主从同步:多台 DNS 时,
view配合allow-transfer和also-notify做主从,注意从服务器也要有相同的 view + ACL 配置。 - 客户端真实 IP:如果前面有 DNS 负载均衡(如 F5/LVS),
match-clients看到的是 LB 的 IP,不是真实客户端 IP。这种场景需要 LB 做 EDNS Client Subnet 透传。
八、总结
| 组件 | 作用 |
|---|---|
acl |
定义运营商 IP 段 |
view + match-clients |
按来源 IP 分流到不同 zone |
zone 文件 + $INCLUDE |
线路差异 + 公共记录复用 |
named-checkconf / dig -b |
验证语法 + 测试分流 |
核心思路一句话:用 view 把客户端按 ACL 分类,每类看到不同的解析结果。配置拆分到多文件后,维护成本低、扩展运营商线路也容易。
作者:EmporerLinux | 分类:网络服务
本文首发于 emporerlinux.com,转载请注明出处。