前言

之前用树莓派在家里面建立了一个内网DNS服务器,现在想要用这个树莓派做一个controller 做更多的事情。

想了想,WireGurad挺适合的,于是有了这篇文章。

但是后续发现,无论是ipv4 还是 ipv6 都无法从外界单方面连通路由器内网,也许是因为路由器的规则:

  1. ipv4并不是传统意义的外网,而是CGNAT

  2. ipv6可能是我没有找到正确的位置,ipv6的控制已经制定了规则,也无法连通

所以这篇也就当作一个小记录吧,也算是无敌小白版吧,但就是没有成功的无敌小白版(笑)。

正文

1. 配置 路由器规则

打开 我们的路由器内网管理页面,配置:

路由器端口转发

名称

wireguard

协议

UDP

广域网主机起始IP地址

广域网主机结束IP地址

广域网连接

2_INTERNET_R_VID_100

广域网起始端口

51820

广域网结束端口

51820

启用MAC映射

虚拟主机IP地址

192.168.1.50

虚拟主机端口

51820

2. 树莓派上配置 WireGuard

2.1 安装WireGuard

# wireguard
sudo apt update
sudo apt install wireguard -y

# 我们后续wg0.conf 会用到
sudo apt update
sudo apt install -y iptables

2.2 生成服务器密钥

在树莓派上执行:

wg genkey | tee server_private.key | wg pubkey > server_public.key

2.3 配置 WireGuard(树莓派)

编辑配置文件:

sudo vim /etc/wireguard/wg0.conf

填入,这里privatekey,是我们的server_private.key 的私钥:

[Interface]
Address = 10.6.0.1/24
ListenPort = 51820
PrivateKey = <这里粘贴你的 server_private.key 私钥>

PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

2.4 开启内核转发

sudo vim /etc/sysctl.conf

取消注释:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

应用:

sudo sysctl -p

2.5 启动 WireGuard

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

检查状态:

# WireGuard 接口与监听端口
sudo wg show
sudo ss -ulpn | grep 51820

# 转发是否开启(应该是 1)
sudo sysctl -n net.ipv4.ip_forward

若监听里看到 51820,且 ip_forward=1,一切就绪。

3. 给客户端 配置WireGuard

3.1 在树莓派上生成客户端密钥对

wg genkey | tee client1_private.key | wg pubkey > client1_public.key

3.2 把客户端公钥写入服务器配置

[Peer]
# 客户端1(手机)
PublicKey = <这里粘贴你的 client1_public.key 公钥>
AllowedIPs = 10.6.0.2/32 

其中 10.6.0.2/32 为 虚拟内网(VPN内网)

3.3 重启服务

sudo systemctl restart wg-quick@wg0

3.4 准备客户端配置文件(client1.conf)

在树莓派上新建一个文件,比如 /etc/wireguard/client1.conf

[Interface]
PrivateKey = <这里粘贴你的 client1_private.key 私钥>       # 你生成 peer 时得到的私钥
Address = 10.6.0.2/32           # 客户端的隧道 IP
DNS = 192.168.1.50              # 我们的 Pi-hole IP, DNS服务器

[Peer]
PublicKey = <这里粘贴你的 server_public.key 公钥>   # 服务器的公钥
Endpoint = <你的公网IP>:51820   
AllowedIPs = 0.0.0.0/0, ::/0    # 表示全流量走 VPN
PersistentKeepalive = 25

⚠️注意:<客户端私钥>客户端独有 的,你之前生成客户端 key pair 的时候会有。不要用服务器的私钥。

<你的公网IP> 填树莓派所在网络的公网 IP(就是你路由器对外的 IP),或者如果你有 DDNS,就填域名。

3.5 转换为二维码(方便手机导入)

在树莓派上安装二维码工具:

sudo apt install -y qrencode

生成二维码:

sudo qrencode -t ansiutf8 -r /etc/wireguard/client1.conf

终端会直接显示一个二维码,你的手机(WireGuard app → 添加隧道 → 扫描二维码)就能导入了。

4. 无法连通树莓派(ipv4 + ipv6)

一般来说,这样就成功了。

但是我们并不能成功,无论是ipv4 还是 ipv6的连接都无法连通。

4.1 ipv4(CGNAT问题)

我们这里看似是公网,38+,但是其实问题是 运营商又做了一个NAT,然后再帮我们放在公网上面,如果是这样的话,我们对这个公网发送消息,我们是根本不可能收到的:

我们打开路由器的WAN信息就可以看见了:

这个信息一看就确认了:我们现在是 CGNAT,所以端口转发根本不可能成功。

原因:

  • 我们在路由器 WAN 口看到的是 100.xxx.xxx.xxx

  • 这个地址段 100.64.0.0/10(也就是 100.64.0.0100.127.255.255)是 运营商级 NAT(CGNAT)专用地址段

  • 说明你的宽带运营商把你放在了一个共享公网出口后面。你本地是 100.64.x.x,然后再 NAT 出去变成 38.xxx.xxx.xxx,我们在外面看见的公网ip。

所以我们现在的情况是:

树莓派 192.168.1.50 → 家里路由器 NAT → WAN口 100.64.xxx.xxx → 运营商大NAT → 公网 38.xxx.xxx.xxx

这种情况下,

  • 你在路由器上做端口转发只能转到 100.64.xxx.xxx,但这个 IP 根本不对外暴露。

  • 外网访问到的 38.xxx.xxx.xxx 在你家路由器这里根本没有对应关系,所以进不来。

4.2 ipv6(未知原因)

ipv6具体原因不清楚,有可能是我路由没有设置对,但是结果就是给树莓派的ipv6地址直接通讯,也没有办法收到包。很奇怪。

有大佬们知道的,请务必求告知!

5. 后续方向

zerotier

总结

东西是好东西,但是怎么就没有办法成功呢?

参考

[1] ChatGPT
[2] 自己
[3] zerotier

立志做一个有趣的碳水化合物。