DNS核心概念
什么是域名(Domain Name)
域名是互联网中用于标识主机的人类可读地址,是 IP 地址的友好映射。由于 IP 地址(如 192.168.1.1 或 2001:db8::1)难以记忆,域名通过分层结构(如www.example.com)简化主机标识。
域名分层结构(从右到左):
- 根域(.):最高层级,隐含在所有域名末尾(如www.example.com.)
- 顶级域(TLD):如.com(商业)、.org(组织)、.cn(国家顶级域)
- 二级域:如 example(核心品牌 / 机构标识)
- 主机记录:如 www(web 服务器)、mail(邮件服务器)
什么是 DNS(Domain Name System)
DNS(域名系统)是互联网的分布式域名解析服务,核心功能是将域名(如www.example.com)转换为 IP 地址(如 192.168.1.100),反之也支持 IP 到域名的反向解析。
DNS 的核心价值:
- 解决 IP 地址难记忆问题
- 支持服务地址动态切换(无需修改客户端配置)
- 分布式架构保证高可用与负载均衡
- 支持多种资源记录(IP、邮件服务器、别名等)
正向解析与反向解析
正向解析(Forward Resolution)
最常用的 DNS 解析类型:域名 → IP 地址的映射过程。
例如:将www.example.com解析为 192.168.1.100,用于用户通过域名访问网站、API 等服务。
反向解析(Reverse Resolution)
IP 地址 → 域名的映射过程,核心用于身份验证(如邮件服务器反垃圾邮件、日志审计)。
例如:将 192.168.1.100 解析为www.example.com,验证该 IP 对应的主机是否为合法服务节点。
客户端域名解析流程(hosts 文件优先机制)
当终端(Windows/Linux/macOS)发起域名解析请求时,遵循本地优先、逐级向上的流程,其中hosts文件优先级最高:
graph TD
A[用户输入域名访问] --> B{查询本地hosts文件}
B -- 存在对应记录 --> C[直接使用hosts中的IP访问]
B -- 无对应记录 --> D{查询本地DNS缓存}
D -- 缓存命中 --> E[使用缓存IP访问]
D -- 缓存未命中 --> F[向配置的DNS服务器发起请求]
F --> G[DNS服务器递归/迭代解析]
G --> H[返回IP地址给客户端]
H --> I[客户端缓存结果并访问目标主机]
关键说明
hosts 文件路径:
Windows:C:\Windows\System32\drivers\etc\hosts
Linux/macOS:/etc/hosts
hosts 文件格式:一行一条记录,格式为 IP地址 域名 [别名],
例如:
192.168.1.100 www.example.com example.com
优先级顺序:hosts文件 > 本地DNS缓存 > 配置的DNS服务器
适用场景:本地测试、临时映射、屏蔽恶意域名(无需依赖 DNS 服务器)
环境准备
前置条件
- 服务器关闭防火墙(或开放 53 端口,DNS 使用 UDP/53 和 TCP/53)
- 禁用 SELinux(或配置规则)
- 网络互通,服务器可正常联网(用于安装依赖)
安装Bind9
# 更新系统包
dnf update -y
# 安装BIND核心组件(named为DNS服务进程)
dnf install -y bind bind-utils bind-libs bind-chroot
# 验证安装结果
rpm -qa | grep bind
# 预期输出示例:bind-9.16.23-10.el9.x86_64、bind-utils-9.16.23-10.el9.x86_64
核心组件说明
- bind:DNS 服务器核心程序(named 进程)
- bind-utils:DNS 测试工具(dig、nslookup、host)
- bind-libs:BIND 依赖库
- bind-chroot:安全加固组件(将 named 进程限制在/var/named/chroot目录,降低安全风险)
BIND9 核心配置
BIND 的配置文件分为两类:主配置文件(全局参数)和区域配置文件(解析规则)。
主配置文件(/etc/named.conf)
主配置文件定义 DNS 服务器的全局参数(监听地址、允许查询的客户端、区域文件路径等)。
# 备份默认配置文件
cp /etc/named.conf /etc/named.conf.bak
# 编辑主配置文件
vim /etc/named.conf
替换为以下配置(关键注释已标注):
options {
// 监听地址(0.0.0.0表示所有IPv4地址,::表示所有IPv6地址)
listen-on port 53 { 0.0.0.0; };
listen-on-v6 port 53 { ::; };
// DNS服务器根目录(bind-chroot启用后实际为/var/named/chroot/var/named)
directory "/var/named";
// 缓存文件路径
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
// 允许查询的客户端(配置为内网网段,如192.168.1.0/24,或any允许所有)
allow-query { 192.168.1.0/24; localhost; localnets; };
// 递归查询(允许客户端请求服务器代为查询外部域名)
recursion yes;
// 禁用DNSSEC(测试环境关闭,生产环境建议启用)
dnssec-enable no;
dnssec-validation no;
// 转发器(当本地无解析记录时,转发请求到公共DNS服务器)
forwarders {
223.5.5.5; // 阿里云DNS
119.29.29.29; // 腾讯云DNS
8.8.8.8; // Google DNS(备选)
};
// 其他默认参数
bindkeys-file "/etc/named.root.key";
managed-keys-directory "/var/named/dynamic";
pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
};
// 日志配置(记录查询日志到/var/log/named/query.log)
logging {
channel query_log {
file "/var/log/named/query.log" versions 3 size 10m;
severity info;
print-time yes;
print-category yes;
print-severity yes;
};
category queries { query_log; };
};
// 根域解析(默认配置,指向根服务器列表)
zone "." IN {
type hint;
file "named.ca";
};
// 正向解析区域配置(自定义域名example.com)
zone "example.com" IN {
type master; // 主服务器(权威DNS)
file "example.com.zone"; // 正向解析区域文件路径
allow-update { none; }; // 禁止动态更新(生产环境可配置ACL)
};
// 反向解析区域配置(网段192.168.1.0/24)
// 反向区域名格式:网段反转 + .in-addr.arpa(IPv4)
zone "1.168.192.in-addr.arpa" IN {
type master;
file "192.168.1.zone"; // 反向解析区域文件路径
allow-update { none; };
};
// 包含动态DNS配置(默认)
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
正向解析
区域文件是实际存储域名 - IP 映射关系的文件,需放在/var/named目录下(bind-chroot 启用后实际路径为/var/named/chroot/var/named)。
正向解析区域文件(example.com.zone)
# 创建正向区域文件(复制模板文件,保留权限)
cp /var/named/named.localhost /var/named/example.com.zone
chmod 640 /var/named/example.com.zone # named进程需读取权限
chown root:named /var/named/example.com.zone # 属主为root:named
# 编辑正向区域文件
vim /var/named/example.com.zone
配置内容(关键记录说明见注释):
$TTL 1D ; 缓存时间(1天)
@ IN SOA example.com. admin.example.com. (
2025112801 ; 序列号(格式:年月日+版本号,更新需递增)
1D ; 刷新时间(从服务器同步主服务器记录的间隔)
1H ; 重试时间(同步失败后重试间隔)
1W ; 过期时间(从服务器同步失败后,多久不再提供解析)
3H ) ; 否定缓存时间(查询不存在记录的缓存时长)
IN NS dns-server.example.com. ; 该区域的权威DNS服务器
IN A 192.168.1.200 ; example.com的A记录(域名对应IPv4)
IN AAAA ::1 ; 可选:IPv6记录(若需支持IPv6)
; 主机记录(A记录:域名→IPv4)
dns-server IN A 192.168.1.200 ; DNS服务器自身映射
www IN A 192.168.1.100 ; web服务器
mail IN A 192.168.1.101 ; 邮件服务器
ftp IN A 192.168.1.102 ; FTP服务器
; 别名记录(CNAME:域名别名→主域名)
blog IN CNAME www.example.com. ; blog.example.com别名指向www.example.com
mail2 IN CNAME mail.example.com. ; 邮件服务器别名
反向解析
反向解析区域文件(192.168.1.zone)
# 创建反向区域文件
cp /var/named/named.localhost /var/named/192.168.1.zone
chmod 640 /var/named/192.168.1.zone
chown root:named /var/named/192.168.1.zone
# 编辑反向区域文件
vim /var/named/192.168.1.zone
配置内容:
$TTL 1D
@ IN SOA example.com. admin.example.com. (
2025112801 ; 序列号(需与正向区域文件一致或递增)
1D
1H
1W
3H )
IN NS dns-server.example.com. ; 权威DNS服务器
; 反向记录(PTR记录:IP→域名)
; 格式:IP最后一段 IN PTR 完整域名.
200 IN PTR dns-server.example.com. ; 192.168.1.200 → DNS服务器
100 IN PTR www.example.com. ; 192.168.1.100 → web服务器
101 IN PTR mail.example.com. ; 192.168.1.101 → 邮件服务器
102 IN PTR ftp.example.com. ; 192.168.1.102 → FTP服务器
配置权限与安全加固
目录权限调整
named 进程运行用户为named,需确保配置文件和区域文件可被读取:
# 调整named目录权限
chown -R root:named /var/named
chmod -R 750 /var/named
# 创建日志目录并授权
mkdir -p /var/log/named
chown named:named /var/log/named
chmod 750 /var/log/named
启用 bind-chroot(可选,增强安全性)
bind-chroot 将 named 进程的根目录切换到/var/named/chroot,即使进程被劫持,攻击者也只能访问该目录:
# 启用chroot(修改named.service配置)
vim /usr/lib/systemd/system/named.service
在[Service]段添加以下内容:
ExecStartPost=/usr/sbin/named-checkconf -z /etc/named.conf
ExecStart=/usr/sbin/named -u named -t /var/named/chroot # 添加-t参数指定chroot目录
重新加载系统服务配置:
systemctl daemon-reload
DNS开机自启
# 验证配置文件语法(关键!配置错误会导致服务启动失败)
named-checkconf /etc/named.conf # 主配置文件校验,无输出则正常
named-checkzone example.com /var/named/example.com.zone # 正向区域文件校验
named-checkzone 1.168.192.in-addr.arpa /var/named/192.168.1.zone # 反向区域文件校验
# 启动named服务
systemctl start named
# 设置开机自启
systemctl enable named
# 查看服务状态
systemctl status named
# 预期输出:active (running)
防火墙与Selinux配置
开放端口53
# 开放UDP/53(主要)和TCP/53(区域传输、长查询)
firewall-cmd --permanent --add-port=53/udp
firewall-cmd --permanent --add-port=53/tcp
# 重新加载防火墙规则
firewall-cmd --reload
# 验证开放结果
firewall-cmd --list-ports | grep 53
Selinux配置
若启用 SELinux,需配置规则允许 named 进程访问相关文件:
# 允许named读取区域文件
setsebool -P named_write_master_zones on
setsebool -P named_read_master_zones on
# 配置区域文件SELinux上下文
semanage fcontext -a -t named_zone_t "/var/named/example.com.zone"
semanage fcontext -a -t named_zone_t "/var/named/192.168.1.zone"
restorecon -v /var/named/*.zone
# 允许named写入日志
semanage fcontext -a -t named_log_t "/var/log/named(/.*)?"
restorecon -v /var/log/named
DNS服务器测试
本地服务器测试
DNS正向解析测试
dig @192.168.1.200 www.example.com A
dig @192.168.1.200 mail.example.com A
dig @192.168.1.200 blog.example.com CNAME # 测试别名记录
# 测试反向解析(IP→域名)
dig @192.168.1.200 192.168.1.100 PTR
dig @192.168.1.200 192.168.1.101 PTR
# 测试外部域名解析(验证转发器是否生效)
dig @192.168.1.200 www.baidu.com A
测试成功判断:输出结果中ANSWER SECTION包含正确的 IP 或域名,例如:
;; ANSWER SECTION:
www.example.com. 86400 IN A 192.168.1.100
Linux终端测试
# 临时修改客户端DNS为服务器IP
echo "nameserver 192.168.1.200" > /etc/resolv.conf
# 测试解析
nslookup www.example.com
host mail.example.com
dig 192.168.1.102 PTR # 反向解析测试
Windows终端测试
- 打开「网络和共享中心」→ 「本地连接」→ 「属性」→ 「IPv4 属性」
- 手动设置 DNS 服务器为 192.168.1.200
打开命令提示符(CMD)测试:
nslookup www.example.com
nslookup 192.168.1.100 # 反向解析
ping blog.example.com # 验证别名解析
验证 hosts 文件优先级
在客户端测试 hosts 文件覆盖 DNS 解析:
# Linux客户端修改hosts
echo "192.168.1.250 www.example.com" >> /etc/hosts
# 测试解析(应返回hosts中的192.168.1.250,而非DNS服务器的192.168.1.100)
nslookup www.example.com
dig www.example.com A
# 测试完成后删除hosts中的测试记录
sed -i '/192.168.1.250 www.example.com/d' /etc/hosts
Linux Openeuler DNS部署实战
wpzglfpsysdqrvpgslhmpnqflxivhu