通过 WireGuard Hub 和 Spoke VPS(Nftables)路由所有流量

通过 WireGuard Hub 和 Spoke VPS(Nftables)路由所有流量

正如标题所述,我正在使用 WireGuard Hub 和 Spoke 配置将我家里的网络连接到 RoadWarrior 对等点。不幸的是,我在家里和路上都没有公共 IPv4 和 v6 地址,所以我需要集线器。到目前为止,私有 IP 地址的路由有效,但我想将 VPS(HUB 和主机 B)也用作正常流量的出口点,因为我有时在路上带着手机在不安全的网络中。因此,在我的主机 A(智能手机)上,我将允许的 IP 设置为 0.0.0.0/0,但不幸的是这没有通过。我怀疑 VPS(HUB 和主机 B)上缺少路由规则。下面是我对整个事情的看法。

RoadWarrior (Host A)   <--->   VPS HUB (Host B)   <---->  Home-net (Host C)
                                    |
                                    |
                                 Internet 

以下是我在 VPS 上的 WireGuard 配置:

# /etc/wireguard/wg0.conf

[Interface]
Address = 10.210.1.1/16
ListenPort = 51828
PrivateKey = 

PreUp = sysctl -w net.ipv4.ip_forward=1
PreUp = sysctl -w net.ipv6.conf.all.forwarding=1
PreUp = nft -f /etc/nftables.wg

PostDown = nft -f /etc/nftables.conf
PostDown = sysctl -w net.ipv4.ip_forward=0
PostDown = sysctl -w net.ipv6.conf.all.forwarding=0

# Home-net (Host C)

[Peer]
PublicKey = 
PresharedKey = 
AllowedIPs = 10.211.1.1/24, 10.1.0.0/16, 10.2.0.0/16


#Road-Warrior Peers (Host A)

[Peer]
PublicKey = 
PresharedKey = 
AllowedIPs = 10.212.1.1/32

WireGuard 运行时我的 nftables 配置:

#!/usr/sbin/nft -f

flush ruleset

define pub_iface = eth0
define wg_iface = wg0
define wg_port = 51828

table inet basic-filter {
        chain input {
                type filter hook input priority 0; policy drop;
                ct state { established, related } accept
                iif lo accept
                ip protocol icmp accept
                ip6 nexthdr ipv6-icmp accept
                ct state new tcp dport 51829 log prefix "Neue SSH-Verbindung" accept
                iif $pub_iface udp dport $wg_port accept
                iifname $wg_iface accept
                reject
        }
        chain forward {
                type filter hook forward priority 0; policy drop;
                iifname $wg_iface oifname $wg_iface accept
                reject with icmpx type host-unreachable
        }
        chain output {
                type filter hook output priority 0; policy accept;
        }
}

当 WireGuard 发生故障时,我的 WireGuard 配置如下:

#!/usr/sbin/nft -f

flush ruleset

table inet basic-filter {
        chain input {
                type filter hook input priority 0; policy drop;
                ct state { established, related } accept
                iif lo accept
                ip protocol icmp accept
                ip6 nexthdr ipv6-icmp accept
                ct state new tcp dport 51829 log prefix "Neue SSH-Verbindung " accept
                reject
        }
}

也许您还可以查看我的 nftables 配置,因为它对我来说相对较新:) 谢谢:)

答案1

没有提供路线(ip route...),但我假设主机的 B 路线已由系统和正确配置wg-quick

由于 WG IP 地址不公开,因此在通过链接接入互联网时必须进行 NAT 处理后布线. 添加此块,仍在table inet basic-filter块内:

        chain natpostrouting {
                type nat hook postrouting priority 100; policy accept;
                iifname $wg_iface oifname $pub_iface masquerade
        }

如果 VPS 的内核太旧(早于内核 5.5) 输入接口名称表达式必须替换为源地址表达式,这取决于精确的设置。例如,代替上面的:

        chain natpostrouting {
                type nat hook postrouting priority 100; policy accept;
                ip saddr 10.0.0.0/8 oifname $pub_iface masquerade
        }

现在,nftables缺少允许(上述)与 Internet 的流量的转发规则。在正向链中的reject语句规则之前插入以下两个规则。第二条规则允许从 WG 转发到 Internet,第一条规则允许流量以有状态的通用方式返回,就像在输入链。

                ct state { established,related } accept
                iifname $wg_iface oifname $pub_iface accept

还有一些其他的小细节。

  • 不需要安装和删除不同的nftables隧道上行或下行时的规则集

    但这取决于你自己的方便。

  • 拒绝可能被归类为无效的接收延迟数据包时可能导致 TCP 连接意外中止

    因此,在拒绝它们之前,请先删除它们。在最终reject语句规则之前的任何位置插入此规则,一次在链中input,一次在forward链中:

                    ct state invalid drop
    

    A可能的未来补丁可能会不再需要这个。

  • IPv6下一个并不直接等同于 IPv4 的协议

    因为可能存在扩展头固定头和上层协议头之间。

    互联网上的很多文档都有这个错误。

    因此几乎永远不应该使用它(因为在意图匹配的情况下它可能无法匹配):

    ip6 nexthdr ipv6-icmp accept
    

    并被系统已知的元信息替换,因为它正确地解析了所有的包:

    meta nfproto ipv6 meta l4proto ipv6-icmp accept
    

    或者简单来说:

    meta l4proto ipv6-icmp accept
    

相关内容