)
为什么要写这篇博文先说说我的经历吧。刚入行做运维那会儿公司服务器不到十台大家都是靠IP地址记——192.168.1.101 是测试数据库192.168.1.102 是Git仓库192.168.1.103 是内部Wiki……新人来了老员工丢给他一张Excel表“背下来”。结果呢换个IP就得更新表格还得群发邮件通知所有人效率低下不说还经常有人连错服务器搞得开发环境乌烟瘴气。后来我接触到了内网DNS才发现原来“用名字代替数字”这件事在Linux下不过是一套BIND服务就能搞定的事儿。从此以后但凡我负责的网络环境第一件事就是先把DNS搭起来——域名解析看似基础却是企业网络管理中投入产出比最高的环节之一。这篇文章我就把自己多年踩坑总结出来的经验完整地写下来希望能给正在苦恼于IP管理的你带来一些实实在在的帮助。---第一章你真的需要自建DNS吗很多朋友会问“我用外网DNS不也行吗比如把内网域名注册到阿里云解析到内网IP”这里要澄清一个概念外网DNS只能解析公网IP而企业内网大量的服务IP都是私有地址比如10.x.x.x、192.168.x.x这些地址在外网根本不可路由所以必须在内网搭建自己的DNS服务器。另外自建DNS的好处远不止“记名字”这么简单。你可以用它做负载均衡同一个域名解析多个IP轮询、可以做服务高可用切换主备切换时只需改DNS记录、可以配合自动化运维实现服务发现新服务上线自动注册域名。可以说DNS是微服务治理的雏形很多公司哪怕上了Kubernetes内部依然保留着DNS做服务别名可见其生命力之强。当然如果你的公司只有三五台机器那确实没必要大费周章。但当服务器数量超过20台或者团队超过5个人**DNS带来的效率提升就已经远远超过它的维护成本了**。我在实践中感受到最直接的收益就是再也不用在群里所有人“XXX的IP换了大家更新一下hosts文件”——因为用DNS你只需要在服务器上改一条记录客户端自动生效省心太多。---第二章准备工作——网络规划与系统环境2.1 我的实验环境-操作系统CentOS 7.9最小化安装当然CentOS 8也适用命令基本一致。-服务器角色主DNS服务器同时作为权威解析和递归解析。-硬件配置2核CPU、4G内存、20G硬盘——对于DNS服务来说绰绰有余甚至给1核1G都跑得飞起。2.2 网络规划的重要性DNS服务器必须使用**固定IP**这是毋庸置疑的。我习惯将服务器划分两个网段一个用于远程管理SSH一个专门承载业务流量。这样做的好处是即使业务网络出现广播风暴或异常流量管理网依然能连上去排查问题。在我的环境里管理网IP是 192.168.137.100/24业务网IP是 10.10.0.100/24。DNS服务将监听在业务网IP上以便所有内网客户端都能访问。如果你只有一张网卡那没关系只要IP是固定的就行。配置静态IP的步骤很简单编辑 /etc/sysconfig/network-scripts/ifcfg-ens32网卡名称可能不同用 ip a 查看把 BOOTPROTOdhcp 改成 static然后加上 IPADDR、NETMASK、GATEWAY、DNS1这里DNS可以暂时填114.114.114.114等自己搭好了再改回来。改完保存执行 systemctl restart network 即可生效。记得用 ping 测试一下网关通不通。2.3 关闭防火墙还是放行端口很多新手图省事会直接 systemctl stop firewalld但这样做在生产环境是绝对不允许的。正确的做法是只开放需要的端口——对于DNS就是UDP 53和TCP 53。UDP用于普通查询TCP用于大响应数据比如区域传输和DNS-over-TCP。我们后面会统一配置防火墙规则现在暂时可以保持开启等装完BIND再一起放行。---第三章BIND安装与初步配置3.1 BIND到底是什么BIND全称是Berkeley Internet Name Domain是目前互联网上应用最广泛的DNS软件没有之一。它实现了DNS协议的所有标准功能既能做权威解析回答“www.company.local的IP是多少”也能做递归解析帮你问外面的DNS服务器“www.baidu.com”的IP是多少。在企业内网我们通常两种功能都开启这样客户端把DNS指向我们的服务器后既能解析内网域名也能正常上网。安装命令很简单直接 yum install -y bind bind-utils。其中 bind-utils 包含了 dig、nslookup 等工具用来测试解析是否正常非常实用。3.2 主配置文件 named.conf 详解安装完成后核心配置文件是 /etc/named.conf。这个文件默认有不少内容但大部分是注释我们可以先备份一下然后重新写一个精简版。打开文件你会发现它主要分为几个部分options 全局选项、logging 日志配置、以及区域定义zone。对于初学者最需要关注的是 options 块里的几个参数-listen-on指定BIND在哪些IP和端口上监听。默认只有 127.0.0.1这意味着只有本机能查询其他人根本访问不到。所以我们必须加上内网IP比如 10.10.0.100。-allow-query允许哪些IP段发起查询。为了安全只写内网网段绝对不要写 any。-recursion是否开启递归解析。如果你希望客户端能用这台DNS解析外网域名就设为 yes如果只做权威解析比如只解析 company.local就设为 no。大多数企业会开启递归方便客户端统一上网。- forwarders如果内网不能直接访问外网根服务器比如需要走代理可以在这里指定上游DNS比如 223.5.5.5.5BIND会把递归请求转发给它们。我一般会在 options 里加上 version not available; 来隐藏版本号这是最基本的安全加固。3.3 添加自定义区域区域Zone指的是一个域名空间比如 company.local。我们告诉BIND凡是查询 company.local 下面任何域名如 www.company.local、git.company.local的请求都由我来回答回答的内容在指定的区域文件中。在 /etc/named.rfc1912.zones 文件末尾或者直接在 named.conf 末尾添加如下内容zone company.local IN { type master; file /var/named/company.local.zone; allow-update { none; }; };- type master 表示这是主服务器数据由自己维护。- file 指定区域数据文件路径必须放在 /var/named/ 目录下且属主为 named 用户。- allow-update { none; }; 禁止动态更新避免安全风险。如果你需要DDNS动态DNS可以改成允许特定密钥更新但这里我们暂不涉及。---第四章区域文件——核心数据写哪里4.1 区域文件的结构区域文件是一个纯文本文件记录了域名到IP的映射关系正向解析以及IP到域名的映射反向解析。它的格式遵循DNS规范包含了SOA、NS、A、PTR、CNAME等记录类型。先说SOA记录这是每个区域文件的第一条记录用于说明该区域的基本属性主域名服务器、管理员邮箱用点代替、序列号Serial、刷新间隔、重试间隔、过期时间、负缓存TTL。其中序列号非常关键当你修改了任何记录后**必须增加序列号的值**否则从服务器不会同步新数据主服务器自己也不会重新加载——很多新手改了配置后不生效十有八九是忘了递增序列号。我个人的习惯是采用日期序号格式比如 2025070101表示2025年7月1日的第一次修改清晰明了。4.2 完整的正向区域文件示例下面是我在实际环境中使用的 company.local.zone 文件内容。这里我把每个部分都解释一下方便你理解。$TTL 604800 IN SOA ns1.company.local. admin.company.local. ( 2025070101 ; Serial 604800 ; Refresh (秒) 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; 名字服务器记录 IN NS ns1.company.local. ; 地址记录 IN A 10.10.0.100 ns1 IN A 10.10.0.100 www IN A 10.10.0.101 git IN A 10.10.0.102 api IN A 10.10.0.103- $TTL 604800 表示默认的生存时间即客户端缓存这条记录的时间单位是秒604800秒7天。内网环境可以设短一点方便快速更新。- 代表当前域名即 company.local。- SOA后面的 ns1.company.local. 是主DNS的域名注意末尾有点号表示绝对域名。- admin.company.local. 是管理员邮箱实际上 admincompany.local用点代替。- 下面NS记录声明了权威服务器A记录就是具体的解析条目。你可以根据需要添加更多A记录比如 jenkins、confluence 等。只要你能规划好整个公司所有内部服务都可以在这里注册。4.3 反向解析文件可选反向解析虽然不强制但在很多场景下很有用。比如当你查看访问日志时看到的是IP地址如果有反向解析日志里会直接显示域名排查问题会方便很多。另外有些服务如邮件服务器会做反向查询验证所以养成配置反向解析的习惯是好的。反向区域的名称是IP地址的反写 .in-addr.arpa。比如我的业务网段是 10.10.0.0/24反向域就是 0.10.10.in-addr.arpa。在 named.rfc1912.zones 里增加zone 0.10.10.in-addr.arpa IN { type master; file /var/named/10.10.0.zone; }; 然后创建 /var/named/10.10.0.zone内容如下 $TTL 604800 IN SOA ns1.company.local. admin.company.local. (2025070101 604800 86400 2419200 604800) IN NS ns1.company.local. 100 IN PTR ns1.company.local. 101 IN PTR www.company.local. 102 IN PTR git.company.local.注意PTR记录的写法只写IP的最后一位数字因为前面已经在区域声明中确定了网段。4.4 权限检查区域文件创建后一定要检查属主和权限。BIND进程以 named 用户身份运行因此文件必须归属于 named 用户或者至少可读。一般执行chown named:named /var/named/company.local.zone /var/named/10.10.0.zone chmod 640 /var/named/*.zone否则启动时会报 permission denied 错误很多人就卡在这里。---第五章启动服务与防火墙放行5.1 启动BIND一切准备就绪我们就可以启动服务了systemctl start named systemctl enable named启动后可以用 systemctl status named 查看状态如果显示 active (running) 就说明成功了。如果有报错用 tail -f /var/log/messages 实时查看日志绝大多数错误都会在这里提示比如配置文件语法错误、区域文件格式错误等。5.2 防火墙配置前面说过了不要直接关防火墙。正确的做法是放行DNS端口firewall-cmd --permanent --add-port53/udp firewall-cmd --permanent --add-port53/tcp firewall-cmd --reload如果你用了 firewalld 的默认服务也可以 --add-servicedns效果一样。顺便把 named 服务加入防火墙的信任区不端口就够。5.3 测试本机解析先在本机测试确保服务能正确响应dig 127.0.0.1 www.company.local返回结果中应该能看到 ANSWER SECTION 包含 10.10.0.101。再用反向查询dig 127.0.0.1 -x 10.10.0.101同样能看到 101.0.10.10.in-addr.arpa 的PTR记录。如果成功说明基本配置没问题。接下来可以换一台内网机器将其DNS设置为 10.10.0.100然后运行 nslookup www.company.local。如果能解析那就大功告成啦---第六章安全加固与日常维护6.1 限制递归范围递归功能虽然方便但也容易被利用作放大攻击DNS反射攻击。所以我们要在 options 里加上allow-recursion { 192.168.137.0/24; 10.10.0.0/24; };这样只有内网客户端才能利用递归外网访问只能得到权威解析如果有的话。如果你只有内网使用那就直接限制到内网网段。6.2 隐藏版本信息在 options 里添加 version unknown; 或 version not currently available;可以防止攻击者通过 dig server version.bind chaos txt 获取BIND版本从而针对性利用已知漏洞。6.3 开启DNSSEC先不着急DNSSEC域名安全扩展虽然能防止DNS欺骗但配置复杂且需要客户端支持中小企业暂时可以不考虑。等以后有时间再慢慢折腾。6.4 定期备份区域文件DNS记录是企业的核心资产必须定期备份。我写了一个简单的备份脚本放在 /root/backup_dns.sh#!/bin/bash cp /var/named/*.zone /backup/dns/$(date %Y%m%d)/ find /backup/dns/ -mtime 30 -delete然后加入cron每天凌晨3点执行0 3 /root/backup_dns.sh这样即使误操作删除了记录也能快速恢复。6.5 监控服务健康建议用监控工具比如Zabbix或Prometheus定期探测DNS解析是否正常。最简单的可以写一个脚本每分钟查询一个固定域名如果失败则报警。毕竟DNS挂了内网大部分服务都会跟着瘫痪这个监控优先级很高。---第七章常见问题与排错经验接下来我把自己几年遇到过的问题总结一下希望能帮你少走弯路。问题1启动失败提示 cannot open file /var/named/company.local.zone: permission denied解决办法检查文件属主执行 chown named:named并确保目录权限至少为 755。问题2修改了记录但客户端查询结果不变原因99%是序列号没递增。记得每次修改都要加大Serial值并执行 rndc reload 或重启服务。问题3客户端能解析内网域名但无法上网检查 recursion yes; 是否开启以及服务器本身能否访问外网ping 114.114.114.114。如果网络不通需要配置 forwarders。问题4防火墙放行了端口但外部还是超时检查SELinux是否拦截。可以临时 setenforce 0 测试如果有效则用 chcon 或 semanage 为BIND配置正确的上下文。问题5日志报 no more recursive clients这是递归查询并发数超过限制。在 options 里调大 recursive-clients 的值比如 recursive-clients 1000;。问题6主从同步失败检查从服务器的 allow-transfer 配置以及主服务器的 also-notify并确保序列号一致。---第八章进阶方向与结语当你把基础的单机DNS跑起来之后还可以继续折腾以下几个方向-主从架构加一台备用DNS提高可用性。配置也很简单从服务器上 type slave; 指定 masters 即可。-智能DNS视图根据客户端来源IP返回不同的解析结果比如内网用户访问 www 得到内网IP外网用户得到公网IP。-与自动化工具结合比如用Ansible推送DNS配置用Git管理区域文件实现配置即代码。回到文章开头那个故事自从我搭建了内网DNS公司里再没有人抱怨“又连错服务器”了。新员工入职只需要告诉他“访问 git.company.local 就能拉代码”就这么简单。运维的价值有时候就体现在这些看不见的细节里——让复杂的事变得简单让混乱变得有序。这篇博文从零开始手把手带你完成了企业内网DNS服务器的搭建、配置、测试和加固。如果你按照步骤一步步来相信一定能够成功。如果在实践过程中遇到任何问题欢迎在评论区留言我看到后会尽量回复。如果你觉得文章有帮助也请点个赞支持一下让更多有需要的人看到。最后感谢你的阅读祝你的运维之路越走越顺畅---本文仅作学习请自行判断文中代码正确性。