如何在 Wireguard 客户端上将 Pi-hole 设置为我的 DNS 服务器

如何在 Wireguard 客户端上将 Pi-hole 设置为我的 DNS 服务器

我正在尝试在远程 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 不起作用的原因(因为它显然是直接在容器主机上配置的;换句话说,它不是一个发夹问题之类的)。

相关内容