我甚至不确定这是否是正确的措辞,我会尽力解释。
我想设置一个小型 VPN,用于托管一些私人项目以及访问互联网。我还想拥有自己的 DNS 服务器,以便拥有很酷的顶级域名。
我的设置看起来怎么样
我正在使用两个 Docker 镜像:
- ubuntu/bind9 用于 DNS
- donaldzou/wgdashboard (https://github.com/donaldzou/WGDashboard) 用于 Wireguard 和 GUI 仪表板
我的 wireguard 接口有名称main
并在端口上运行20000
。请注意,因为这些不是“默认”设置。
现在,它几乎可以正常工作,这意味着我可以将多个对等点连接到此“服务器”对等点。我可以从另一个对等点 ping 任何对等点。因此,设置的“wireguard”部分可以正常工作。我相信这是一个超出 wireguard 范围的路由问题。
以下是我的docker-compose.yml
文件的相关部分:
services:
dns:
image: ubuntu/bind9
restart: unless-stopped
networks:
main:
ipv4_address: 172.16.0.53
wgdashboard:
image: donaldzou/wgdashboard
cap_add:
- NET_ADMIN
- SYS_MODULE
networks:
main:
ipv4_address: 172.16.0.2
ports:
- 10086:10086
- 20000:20000/udp
networks:
main:
ipam:
driver: default
config:
- subnet: 172.16.0.0/16
ip_range: 172.16.0.0/24
gateway: 172.16.0.1
网络已创建,并且两个容器都有正确的 IP
因此,由于我的设置在 UDP 端口 20000 上运行,而不是在网络上运行host
,因此我在 iptables 中有一些规则。我对这部分非常不确定。
# iptables -L | grep 20000
ACCEPT udp -- anywhere 172.16.0.2 udp dpt:20000
ACCEPT udp -- anywhere anywhere udp dpt:20000
# iptables -t nat -L | grep 20000
MASQUERADE udp -- 172.16.0.2 172.16.0.2 udp dpt:20000
DNAT udp -- anywhere anywhere udp dpt:20000 to:172.16.0.2:20000
我还看到有些人请求此网络信息,因此我将其发布在这里:
$ ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
ens3 UP 52:54:00:0c:f3:c5 <BROADCAST,MULTICAST,UP,LOWER_UP>
docker0 DOWN 02:42:61:07:a5:d4 <NO-CARRIER,BROADCAST,MULTICAST,UP>
br-e12a65bf943c UP 02:42:5b:d4:1a:a6 <BROADCAST,MULTICAST,UP,LOWER_UP>
$ ip -br address
lo UNKNOWN 127.0.0.1/8 ::1/128
ens3 UP XX.YY.ZZ.24/24
docker0 DOWN 172.17.0.1/16
br-e12a65bf943c UP 172.16.0.1/16
$ ip route
default via XX.YY.ZZ.1 dev ens3 onlink
XX.YY.ZZ.0/24 dev ens3 proto kernel scope link src XX.YY.ZZ.24
172.16.0.0/16 dev br-e12a65bf943c proto kernel scope link src 172.16.0.1
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
$ ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
$
怎么了
我可以从运行docker的服务器ping和查询
172.16.0.53
(“dns”容器)我可以
172.16.0.53
从“wgdashboard”容器ping 和查询1.1.1.1
我可以从服务器和两个容器进行ping 和查询我可以
http://172.16.0.2:10086/
从所有连接的对等点在浏览器中 ping 并打开(“wgdashboard”)容器我无法从任何一方 ping 通外部世界
我无法
172.16.0.53
从任何一方ping 或发出 DNS 查询
我正在尝试解决此问题:
端口映射
首先,我在docker-compose.yml中53:53/udp
为服务添加了端口映射( ):dns
$ docker-compose up
[+] Running 3/3
⠿ Network apps_main Created 0.1s
⠿ Container apps-dns-1 Created 0.1s
⠿ Container apps-wgdashboard-1 Created 0.1s
Attaching to apps-dns-1, apps-wgdashboard-1
Error response from daemon: driver failed programming external connectivity on endpoint apps-dns-1 (4d28f6ed5232a08b266aed9fd232bc9894b7ae0990d25129b27d4f4112ef289f): Error starting userland proxy: listen udp4 0.0.0.0:53: bind: address already in use
呃,什么,它会尝试绑定到主机的端口 53 吗?无论如何,我都不需要这个,因为我只打算从 wireguard(因此也是 docker)网络内部查询此服务器,而不需要从外部查询?
tcpdump
我从四个位置运行了 tcpdump:
- 主机,接口
br-e12a65bf943c
(docker-compose 网络),tcpdump -i br-e12a65bf943c icmp
- 主机、接口
ens3
(实际互联网)、tcpdump -i ens3 icmp
- wireguard 容器,接口
main
(类似 wg0,但我给了它不同的名字),tcpdump -i main icmp
- bind9 容器,接口
eth0
(它是唯一的一个)
按时间顺序从连接的对等点pingdns
容器(我不知道这些时区是怎么回事,忽略小时):
[wireguard,main] 16:18:22.021439 IP 10.0.0.2 > 172.16.0.53: ICMP echo request
[host,br-e12a65bf943c]17:18:22.021500 IP 10.0.0.2 > 172.16.0.53: ICMP echo request
[dns,eth0] 14:18:22.021508 IP 10.0.0.2 > 172.16.0.53: ICMP echo request
[dns,eth0] 14:18:22.021567 IP 172.16.0.53 > 10.0.0.2: ICMP echo reply
[host,br-e12a65bf943c]17:18:22.021575 IP 172.16.0.53 > 10.0.0.2: ICMP echo reply
[host,ens3] 17:18:22.021584 IP 172.16.0.53 > 10.0.0.2: ICMP echo reply
要点:三次请求,三次回复,但有一个回复决定通过,ens3
而不是返回到 wireguard
正在 Ping 1.1.1.1
[wireguard,main] 16:30:16.689460 IP 10.0.0.2 > 1.1.1.1: ICMP echo request
[host,br-e12a65bf943c]17:30:16.689570 IP 10.0.0.2 > 1.1.1.1: ICMP echo request
主机,ens3
什么都没有(!!!)
结论:我无法从 10.0.0.0/16 网络 ping 外部网络
所以我有三个问题
- ICMP 回复发生了什么
br-e12a65bf943c
?如何让它返回到 wireguard 接口? - ICMP 请求在发往 1.1.1.1 的途中发生了什么?
- 是 iptables 吗
如果你已经读到这里,谢谢你的时间
我猜是解决方案?
谢谢您的回答!您说得对,我忘了提到网络掩码,在本例中我选择了 /16。
dns
确实,在容器上添加此路由可以修复 ping 问题
ip route add 10.0.0.0/16 via 172.16.0.2
现在我的任务是使其“永久”,我想我需要将其添加到dockerfile或其他地方。
第二个问题是外部交通。
我将此规则添加到wireguard
容器中:
iptables -t nat -A POSTROUTING -s 10.0.0.0/16 -o eth0 -j MASQUERADE
是的,看起来它起作用了
答案1
首先,你应该有一个路线10.0.0.0/24
(嗯,/24
因为没有提供所以假设)在 DNS 容器上,作为172.16.0.2
下一跳(又名网关)。或者,你需要 (S)NAT(又称 IP 伪装)里面WG 容器(至少用于发往172.16.0.53:53
UDP 以及可能的 TCP 的流量)。
至于到互联网的流量(例如1.1.1.1
),可能是因为docker守护进程在docker主机上添加的防火墙规则不允许源地址不是172.16.0.0/16
(subnet:
)的流量从转发出去br-e12a65bf943c
。同样,其中一个选项是(S)NAT里面源地址为 的流量的 WG 容器10.0.0.0/24
。
另一种选择是通过某种方式禁用相应的过滤,例如完全阻止 docker 守护进程接触防火墙(--iptables=false
),或者在 docker 守护进程启动后添加例外。
10.0.0.0/24
如果您决定不在 WG 容器内添加额外的 NAT 层,我不太确定是否需要在 docker 主机上专门添加 (S)NAT 规则。您可以检查 docker 主机上的iptables-save
当前SNAT
/MASQUERADE
规则是否仅限于172.16.0.0/16
来自 的流量的源地址br-e12a65bf943c
。此外,根据这一决定,您还需要在 docker 主机上添加路由10.0.0.0/24
(以172.16.0.2
作为下一跳)。