我正在设置 Wireguard 配置,其中有以下实体:
谷歌云或亚马逊 AWS 等主机上的远程 VM 实例。这是我的 wireguard 服务器的远程客户端。我们称之为
gcp_client
我的 LAN 上托管的机器上的 wireguard 服务器。我们称之为
srvlan
。
- 此设备上的 IPv4 转发已通过 启用
sysctl
。 - WAN 和 LAN 之间有一台 Ubiquiti Edgerouter 4。我已在此设备上启用端口转发和发夹 NAT。我还在此路由器上设置了动态 DNS。
- 我的 LAN 上有一个或多个客户端,它们应该能够连接到远程客户端,就像它是我 LAN 上的一台机器一样。由于我的第一个客户端本身就遇到了问题,所以我们称之为
client1
。
在我的设置中,我能够在srvlan
和gcp_client
之间双向 ping,在client1
和之间srvlan
也能 ping。但是,从gcp_client
到ping client1
(反之亦然)失败。
根据阅读的结果tcpdump -i wg0 -n icmp
,我做出了以下观察:
- 从
client1
到 的ping 操作可以gcp_client
到达srvlan
,但不会转发到路由器。 gcp_client
从到 的ping 命令client1
到达我的路由器,路由器将它们转发到srvlan
。但是数据包并没有被转发srvlan
到client1
。
我能得出的唯一结论是,上的转发规则srvlan
存在某种问题。我正在使用它nftables
来管理此设备。
这是我的 wireguard 配置;ip 地址和端口号已更改。
# wg0.conf for gcp_client
[Interface]
Address = 10.0.1.2/24
ListenPort = 50000
PrivateKey = gcp_client_privkey
[Peer]
PublicKey = srvlan_pubkey
AllowedIPs = 10.0.1.0/24
Endpoint = srvlan_ddns:50000
# wg0.conf for srvlan
[Interface]
Address = 10.0.1.1/24
ListenPort = 50000
PrivateKey = srvlan_privkey
[Peer]
PublicKey = gcp_client_pubkey
AllowedIPs = 10.0.1.2/32
Endpoint = gcp_client_domainname:50000
PersistentKeepalive = 25
[Peer]
PublicKey = client1_pubkey
AllowedIPs = 10.0.1.3/32
Endpoint = client1_lanhostname:50000
PersistentKeepalive = 25 # I realise this one is unnecessary, but I had added it while testing just in case the problem got fixed.
# wg0.conf for client1
[Interface]
Address = 10.0.1.3/24
ListenPort = 50000
PrivateKey = client1_privkey
[Peer]
PublicKey = srvlan_pubkey
AllowedIPs = 10.0.1.0/24
Endpoint = srvlan_lanhostname:50000
这是我的防火墙srvlan
。
# nft list ruleset
table inet firewall {
chain inbound {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif "lo" accept
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
ip protocol igmp accept
tcp dport 22 accept
iifname "eno1" tcp dport { 80, 443 } ct state new accept
iifname "eno1" udp dport 50000 ct state new accept
iifname "wg0" udp dport 53 ct state new accept
iifname "wg0" tcp dport { 80, 443 } ct state new accept
iifname "wg0" udp dport 50000 ct state new accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iifname "wg0" oifname "eno1" ct state new accept
}
chain outbound {
type filter hook output priority filter; policy accept;
ct state invalid drop
}
}
table ip router {
chain prerouting {
type nat hook prerouting priority filter; policy accept;
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "eno1" ip saddr 10.0.1.0/24 masquerade
}
}
答案1
什么时候服务端转发 WireGuard 隧道流量,它从WG0并将其路由至...WG0再次:两次相同的界面。
因此您需要将此条目附加到inet 防火墙转发链式nftables:
iifname "wg0" oifname "wg0" accept
其他连锁问题入站:
ip protocol icmp accept ip6 nexthdr ipv6-icmp accept ip protocol igmp accept
尽管协议适用于 IPv4,下一个在协议 IPv6 中,不保证下一个报头是 ICMPv6:可以有多个扩展头在固定报头和上层协议报头之间。如果某些数据包中出现此类扩展报头,则将nexthdr ipv6-icmp
不再匹配。对于 IPv4 和 IPv6,请使用正确的语法:
meta nfproto ipv4 meta l4proto icmp accept
meta nfproto ipv6 meta l4proto ipv6-icmp accept
meta nfproto ipv4 meta l4proto igmp accept
取决于nftables版本,它将以更简化的形式显示回来。
iifname "wg0" udp dport 50000 ct state new accept
端口 50000 不会出现在 WireGuard 接口内(除非您想在 WireGuard 内建立 WireGuard 隧道),而是出现在接口外(已经有规则)。它应该不需要。
请记住,当你添加更多 WireGuard 客户端/对等端时(正如你正确所做的那样),不能有重叠服务端的允许IP条目,因为它们决定了 WireGuard 中发生的加密路由,以便在标准路由之后选择适当的对等体。此外,如果gcp_客户端通过连接服务端对于不使用 WireGuard 隧道的服务器,还必须将其 LAN 地址添加到允许IP以及路由表gcp_客户端。允许IP用于根据数据包的来源接受数据包(并确定哪个对等点并可能在漫游的情况下更新其端点),并根据数据包的目的地确定向哪个对等点发送数据包。