![将传入的外部 DNS 数据包转发到嵌入式 docker DNS](https://linux22.com/image/693951/%E5%B0%86%E4%BC%A0%E5%85%A5%E7%9A%84%E5%A4%96%E9%83%A8%20DNS%20%E6%95%B0%E6%8D%AE%E5%8C%85%E8%BD%AC%E5%8F%91%E5%88%B0%E5%B5%8C%E5%85%A5%E5%BC%8F%20docker%20DNS.png)
我在 docker 容器中运行 openvpn 服务。链接到此容器的是一些其他容器,包括一个 gitlab 容器。我希望能够使用其容器名称作为主机从 VPN 客户端访问此 gitlab 容器。我喜欢使用 docker 网络来管理哪些容器可以通过 VPN 访问的想法。
由于 docker 具有其嵌入式 DNS 功能,我认为这应该可以通过将 DNS 数据包转发给它(127.0.0.11:53)来实现,这样我就可以使用 VPN 服务器的地址作为客户端上的名称服务器。
至少,在 OVPN 容器中本地执行时,似乎有一个有效的 DNS 服务:
bash-4.3# nslookup gitlab 127.0.0.11
Server: 127.0.0.11
Address 1: 127.0.0.11
Name: gitlab
Address 1: 172.19.0.2 gitlab_gitlab_1.gitlab_default
但是,我的 iptables 路由不起作用:
iptables -t nat -I PREROUTING 1 -p udp -s 192.168.255.0/24 --dport 53 -j DNAT --to-destination 127.0.0.11:53
iptables -t nat -I PREROUTING 1 -p tcp -s 192.168.255.0/24 --dport 53 -j DNAT --to-destination 127.0.0.11:53
其中 192.168.255.0/24 是我的 VPN 网络。
这是完整的 iptables 列表:
bash-4.3# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 192.168.255.0/24 anywhere tcp dpt:domain to:127.0.0.11:53
DNAT udp -- 192.168.255.0/24 anywhere udp dpt:domain to:127.0.0.11:53
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER_OUTPUT all -- anywhere 127.0.0.11
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
DOCKER_POSTROUTING all -- anywhere 127.0.0.11
MASQUERADE all -- 192.168.255.0/24 anywhere
Chain DOCKER_OUTPUT (1 references)
target prot opt source destination
DNAT tcp -- anywhere 127.0.0.11 tcp dpt:domain to:127.0.0.11:36429
DNAT udp -- anywhere 127.0.0.11 udp dpt:domain to:127.0.0.11:33172
Chain DOCKER_POSTROUTING (1 references)
target prot opt source destination
SNAT tcp -- 127.0.0.11 anywhere tcp spt:36429 to::53
SNAT udp -- 127.0.0.11 anywhere udp spt:33172 to::53
除上述两个规则外,所有规则均由 docker 自动创建。我做错了什么?
答案1
docker 内嵌 DNS 的目标端口每次启动时都会改变(to:127.0.0.11:36429
)。尝试将传入流量分派到DOCKER_OUTPUT
规则:
iptables -t nat -A PREROUTING -p udp --dport 53 -j DOCKER_OUTPUT
iptables -t nat -A PREROUTING -p tcp --dport 53 -j DOCKER_OUTPUT
要将响应转发给原始请求者,请将伪装规则添加到任何源自您之外的包localhost
:
iptables -t nat -A POSTROUTING ! -s 127.0.0.1 -p udp --dport 53 -j MASQUERADE
iptables -t nat -A POSTROUTING ! -s 127.0.0.1 -p tcp --dport 53 -j MASQUERADE