在Linux服务器上为企业级应用实现内部域名解析,核心思路是:搭建一个独立的内部DNS服务器,然后通过VPN的配置,将这个DNS服务器的地址“推送”给所有连接到VPN的客户端。这样,无论客户端在哪里,只要连上VPN,就能自动使用内部DNS来解析内部域名,无需修改每台机器的hosts文件。

企业级内部DNS的实现方式

企业级场景下,通常不会在每台机器上手动维护hosts,也不会依赖路由器,而是会部署一个专用的DNS服务器软件。主流的方案有:

  • **BIND (named)**:功能最全面、最稳定,是构建权威DNS服务器的行业标准,适合复杂的企业环境。它支持视图(View)、区域传送、DNSSEC等高级功能。
  • Unbound:一款注重安全、性能和隐私的递归与缓存DNS服务器,配置相对现代,适合作为生产环境的解析器。
  • dnsmasq:轻量易用,同时提供DNS和DHCP功能。
  • CoreDNS:在Kubernetes生态中非常流行,插件化架构灵活,也适合作为通用的内部DNS服务器。

内网机器指向dns

DNS服务器配置完成后,还需要让内网把查询发给它。

使用 systemd-resolved 的系统,编辑 /etc/systemd/resolved.conf:

1
2
[Resolve]
DNS=192.168.1.10 223.5.5.5

然后重启:

1
sudo systemctl restart systemd-resolved

与VPN集成:实现自动下发DNS

OpenVPN:使用 push 指令下发DNS

OpenVPN服务端可以通过 push 指令,将DNS设置下发给客户端。

在你的OpenVPN服务端配置文件(如 server.conf)中,添加以下内容:

1
2
3
4
5
6
7
8
9
# 推送DNS服务器地址(即你内部DNS服务器的VPN隧道IP)
push "dhcp-option DNS 10.8.0.1"

# 推送域名搜索后缀,客户端解析短名称时会自动补全
push "dhcp-option DOMAIN internal.com"

# 如果需要多个搜索后缀,可以用 `DOMAIN-SEARCH`,它会把域名追加到搜索列表
push "dhcp-option DOMAIN-SEARCH internal.com"
push "dhcp-option DOMAIN-SEARCH dev.internal.com"

WireGuard:使用 PostUp 脚本配置DNS

WireGuard本身没有推送DNS的机制,但可以通过客户端的 PostUp 钩子,在建立连接后自动执行命令来配置DNS。

linux客户端

在WireGuard客户端配置文件(如 wg0.conf)的 [Interface] 部分:

1
2
3
4
5
6
[Interface]
# ... 其他配置 ...

# 使用 resolvectl (适用于 systemd-resolved) 动态添加DNS
PostUp = resolvectl domain %i ~internal.com; resolvectl dns %i 10.1.0.1
PostDown = resolvectl revert %i

windows客户端

出于安全考虑,WireGuard for Windows 默认禁用 PreUp、PostUp、PreDown、PostDown 脚本。必须先以管理员身份修改注册表来开启此功能:

1
reg add HKLM\Software\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f

在注册表修改完成后,你可以在配置文件的 [Interface] 部分,使用以下基于 NRPT (名称解析策略表) 的 PowerShell 命令来替代 resolvectl。

1
2
3
PostUp = powershell.exe -Command "Add-DnsClientNrptRule -Comment 'WG-Internal-DNS' -Namespace '.internal.com' -NameServers '10.1.0.1'"

PostDown = powershell.exe -Command "Get-DnsClientNrptRule | Where-Object { $_.Comment -eq 'WG-Internal-DNS' } | Remove-DnsClientNrptRule -Force"

验证

VPN 连通后

1
2
3
4
5
6
7
# Linux
resolvectl status %i | grep -A3 internal.com
resolvectl query app.internal.com

# Windows PowerShell
Get-DnsClientNrptRule | Where-Object { $_.Namespace -eq '.internal.com' }
Resolve-DnsName app.internal.com