我有许多远程位置的网络,我希望能够通过 VPN 访问它们。每个网络的拓扑结构都很简单,就是一个 NAT 路由器和一台运行 SSH 服务器的机器。路由器已转发 SSH 端口,因此只需能够访问路由器的 IP 即可。我已经配置了一个 OpenVPN 服务器,并在每个远程网络上设置了路由器以访问它。客户端 PC 也配置为访问 VPN,并且服务器已配置为可以使用其 VPN IP 地址访问各个路由器。
拓扑:
这一切都很好,只是客户端不知道路由器的 VPN IP 地址。目前,我必须查看 OpenVPN 状态日志,然后使用该 IP。我宁愿不使用静态 IP,因为远程网络的数量会增加。
所以,我的问题是,是否可以在 VPN 服务器上运行本地 DNS 服务器,并让其自动为连接的客户端进行更新?
我已经看到了几篇关于更新 VPN 服务器上的 resolv.conf 以及将 DNS 详细信息推送到客户端的文章,但不确定实际运行和更新 DNS 服务器所缺少的部分。
服务器配置:
port 1194
proto udp
dev tun
ca ca.crt
cert cert.crt
key key.key # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
client-to-client
keepalive 10 120
cipher AES-256-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3
答案1
为了让其他人寻找类似问题的解决方案,这就是我解决问题的方法。
我在示例配置中添加/取消注释了以下 OpenVPN 服务器设置(/etc/openvpn/server.conf),以告诉客户端使用其 DNS 服务器,并允许客户端相互通信:
topology subnet
push "dhcp-option DOMAIN myvpn.example.com"
push "dhcp-option DNS 10.8.0.1"
client-to-client
然后我使用以下内容配置了 dnsmasq (/etc/dnsmasq.conf),它监听 VPN 连接,并使用额外的 hosts 文件,我们将保持更新:
domain-needed
bogus-priv
local-service
listen-address=127.0.0.1
listen-address=10.8.0.1
local=/myvpn.example.com/
addn-hosts=/etc/hosts.openvpn
最后,以下 Python 脚本(位于 /usr/local/sbin/update-openvpn-hosts 中)使用openvpn 状态库来更新附加主机文件并重新加载 dnsmasq 配置。它每分钟从 /etc/crontab 中的 cron 作业调用一次(* * * * * root /usr/local/sbin/update-openvpn-hosts
)。
#!/usr/bin/env python3
"""Create hosts file from OpenVPN client list."""
import subprocess
import openvpn_status
with open('/etc/openvpn/openvpn-status.log') as logfile:
status = openvpn_status.parse_status(logfile.read())
with open('/etc/hosts.openvpn', 'w') as hostsfile:
for routing in status.routing_table.values():
line = '{0} {1} {1}.myvpn.example.com\n'.format(routing.virtual_address, routing.common_name)
hostsfile.write(line)
subprocess.run(['systemctl', 'reload', 'dnsmasq'])
需要注意的一点是,当连接到 VPN 时,全部DNS 请求将通过 VPN 服务器进行路由,而不仅仅是发往 VPN 客户端的请求。这是 DNS 的一个基本限制。