1. 项目概述为什么要在Linux上折腾DNS转发最近在准备一个服务器相关的项目手头有几台机器一台是统信UOS另一台是CentOS它们都需要作为内网服务器为其他设备提供稳定的域名解析服务。直接让每台设备都去查询公共DNS不仅效率低延迟不稳定而且一旦遇到某些公共DNS抽风或者网络波动整个内网的服务发现就可能出问题。所以一个本地的、可控的DNS转发服务器就显得非常有必要了。它就像是你办公室里的一个“问询处”内部同事内网设备有任何找地址域名解析的需求都先来这里它能回答的缓存过的直接回答回答不了的再帮你出去问转发到上游DNS大大提升了效率和稳定性。这个需求在国产化替代和特定行业比如标题里提到的“国赛”环境中尤其常见。统信UOS作为国产主流操作系统CentOS则是服务器领域的经典掌握在这两种系统上配置DNS转发的技能算是运维和开发的一项基本功。网上教程很多但要么过于简略只给命令要么场景单一对于两者之间的差异和实际部署中的“坑”提及甚少。今天我就结合自己的实操经验把在统信UOS和CentOS上搭建DNS转发服务器的完整过程、核心配置、以及那些容易踩到的“雷”都梳理出来目标是让你看完就能动手一次配置成功。2. 核心思路与方案选型不止是改个配置文件那么简单在Linux上实现DNS转发核心是配置一个DNS缓存转发器。它的工作流程很简单客户端向它发起DNS查询请求它首先查看自己的缓存是否有记录有则立即返回没有则根据配置将请求转发给指定的上游DNS服务器如114.114.114.114, 8.8.8.8等拿到结果后返回给客户端并缓存起来。实现这个功能主流有两种技术方案使用systemd-resolved这是现代Linux发行版如较新版本的统信UOS、CentOS 8默认集成的网络解析管理器。配置相对简单通过修改/etc/systemd/resolved.conf文件即可。但它更偏向于客户端本地解析和链路管理作为全功能转发服务器有时显得力不从心日志和缓存管理也不如专业软件直观。使用dnsmasq或binddnsmasq轻量级、配置简单专为小型网络设计。它集成了DHCP和DNS转发功能对于绝大多数内网DNS转发、缓存需求来说它是“神器”般的存在。配置一个文件几行命令就能跑起来资源占用极小。bind功能极其强大的老牌DNS服务器软件可以配置成权威DNS、缓存DNS、转发DNS等。配置复杂但功能全面、性能强劲适用于大型、复杂的网络环境。为什么我强烈推荐 dnsmasq对于“实现DNS转发”这个目标尤其是在统信UOS和CentOS这样的服务器上dnsmasq是平衡了功能、易用性和资源消耗的最佳选择。systemd-resolved的转发功能有时会有一些奇怪的限制比如对某些记录类型的转发支持问题而bind则像是用牛刀杀鸡配置复杂度陡增。dnsmasq的配置文件通常只有几十行逻辑清晰排查问题方便并且它在各个发行版的软件源中都唾手可得。因此下文将围绕使用dnsmasq来实现DNS转发进行详细展开。当然我也会提一下systemd-resolved的快速配置方法作为备选。3. 环境准备与软件安装在开始配置之前我们需要确保系统环境就绪。无论是统信UOS还是CentOS第一步都是获取管理员权限并更新系统软件包。3.1 系统更新与权限确认打开终端首先切换到root用户或者使用sudo执行后续所有命令。这是服务器操作的基本安全规范也能避免很多权限错误。# 方法一直接切换到root用户需要root密码 su - # 方法二在普通用户下使用sudo前缀执行命令需要用户有sudo权限 sudo your_command接着更新系统的软件包列表确保我们安装的是最新版本的软件。这一步能解决很多因软件包版本过旧导致的依赖问题。# 在统信UOS基于Debian/Deepin上 sudo apt update sudo apt upgrade -y # 在CentOS 7 / Rocky Linux / AlmaLinux 8 等RHEL系上 sudo yum update -y # 在CentOS 8 / Rocky Linux 8 / AlmaLinux 8 上也可以使用dnf sudo dnf update -y注意在生产环境中大规模升级前建议先查看更新列表评估影响。但在实验或新环境中直接升级通常是安全的。3.2 安装 dnsmasq 软件包更新完系统后安装dnsmasq就非常简单了一条命令即可。# 在统信UOS上安装 sudo apt install dnsmasq -y # 在CentOS/RHEL系上安装 sudo yum install dnsmasq -y # 或使用 dnf sudo dnf install dnsmasq -y安装完成后系统会自动创建dnsmasq服务、默认配置文件以及必要的运行用户。我们可以先不启动它等配置完成后再启动。验证安装是否成功dnsmasq --version这条命令会输出dnsmasq的版本信息如果能正常显示说明安装成功。3.3 关键配置文件与目录说明安装好dnsmasq后我们需要认识几个关键的文件和目录这对后续配置和排错至关重要/etc/dnsmasq.conf这是dnsmasq的主配置文件。我们所有的核心配置都将在这里进行。默认情况下这个文件里有很多被注释掉的示例配置。/etc/dnsmasq.d/这是一个配置目录。你可以将自定义的配置片段以.conf为后缀放在这个目录下dnsmasq启动时会自动读取并合并。这种方式比直接修改主配置文件更清晰也便于管理多个配置。/etc/resolv.conf这是系统默认的DNS解析器配置文件。在配置dnsmasq作为系统DNS后这个文件通常会被指向127.0.0.1即本机。重要提示在一些由NetworkManager或systemd-resolved管理的系统上这个文件可能是动态生成的或一个符号链接直接修改可能无效或被覆盖。我们后续会处理这个问题。/var/log/dnsmasq.logdnsmasq的日志文件需要配置开启。这是排查DNS问题最宝贵的线索来源。/etc/hosts系统的本地主机名映射文件。dnsmasq默认会读取这个文件的内容作为最优先的DNS记录。4. 核心配置详解手把手打造你的DNS转发器现在进入核心环节配置dnsmasq。我们不打算启用它的DHCP功能只聚焦于DNS缓存和转发。4.1 备份与初始清理在修改任何配置文件之前养成备份的好习惯。sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.bak然后我们可以选择直接编辑主配置文件/etc/dnsmasq.conf或者更推荐的方式在/etc/dnsmasq.d/目录下创建一个新的配置文件例如custom.conf。这样做的好处是即使dnsmasq软件包升级你的自定义配置也不会被覆盖。sudo vim /etc/dnsmasq.d/custom.conf4.2 基础转发与缓存配置在custom.conf文件中我们添加以下核心配置# 1. 指定监听的网络接口 # 如果不指定dnsmasq默认监听所有接口包括回环口lo。为了安全建议明确指定。 # 假设你的服务器对内服务的网卡是 eth0 或 ens33请根据 ip addr 命令的实际输出修改。 interfaceeth0 # 如果你希望也监听本地回环可以加上通常需要用于本机测试 listen-address127.0.0.1 # 监听服务器对内的IP地址例如 192.168.1.100 listen-address192.168.1.100 # 2. 禁止dnsmasq作为DHCP服务器运行除非你需要 no-dhcp-interfaceeth0 # 3. 指定上游DNS服务器这是转发的关键 # 可以指定多个dnsmasq会按顺序尝试。国内推荐使用114DNS、阿里DNS等。 server114.114.114.114 server223.5.5.5 server8.8.8.8 # 你也可以针对特定域名使用特定的上游DNS例如所有.google.com的查询走8.8.8.8 # server/google.com/8.8.8.8 # 4. 启用详细的查询日志便于调试生产环境可关闭 log-queries # 指定日志文件位置需要确保dnsmasq用户有写入权限 log-facility/var/log/dnsmasq.log # 5. 设置缓存大小默认是150条对于小型网络足够大型网络可以增加 cache-size1000 # 设置不缓存未知域名减少缓存污染 no-negcache # 6. 设置本地域名可选 # 如果你的内网域是 mycompany.local可以这样设置这样查询 host1 会自动补全为 host1.mycompany.local # domainmycompany.local # expand-hosts # 7. 强制读取 /etc/hosts 文件默认就是读取的这里显式声明 read-ethers配置项解读与避坑指南interface和listen-address这是第一个大坑。如果你只配置了interfaceeth0那么dnsmasq只会监听eth0这个网卡上的所有IP地址。但有时你可能希望只监听某个特定的IP比如一个内网IP。更稳妥的做法是使用listen-address明确指定IP。我个人的经验是同时配置interface和具体的listen-address最为可靠。配置完成后一定要用netstat -tulnp | grep :53命令检查53端口DNS端口是否在你期望的IP上成功监听。server可以添加多个上游DNS。dnsmasq的机制是如果第一个服务器查询失败或超时才会尝试下一个。所以应该把最稳定、最快的放在前面。对于国内网络将国内公共DNS如114、阿里、腾讯放在前面是明智的选择。log-queries在调试阶段务必开启它能记录下每一个查询请求和响应是判断“为什么解析不了”的最直接证据。查看日志的命令是sudo tail -f /var/log/dnsmasq.log。缓存cache-size的单位是“条DNS记录”。1000条对于几十台设备的内网环境绰绰有余。no-negcache建议开启它避免缓存“此域名不存在”的否定应答防止因为一次偶然的查询失败导致后续一段时间内都无法解析。4.3 配置系统使用本地DNS转发器配置好了dnsmasq接下来需要告诉你的Linux服务器“以后所有DNS查询都先问本机127.0.0.1上的dnsmasq”。这需要修改系统级的DNS设置。重要警告在现代Linux上尤其是使用NetworkManager或systemd-resolved的系统直接修改/etc/resolv.conf可能无效因为它会被网络管理工具覆盖。推荐方法修改网络管理器配置一劳永逸对于统信UOS通常使用NetworkManager找到你的网络连接配置文件。可以通过图形界面网络设置修改或者在终端使用nmcli。# 列出所有连接 nmcli connection show # 假设你的连接名是“有线连接 1” sudo nmcli connection modify 有线连接 1 ipv4.dns 127.0.0.1 sudo nmcli connection modify 有线连接 1 ipv4.ignore-auto-dns yes sudo nmcli connection down 有线连接 1 sudo nmcli connection up 有线连接 1对于CentOS也常用NetworkManager方法与统信UOS类似。如果使用的是传统的network-scriptsCentOS 7常见则需要编辑网卡配置文件例如/etc/sysconfig/network-scripts/ifcfg-eth0添加或修改DNS1127.0.0.1 PEERDNSno # 禁止从DHCP获取DNS覆盖此设置然后重启网络服务sudo systemctl restart network。对于使用systemd-resolved的系统如果systemd-resolved是活跃的systemctl status systemd-resolved显示为active更规范的做法是配置它。# 编辑 resolved 的配置文件 sudo vim /etc/systemd/resolved.conf找到并修改/添加以下行[Resolve] DNS127.0.0.1 # 如果还有备用上游DNS可以在这里添加但dnsmasq已经做了转发这里通常只留127.0.0.1即可 # FallbackDNS114.114.114.114 223.5.5.5 Domains~. # 这个设置很重要表示所有域名都由此解析器处理保存后重启服务并链接/etc/resolv.confsudo systemctl restart systemd-resolved sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf验证系统DNS配置配置完成后执行cat /etc/resolv.conf应该看到nameserver 127.0.0.1。然后使用nslookup或dig测试nslookup baidu.com # 或者 dig baidu.com观察输出的SERVER一行应该是127.0.0.1#53。如果还是原来的公共DNS IP说明系统DNS配置未生效需要检查上述步骤。4.4 启动、测试与验证现在启动dnsmasq服务并设置开机自启。# 启动dnsmasq服务 sudo systemctl start dnsmasq # 设置开机自启 sudo systemctl enable dnsmasq # 检查服务状态确保是 active (running) sudo systemctl status dnsmasq关键测试步骤基础解析测试在服务器本机上测试一个外网域名和一个内网域名如果你在/etc/hosts里配置了。dig baidu.com dig your-internal-hostname # 替换为你的内网主机名第一次查询可能会稍慢因为要向上游请求。第二次查询相同的域名应该会显示FROM CACHE并且响应时间Query time极短如 0 msec这说明缓存生效了。日志验证打开另一个终端窗口实时查看日志。sudo tail -f /var/log/dnsmasq.log然后在第一个终端执行dig命令观察日志窗口是否有对应的查询和回复记录。这能直观地看到dnsmasq的工作流程。客户端测试将另一台电脑客户端的DNS服务器地址设置为你的Linux服务器的IP例如192.168.1.100。然后在客户端上执行nslookup或ping域名测试。切记要确保服务器防火墙放行了53端口的UDP/TCP入站请求这是第二个大坑。5. 防火墙与SELinux配置打通网络的关键即使dnsmasq配置完美服务运行正常如果防火墙没开端口外部客户端的请求也无法到达。同样在CentOS上SELinux也可能阻止dnsmasq绑定端口或访问网络。5.1 防火墙配置DNS主要使用UDP 53端口进行查询有时也会使用TCP 53端口进行区域传输或处理大型响应。我们需要在防火墙中放行这两个端口。在统信UOS可能使用ufw或firewalld上如果使用ufw:sudo ufw allow 53/udp sudo ufw allow 53/tcp sudo ufw reload如果使用firewalld(与CentOS相同):sudo firewall-cmd --permanent --add-servicedns sudo firewall-cmd --reload在CentOS默认使用firewalld上# 添加dns服务它默认包含了53/tcp和53/udp sudo firewall-cmd --permanent --add-servicedns # 或者直接添加端口 # sudo firewall-cmd --permanent --add-port53/tcp # sudo firewall-cmd --permanent --add-port53/udp # 重新加载防火墙配置 sudo firewall-cmd --reload # 验证规则是否添加成功 sudo firewall-cmd --list-all在输出中你应该在services:部分看到dns。5.2 SELinux 配置针对CentOS/RHEL系SELinux是另一个常见的“拦路虎”。如果SELinux处于 enforcing 模式可能会阻止dnsmasq绑定到53端口。检查SELinux状态getenforce # 输出可能是 Enforcing, Permissive, 或 Disabled临时解决方案不推荐生产环境设置为宽容模式。sudo setenforce 0永久解决方案推荐为dnsmasq添加正确的SELinux布尔值策略。# 1. 检查与dnsmasq和端口相关的布尔值 sudo getsebool -a | grep dnsmasq # 2. 通常需要允许dnsmasq使用网络和作为缓存DNS # 允许dnsmasq使用网络关键 sudo setsebool -P dnsmasq_use_tcp on sudo setsebool -P dnsmasq_udp_bind_http_port on # 允许dnsmasq作为缓存dns服务器 sudo setsebool -P dnsmasq_run_rescache on # 3. 如果上述布尔值还不够或者你的dnsmasq需要监听非标准端口可能需要添加端口标签 # 查看当前53端口的标签 sudo semanage port -l | grep -w 53 # 如果dnsmasq_port_t不在列表中需要添加通常默认已有 # sudo semanage port -a -t dnsmasq_port_t -p tcp 53 # sudo semanage port -a -t dnsmasq_port_t -p udp 53如果问题依旧可以查看SELinux的拒绝日志获取更精确的提示。sudo ausearch -m avc -ts recent | grep dnsmasq根据日志提示使用audit2allow工具生成自定义策略模块。实操心得在调试初期可以先将SELinux设置为Permissive模式让服务先跑起来。等所有功能测试正常后再切回Enforcing模式并根据日志逐一解决SELinux策略问题。直接禁用SELinux是下策会降低系统安全性。6. 高级配置与优化技巧基础功能搞定后我们可以根据实际需求进行一些高级配置让DNS转发器更加强大和顺手。6.1 域名特定转发与广告过滤dnsmasq支持非常灵活的域名匹配规则。特定域名走特定DNS比如让所有.internal后缀的域名查询转发到内网的一台权威DNS服务器192.168.1.10而其他所有查询走公共DNS。# 在 /etc/dnsmasq.d/custom.conf 中添加 server/internal/192.168.1.10 # 注意更具体的域名规则要放在更通用的规则前面屏蔽广告域名可以创建一个域名列表文件如/etc/dnsmasq.d/blocklist.conf将广告服务器的域名指向一个无效的地址如0.0.0.0或127.0.0.1。# 创建屏蔽列表文件 sudo vim /etc/dnsmasq.d/blocklist.conf # 添加内容例如 address/doubleclick.net/0.0.0.0 address/ads.google.com/0.0.0.0 # ... 可以添加很多行然后在主配置或custom.conf中确保包含了conf-dir/etc/dnsmasq.d这一行默认通常有。重启dnsmasq后对这些域名的查询将返回0.0.0.0从而达到屏蔽广告的效果。6.2 性能调优与缓存管理增大缓存对于有大量客户端或查询频繁的环境可以增加cache-size比如cache-size10000。调整最小TTL和最大TTLDNS记录都有生存时间TTL。dnsmasq允许你设置一个下限和上限防止上游返回过短或过长的TTL影响缓存效率或及时性。# 无论上游返回的TTL多短都至少缓存60秒 min-cache-ttl60 # 无论上游返回的TTL多长最多只缓存3600秒1小时 max-cache-ttl3600清空缓存在调试或需要立即刷新记录时可以重启dnsmasq服务来清空缓存。dnsmasq本身没有提供热重载缓存的功能。sudo systemctl restart dnsmasq6.3 配置为纯缓存DNS服务器如果你希望dnsmasq仅作为缓存服务器不提供任何本地记录不读取/etc/hosts不处理本地域可以添加no-hosts # 不读取 /etc/hosts domain-needed # 不转发不含域名的简单主机名查询 bogus-priv # 将私有IP段如10.x 192.168.x的逆向查询指向0.0.0.0这样配置后dnsmasq就变成了一个纯粹的转发和缓存代理。7. 常见问题排查与解决实录在实际部署中你几乎一定会遇到一些问题。下面是我踩过的一些坑和解决方法。7.1 服务启动失败错误dnsmasq: failed to create listening socket for port 53: Address already in use原因53端口被其他进程占用。可能是systemd-resolved、namedbind或其他程序。解决找出占用者sudo netstat -tulnp | grep :53如果是systemd-resolved可以停止并禁用它sudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved。注意这可能会影响主机自身的DNS解析需要确保dnsmasq配置正确并能处理本机查询。如果是named你需要决定是停用它还是让dnsmasq监听其他端口不推荐因为标准DNS端口是53。错误dnsmasq: cannot open log file /var/log/dnsmasq.log原因dnsmasq运行用户通常是dnsmasq或nobody没有权限写入指定的日志文件或目录。解决sudo touch /var/log/dnsmasq.log sudo chown dnsmasq:dnsmasq /var/log/dnsmasq.log # 用户组请根据实际情况调整 sudo chmod 644 /var/log/dnsmasq.log7.2 客户端无法解析域名症状服务器本机dig正常但客户端设置服务器IP后nslookup超时或失败。排查步骤检查防火墙在客户端telnet DNS服务器IP 53。如果连接失败基本就是防火墙问题。回顾第5节确保53端口已放行。检查dnsmasq监听地址在服务器上执行sudo netstat -tulnp | grep :53。确认dnsmasq进程监听的地址中包含了服务器对客户端的那个IP如192.168.1.100:53而不仅仅是127.0.0.1:53。如果没有检查配置文件中的listen-address设置。检查客户端DNS设置确认客户端网络配置中DNS服务器地址填写正确没有拼写错误。查看dnsmasq日志sudo tail -f /var/log/dnsmasq.log。在客户端发起一个查询看服务器端日志是否有收到请求。如果没有问题出在网络连通性或防火墙。如果有收到但没回复或回复错误则是dnsmasq配置或上游DNS问题。症状解析结果不对返回了错误的IP或SERVFAIL。排查步骤检查上游DNS在服务器上直接dig 114.114.114.114 baidu.com测试上游DNS是否工作正常。检查dnsmasq缓存可能是缓存了错误或过时的记录。重启dnsmasq服务清空缓存再试。检查特定域名规则如果你配置了类似server/example.com/1.2.3.4的规则确保没有意外的规则覆盖或干扰了你的查询。7.3 解析速度慢首次查询慢后续快这是正常的首次查询需要向上游请求并缓存。所有查询都慢检查上游DNS换用更快的上游DNS服务器测试。可以用dig或nslookup分别测试不同上游的响应时间。检查网络服务器本身到上游DNS的网络是否有问题。检查dnsmasq负载如果查询量巨大单个dnsmasq进程可能成为瓶颈。可以查看系统资源使用情况top,htop。dnsmasq是单进程的对于极高并发场景可能需要考虑使用bind或部署多个dnsmasq实例进行负载均衡。7.4 统信UOS与CentOS的差异点总结包管理器统信UOS用apt CentOS用yum/dnf。安装命令不同。默认服务管理两者现在都主要使用systemctl这点一致。网络配置管理统信UOS桌面版可能更依赖NetworkManager的图形界面或nmcli而CentOS服务器版可能使用network-scriptsCentOS 7或NetworkManagerCentOS 8。修改DNS的方法略有不同核心思想都是让系统的DNS指向127.0.0.1。SELinuxCentOS 默认开启并处于Enforcing模式需要额外配置。统信UOS 的 SELinux 策略可能有所不同或者默认未开启遇到权限问题的概率相对较低。防火墙统信UOS可能预装ufw或firewalldCentOS 7 默认是firewalld。命令需要对应调整。配置的本质是一样的都是安装dnsmasq编辑配置文件设置防火墙修改系统DNS。只要理解了原理这些差异只是命令和路径的不同而已。最关键的还是配置后的测试和日志分析这是定位问题的通用法门。