强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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"

; 注意:不包含 dbredismq 等内网服务
; 注意:不包含 devstaging 等开发环境

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 区分区域传输使用不同密钥区分视图

💡 小技巧

  1. 视图按顺序匹配:最具体的放在最前面,any 放在最后。
  2. 使用 TSIG 区分视图的区域传输:比 IP 匹配更可靠。
  3. 保持视图中的区域文件独立:每个视图一个目录。
  4. 不要过度使用视图:视图过多会增加配置复杂度和内存占用。
  5. 测试时用 dig 指定源地址dig -b 192.168.1.100 @server domain

📖 扩展阅读