BIND DNS 服务器搭建完全教程 / 第 08 章:视图(Views)配置
本章概述
视图(Views)是 BIND 最强大的特性之一,允许根据客户端来源返回不同的解析结果。本章讲解视图的工作原理、内外网分离架构、ACL 匹配规则和多视图配置。
8.1 视图基础
8.1.1 什么是视图
视图允许你为不同的客户端组提供不同的 DNS 响应,实现"同一个域名,不同的解析结果"。
同一个域名:www.example.com
内网客户端 (192.168.1.x) → 解析到 192.168.1.100(内网地址)
外网客户端 (互联网) → 解析到 203.0.113.10(公网地址)
8.1.2 视图的典型应用场景
| 场景 | 说明 |
|---|---|
| 内外网分离 | 内网用户访问内网 IP,外网用户访问公网 IP |
| 按地理位置分流 | 不同地区的用户解析到最近的服务器 |
| 按运营商分流 | 电信、联通、移动用户解析到不同机房 |
| 安全隔离 | 对外只暴露特定记录,对内显示完整记录 |
| 测试环境 | 特定客户端使用测试环境的解析 |
| 灰度发布 | 部分用户访问新版本服务器 |
8.2 视图配置语法
8.2.1 基本结构
view "view-name" {
// 匹配哪些客户端
match-clients { acl-or-address; };
// 匹配哪些目的地
match-destinations { acl-or-address; };
// 是否允许递归
recursion yes|no;
// 该视图内的区域定义
zone "example.com" {
type primary;
file "views/internal/example.com.zone";
};
zone "." {
type hint;
file "db.root";
};
};
⚠️ 关键规则:一旦使用了
view语句,所有zone必须定义在view内部。全局的zone将被忽略。
8.2.2 匹配规则
view "internal" {
// 匹配顺序:
// 1. 从上到下匹配 match-clients
// 2. 第一个匹配的视图生效
// 3. 如果都不匹配,使用最后的默认视图
match-clients {
trusted; // ACL 名称
!192.168.1.100; // 排除特定 IP
10.0.0.0/8; // 子网
};
};
8.2.3 视图匹配的优先级
// 视图按定义顺序从上到下匹配
// 第一个匹配的视图生效
view "special" {
match-clients { 192.168.1.50; }; // 精确 IP 最先匹配
// ...
};
view "internal" {
match-clients { 192.168.0.0/16; }; // 子网匹配
// ...
};
view "external" {
match-clients { any; }; // 兜底(放在最后)
// ...
};
8.3 内外网分离配置
8.3.1 完整配置示例
// /etc/bind/named.conf
// ACL 定义
acl "internal-nets" {
localhost;
localnets;
192.168.0.0/16;
10.0.0.0/8;
172.16.0.0/12;
};
acl "office-nets" {
192.168.1.0/24; // 北京办公室
192.168.2.0/24; // 上海办公室
};
acl "monitoring" {
10.0.0.50; // 监控服务器
};
// ---- 内网视图 ----
view "internal" {
match-clients { internal-nets; };
recursion yes;
allow-recursion { any; };
// 内部域名解析
zone "example.com" {
type primary;
file "views/internal/example.com.zone";
};
// 内部专用域名
zone "internal.corp" {
type primary;
file "views/internal/internal.corp.zone";
};
// 开发环境域名
zone "dev.example.com" {
type primary;
file "views/internal/dev.example.com.zone";
};
// 根提示(递归需要)
zone "." {
type hint;
file "db.root";
};
};
// ---- 外网视图 ----
view "external" {
match-clients { any; };
recursion no;
allow-query { any; };
// 仅返回公网可达的记录
zone "example.com" {
type primary;
file "views/external/example.com.zone";
};
};
8.3.2 内网区域文件
; views/internal/example.com.zone
$TTL 3600
$ORIGIN example.com.
@ IN SOA ns1.example.com. admin.example.com. (
2026051001 3600 900 1209600 86400
)
IN NS ns1.example.com.
IN NS ns2.example.com.
; 内网地址
ns1 IN A 192.168.1.10
ns2 IN A 192.168.1.11
@ IN A 192.168.1.100
www IN A 192.168.1.100
api IN A 192.168.1.101
app IN A 192.168.1.102
mail IN A 192.168.1.20
db IN A 192.168.1.200
redis IN A 192.168.1.201
mq IN A 192.168.1.202
; 开发环境
dev IN A 192.168.10.1
staging IN A 192.168.10.2
; MX
@ IN MX 10 mail.example.com.
; TXT
@ IN TXT "v=spf1 mx ip4:192.168.1.20 ~all"
8.3.3 外网区域文件
; views/external/example.com.zone
$TTL 3600
$ORIGIN example.com.
@ IN SOA ns1.example.com. admin.example.com. (
2026051001 3600 900 1209600 86400
)
IN NS ns1.example.com.
IN NS ns2.example.com.
; 公网地址
ns1 IN A 203.0.113.10
ns2 IN A 203.0.113.11
@ IN A 203.0.113.20
www IN A 203.0.113.20
api IN A 203.0.113.21
mail IN A 203.0.113.30
; MX
@ IN MX 10 mail.example.com.
; TXT
@ IN TXT "v=spf1 mx ip4:203.0.113.30 ~all"
; 注意:不包含 db、redis、mq 等内网服务
; 注意:不包含 dev、staging 等开发环境
8.3.4 目录结构
/var/cache/bind/
├── views/
│ ├── internal/
│ │ ├── example.com.zone
│ │ ├── internal.corp.zone
│ │ └── dev.example.com.zone
│ └── external/
│ └── example.com.zone
├── db.root
└── ...
8.4 多视图高级配置
8.4.1 按部门分流
acl "dept-engineering" {
192.168.1.0/24;
};
acl "dept-sales" {
192.168.2.0/24;
};
acl "dept-executive" {
192.168.3.0/24;
};
view "engineering" {
match-clients { dept-engineering; };
// 完整的 DNS 解析,包括内部开发域名
recursion yes;
zone "example.com" {
type primary;
file "views/engineering/example.com.zone";
};
zone "." { type hint; file "db.root"; };
};
view "sales" {
match-clients { dept-sales; };
// 受限的 DNS 解析,不包含开发域名
recursion yes;
zone "example.com" {
type primary;
file "views/sales/example.com.zone";
};
zone "." { type hint; file "db.root"; };
};
view "default" {
match-clients { any; };
// 其他网络使用公共解析
recursion no;
zone "example.com" {
type primary;
file "views/external/example.com.zone";
};
};
8.4.2 按运营商分流
acl "chinanet" {
1.0.1.0/24;
14.0.0.0/12;
36.0.0.0/8;
// ... 电信 IP 段
};
acl "cucc" {
1.2.0.0/15;
14.104.0.0/13;
// ... 联通 IP 段
};
acl "cmcc" {
36.128.0.0/10;
39.128.0.0/10;
// ... 移动 IP 段
};
view "chinanet" {
match-clients { chinanet; };
recursion no;
zone "example.com" {
type primary;
file "views/chinanet/example.com.zone";
};
};
view "cucc" {
match-clients { cucc; };
recursion no;
zone "example.com" {
type primary;
file "views/cucc/example.com.zone";
};
};
view "cmcc" {
match-clients { cmcc; };
recursion no;
zone "example.com" {
type primary;
file "views/cmcc/example.com.zone";
};
};
view "default" {
match-clients { any; };
recursion no;
zone "example.com" {
type primary;
file "views/default/example.com.zone";
};
};
8.4.3 配合 GeoIP
BIND 9.10+ 支持 GeoIP 库进行地理位置匹配(需要编译时启用):
view "beijing" {
match-clients { geoip country CN region 11; }; // 北京
// ...
};
view "shanghai" {
match-clients { geoip country CN region 31; }; // 上海
// ...
};
注意:GeoIP 需要 MaxMind 数据库,且 BIND 编译时需
--with-geoip。
8.5 视图间的区域传输
8.5.1 问题
当使用多个视图时,辅助服务器也需要对应多个视图。否则区域传输会出问题。
8.5.2 解决方案:使用 TSIG 区分视图
主服务器:
key "internal-transfer" {
algorithm hmac-sha256;
secret "internal-secret...";
};
key "external-transfer" {
algorithm hmac-sha256;
secret "external-secret...";
};
view "internal" {
match-clients { internal-nets; key internal-transfer; };
zone "example.com" {
type primary;
file "views/internal/example.com.zone";
allow-transfer { key internal-transfer; };
};
};
view "external" {
match-clients { any; };
zone "example.com" {
type primary;
file "views/external/example.com.zone";
allow-transfer { key external-transfer; };
};
};
辅助服务器:
key "internal-transfer" {
algorithm hmac-sha256;
secret "internal-secret...";
};
key "external-transfer" {
algorithm hmac-sha256;
secret "external-secret...";
};
view "internal" {
match-clients { internal-nets; key internal-transfer; };
zone "example.com" {
type secondary;
file "views/internal/example.com.zone";
masters { 192.168.1.10 key internal-transfer; };
};
};
view "external" {
match-clients { any; };
zone "example.com" {
type secondary;
file "views/external/example.com.zone";
masters { 203.0.113.10 key external-transfer; };
};
};
8.6 视图与递归服务器
8.6.1 分离权威和递归功能
// 同一服务器既提供权威解析,又提供递归服务
view "internal-recursive" {
match-clients { internal-nets; };
recursion yes;
allow-recursion { any; };
// 内部域名
zone "example.com" {
type primary;
file "views/internal/example.com.zone";
};
zone "internal.corp" {
type primary;
file "views/internal/internal.corp.zone";
};
// 根提示(递归需要)
zone "." {
type hint;
file "db.root";
};
};
view "external-authoritative" {
match-clients { any; };
recursion no;
allow-query { any; };
zone "example.com" {
type primary;
file "views/external/example.com.zone";
};
};
8.7 视图调试与排错
8.7.1 确认查询使用的视图
# 开启查询日志
rndc querylog on
# 从不同来源查询
dig @192.168.1.10 www.example.com # 内网
dig @203.0.113.10 www.example.com # 外网
# 查看日志中的视图信息
tail -f /var/log/named/query.log
# 日志中会显示使用了哪个视图
8.7.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 所有查询都走同一视图 | match-clients 配置错误 | 检查 ACL 定义 |
| 区域传输失败 | 视图未正确匹配辅助服务器 | 使用 TSIG 区分视图 |
| 配置语法错误 | 全局 zone 和 view 混用 | 所有 zone 移入 view |
| 性能下降 | 视图过多 | 合并相似视图 |
8.7.3 检查视图配置
# 检查配置语法
named-checkconf
# 列出所有视图和区域
rndc zonestatus example.com # 在特定视图下
# 查看所有区域
rndc status
8.8 本章小结
| 配置项 | 说明 | 关键点 |
|---|---|---|
match-clients | 匹配客户端来源 | 从上到下匹配,第一匹配生效 |
match-destinations | 匹配目的地地址 | 用于多 IP 场景 |
recursion | 是否允许递归 | 视图级别独立配置 |
| 视图顺序 | 匹配优先级 | 具体 → 宽泛 → any |
| TSIG 区分 | 区域传输 | 使用不同密钥区分视图 |
💡 小技巧
- 视图按顺序匹配:最具体的放在最前面,
any放在最后。 - 使用 TSIG 区分视图的区域传输:比 IP 匹配更可靠。
- 保持视图中的区域文件独立:每个视图一个目录。
- 不要过度使用视图:视图过多会增加配置复杂度和内存占用。
- 测试时用
dig指定源地址:dig -b 192.168.1.100 @server domain。