我正在尝试在远程 Debian 服务器上设置 Wireguard VPN,并在同一服务器上使用 Pi-hole。我将它们都安装为 Docker 容器。对于 Wireguard,我使用了wg-easy对于 Pi-hole,我使用了docker-pi-hole存储库。
我使用以下命令来配置防火墙,使用此处的说明网站。
# Clear out the entire firewall
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -t nat -F
ip6tables -t mangle -F
ip6tables -F
ip6tables -X
iptables-legacy -P INPUT ACCEPT
iptables-legacy -P FORWARD ACCEPT
iptables-legacy -P OUTPUT ACCEPT
iptables-legacy -t nat -F
iptables-legacy -t mangle -F
iptables-legacy -F
iptables-legacy -X
# Add rules for IPv4
iptables -A INPUT -i wg0 -p tcp --destination-port 53 -j ACCEPT
iptables -A INPUT -i wg0 -p udp --destination-port 53 -j ACCEPT
iptables -A INPUT -i wg0 -p tcp --destination-port 80 -j ACCEPT
iptables -A INPUT -p tcp --destination-port 22 -j ACCEPT
iptables -A INPUT -p tcp --destination-port 51821 -j ACCEPT
iptables -A INPUT -p udp --destination-port 51820 -j ACCEPT
iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT -i lo -j ACCEPT
iptables -A INPUT -p udp --dport 80 -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p udp --dport 443 -j REJECT --reject-with icmp-port-unreachable
iptables -P INPUT DROP
# Add rules for IPv6
ip6tables -A INPUT -i wg0 -p tcp --destination-port 53 -j ACCEPT
ip6tables -A INPUT -i wg0 -p udp --destination-port 53 -j ACCEPT
ip6tables -A INPUT -i wg0 -p tcp --destination-port 80 -j ACCEPT
ip6tables -A INPUT -p tcp --destination-port 22 -j ACCEPT
ip6tables -A INPUT -p tcp --destination-port 51821 -j ACCEPT
ip6tables -A INPUT -p udp --destination-port 51820 -j ACCEPT
ip6tables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -I INPUT -i lo -j ACCEPT
ip6tables -A INPUT -p udp --dport 80 -j REJECT --reject-with icmp6-port-unreachable
ip6tables -A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
ip6tables -A INPUT -p udp --dport 443 -j REJECT --reject-with icmp6-port-unreachable
ip6tables -P INPUT DROP
# Restart Docker in order to re-create the Docker iptables rules
service docker restart
的输出iptables -L --line-numbers && ip6tables -L --line-numbers
是:
# Warning: iptables-legacy tables present, use iptables-legacy to see them
Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere
2 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
3 ACCEPT tcp -- anywhere anywhere tcp dpt:domain
4 ACCEPT udp -- anywhere anywhere udp dpt:domain
5 ACCEPT tcp -- anywhere anywhere tcp dpt:http
6 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
7 ACCEPT tcp -- anywhere anywhere tcp dpt:51821
8 ACCEPT udp -- anywhere anywhere udp dpt:51820
9 REJECT udp -- anywhere anywhere udp dpt:80 reject-with icmp-port-unreachable
10 REJECT tcp -- anywhere anywhere tcp dpt:https reject-with tcp-reset
11 REJECT udp -- anywhere anywhere udp dpt:https reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 DOCKER-USER all -- anywhere anywhere
2 DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
3 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
4 DOCKER all -- anywhere anywhere
5 ACCEPT all -- anywhere anywhere
6 ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Chain DOCKER (1 references)
num target prot opt source destination
1 ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:51821
2 ACCEPT udp -- anywhere 172.17.0.2 udp dpt:51820
3 ACCEPT tcp -- anywhere 172.17.0.3 tcp dpt:http
4 ACCEPT tcp -- anywhere 172.17.0.3 tcp dpt:domain
5 ACCEPT udp -- anywhere 172.17.0.3 udp dpt:domain
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
num target prot opt source destination
1 DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
2 RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
num target prot opt source destination
1 DROP all -- anywhere anywhere
2 RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
num target prot opt source destination
1 RETURN all -- anywhere anywhere
两个容器都已正确安装,我可以访问它们的 WebUI。我能够使用 Wireguard 连接到手机上的 VPN。正如预期的那样,当我查找我的 IP 时,会显示远程服务器的静态 IP。但是,Wireguard 客户端使用 1.1.1.1 作为 DNS 服务器。我应该怎么做才能使用 Pi-hole 作为我的 DNS 服务器?如果我使用服务器静态 IP 作为客户端上的 DNS 服务器,我将无法访问互联网。
输出ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 56:00:03:e6:2e:b0 brd ff:ff:ff:ff:ff:ff
inet 102.3.4.5/23 brd 102.3.4.255 scope global dynamic enp1s0
valid_lft 58212sec preferred_lft 58212sec
inet6 fe80::5400:3ff:fee6:2eb0/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:b9:8f:2e:48 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:b9ff:fe8f:2e48/64 scope link
valid_lft forever preferred_lft forever
87: veth45fdacb@if86: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 4a:1a:46:3d:dc:1c brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::481a:46ff:fe3d:dc1c/64 scope link
valid_lft forever preferred_lft forever
91: veth87dce69@if90: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 42:fb:a1:a8:eb:ff brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::40fb:a1ff:fea8:ebff/64 scope link
valid_lft forever preferred_lft forever
输出iptables-save
# Generated by iptables-save v1.8.7 on Sat Mar 12 16:57:54 2022
*filter
:INPUT DROP [2055:137031]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [4530:715832]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i wg0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i wg0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i wg0 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 51821 -j ACCEPT
-A INPUT -p udp -m udp --dport 51820 -j ACCEPT
-A INPUT -p udp -m udp --dport 80 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -m tcp --dport 443 -j REJECT --reject-with tcp-reset
-A INPUT -p udp -m udp --dport 443 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 51821 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p udp -m udp --dport 51820 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 53 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p udp -m udp --dport 53 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sat Mar 12 16:57:54 2022
# Generated by iptables-save v1.8.7 on Sat Mar 12 16:57:54 2022
*nat
:PREROUTING ACCEPT [4049:393443]
:INPUT ACCEPT [129:8227]
:OUTPUT ACCEPT [165:11159]
:POSTROUTING ACCEPT [1177:81133]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 51821 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p udp -m udp --dport 51820 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 53 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p udp -m udp --dport 53 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 51821 -j DNAT --to-destination 172.17.0.2:51821
-A DOCKER ! -i docker0 -p udp -m udp --dport 51820 -j DNAT --to-destination 172.17.0.2:51820
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.3:80
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 53 -j DNAT --to-destination 172.17.0.3:53
-A DOCKER ! -i docker0 -p udp -m udp --dport 53 -j DNAT --to-destination 172.17.0.3:53
COMMIT
# Completed on Sat Mar 12 16:57:54 2022
# Warning: iptables-legacy tables present, use iptables-legacy-save to see them
谢谢Tom Yan 的回答我能够使用以下脚本正确配置 Pi-hole 和 Wireguard:
Wireguard
docker run -d \
--name=wg-easy \
-e WG_HOST=my-server-static-ip \
-e PASSWORD=my-password \
-e WG_DEFAULT_DNS=172.17.0.3 \
-v ~/.wg-easy:/etc/wireguard \
-p 51820:51820/udp \
-p 51821:51821/tcp \
--ip 172.17.0.2 \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
--sysctl="net.ipv4.ip_forward=1" \
--restart unless-stopped \
weejewel/wg-easy
Pi孔
#!/bin/bash
# https://github.com/pi-hole/docker-pi-hole/blob/master/README.md
PIHOLE_BASE="${PIHOLE_BASE:-$(pwd)}"
[[ -d "$PIHOLE_BASE" ]] || mkdir -p "$PIHOLE_BASE" || { echo "Couldn't create storage directory: $PIHOLE_BASE"; exit 1; }
# Note: ServerIP should be replaced with your external ip.
docker run -d \
--name pihole \
-p 53:53/tcp -p 53:53/udp \
-p :80:80 \
-e TZ="Europe/Paris" \
-e WEBPASSWORD="my-password" \
-v "${PIHOLE_BASE}/etc-pihole:/etc/pihole" \
-v "${PIHOLE_BASE}/etc-dnsmasq.d:/etc/dnsmasq.d" \
--dns=127.0.0.1 --dns=1.1.1.1 \
--restart=unless-stopped \
--hostname pi.hole \
--ip 172.17.0.3 \
-e VIRTUAL_HOST="pi.hole" \
-e PROXY_LOCATION="pi.hole" \
-e ServerIP="my-server-static-ip" \
pihole/pihole:latest
printf 'Starting up pihole container '
for i in $(seq 1 20); do
if [ "$(docker inspect -f "{{.State.Health.Status}}" pihole)" == "healthy" ] ; then
printf ' OK'
echo -e "\n$(docker logs pihole 2> /dev/null | grep 'password:') for your pi-hole: https://${IP}/admin/"
exit 0
else
sleep 3
printf '.'
fi
if [ $i -eq 20 ] ; then
echo -e "\nTimed out waiting for Pi-hole start, consult your container logs for more info (\`docker logs pihole\`)"
exit 1
fi
done;
答案1
您应该能够使用172.17.0.3
(即分配给 Pi-Hole 容器的 IP)作为 Wireguard 客户端上的 DNS 服务器,因为您的 Wireguard 容器和 Pi-Hole 容器连接到同一个网桥。因为源 NAT 已在 Wireguard 容器内设置,它应该可以开箱即用。
请注意,分配给 docker 容器的 IP 显然是默认枚举的,因此除非你能保证容器总是以相同的顺序启动(例如,它们按以下顺序启动):同步使用脚本或有序--ip
由于 systemd 服务的存在,分配给容器的 IP 可能会在下次启动时交换。因此,最好使用 选项静态设置它们的 IP docker run
。
PS 有人可能会认为172.17.0.1
,可以使用 来代替,这应该可以让你免于我刚才提到的枚举 IP 问题。但是,正如你从转储中看到的那样iptables-save
,出于某些原因,docker 默认情况下不会让主机根据映射/转发的端口将流量从 docker 网桥重定向到相应的 docker 容器:
...
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
...
-A DOCKER -i docker0 -j RETURN
...
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 53 -j DNAT --to-destination 172.17.0.3:53
-A DOCKER ! -i docker0 -p udp -m udp --dport 53 -j DNAT --to-destination 172.17.0.3:53
...
因此你需要添加额外的 DNAT 规则手动如果您改用172.17.0.1
,规则将要求指定相应的容器 IP,如您所见。换句话说,这种方法实际上无济于事,更不用说它在当前设置下无论如何都很糟糕。
这也是为什么使用公共 IP 不起作用的原因(因为它显然是直接在容器主机上配置的;换句话说,它不是一个发夹问题之类的)。