使用 Wireguard 从本质上为本地网络中的计算机提供来自 VPS 的公共地址

Joh*_*Dow 6 networking vpn routing iptables wireguard

我正在做家庭项目,并且想为我的机器提供分配给我在云中的 VPS 的公共 IP 地址。

在家里,我有一个公共 IP 地址,并且已经设置了 Wireguard 服务器,外部端口 1194 被转发到该计算机,因此来自互联网的 WG 客户端可以连接到它。

现在,我在云中有一个带有静态公共IP地址的VPS(假设有一个IP 44.44.44.44),而且我在本地网络中有一台机器(假设有一个IP 192.168.1.3),我希望本地网络中的机器将流量处理为它实际上拥有44.44.44.44云中 VPS 的公共 IP( )。这意味着到达 VPS 的所有传入流量都将路由到192.168.1.3本地网络中的计算机 ( )。

我使用 Wireguard 连接 WG 服务器和 VPS 没有任何问题,甚至通过 WG 服务器重定向来自 VPS 的所有流量(使用 iptables NAT 规则),但我陷入了路由来自 VPS 的传入流量保留原始流量的部分本地网络中机器的 IP 地址。

我的客户端(VPS)WG配置:

[Interface]
PrivateKey = dGhpcyBpcyBub3QgdGhlIGtleSA7KQ==
Address = 10.66.66.2/24
#This was part of the test usin
#PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;
#PostDown = iptables -D FORWARD -i wg0 -j ACCEPTl iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = dGhpcyBpcyBub3QgdGhlIGtleSBlYXRoZXIgOyk=
Endpoint = 33.33.33.123:1194
AllowedIPs = 10.66.66.1/32
Run Code Online (Sandbox Code Playgroud)

我的服务器(WG)配置:

[Interface]
Address = 10.66.66.1/24
ListenPort = 1194
PrivateKey = dGhpcyBpcyBub3QgdGhlIGtleSA7KQ==
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = dGhpcyBpcyBub3QgdGhlIGtleSBlYXRoZXIgOyk=
AllowedIPs = 10.66.66.2/32

Run Code Online (Sandbox Code Playgroud)

我的理解是否正确,最好的做法是将机器 ( 192.168.1.3) 连接到 WG 服务器(假设使用 IP 10.66.66.3),然后在 VPS 上创建到 的静态eth0路由10.66.66.3

这是网络的简单绘图以及我想要实现的目标: 在此输入图像描述

A.B*_*A.B 10

推介会

这是一个需要服务器本身最少支持的答案,但需要在 WireGuard 服务器上(尤其是 VPS 上)进行多次路由调整。我选择保留 OP 的设置,包括保留 VPS 和 WGserver 之间的 WireGuard 隧道。

此答案中不会涉及将配置正确集成到正在使用的特定发行版(但给出了提示)。

ipproto/dport/sport 策略路由功能需要内核>=4.17,允许在不需要iptables和/或标记的情况下执行异常。

扩展 fib 规则匹配支持以包括 sport、dport 和 ip proto 匹配(以完成 5 元组匹配支持)。数据中心中基于策略的路由的常见用例需要 5 元组匹配

此设置不使用iptables或 NAT:服务器的 44.44.44.44 地址将通过隧道和(可以说尽管如此)VPS 的 44.44.44.44 地址双向路由。人们可以想象,即使服务器使用的 IPsec ESP 数据包也能通过此隧道正常工作(未测试)。它主要依赖于ip route add table XXX ...策略路由( )选择的附加路由表(ip rule add ... lookup XXX)。

需要牢记的一些注意事项:

  • VPS 和路由器的地址不得动态更改,因为有多个规则依赖于它们。这意味着 WireGuard 的自动漫游功能在这里不起作用,因为所需的ip rule条目引用特定的 IP 地址,并且也必须更改。如果 VPS 发生变化但已知位于单个地址块中,则可能会更改 ip 规则和路由以适应路由/网络掩码,而不仅仅是 44.44.44.44。如果它是完全随机的,那么可以让选择器仅检查端口 1194。

  • VPS 自身的连接现在非常有限:它只是变成了一个有限的路由器。除了作为隧道端点之外,只有 SSH 可用,没有其他可用,甚至 DNS 也不可用。应使用可在WGserverserver上或通过 SSH 隧道设置的代理来完成 VPS 的更新。应该对此进行配置,以避免超过需要地使用隧道,但如果不这样做,甚至可以工作(无用地使隧道流量加倍)。

  • 可能需要检查 VPS 自身的防火墙规则。由于它将路由流量,因此如果设置到位,该流量仍然受iptables / nftables的约束,更重要的是要连接跟踪状态规则。conntrack不知道路由,因此会将 44.44.44.44 视为唯一节点。这应该没什么关系,因为本地流量将使用 INPUT/OUTPUT 链,而路由流量将使用 FORWARD 链,并且两者中不会存在相同类型的流量,因为 VPS 现在仅限于隧道和 SSH。因此,我没有在原始表中添加iptables规则来将 conntrack 分成区域或防止跟踪,但这仍然是一个选项

其他选择也是可能的:

  • 应用多层 NAT,但我宁愿尽可能避免 NAT。它也不会透明地实现“我希望本地网络中的机器处理流量,因为它实际上拥有公共 IP”的目标,因为例如 NAT 已知会破坏 IPSec 的本机 ESP 流量,并且需要正确处理确切的同一远程互联网系统与VPS服务器之间的流量相同(可能带有标记和conntrack 区域)。
  • 使用单独的网络命名空间和窃取非隧道数据包(使用tcnftables,可能不是iptables )对VPS提供一些帮助,但这仍然需要大部分调整以及更多。

使用的路由调整的非详尽列表:

  • 在两个隧道端点上:

    • 为两侧的隧道本身添加路由例外,以便它们仍然正常路由
  • 在WG服务器

    • 允许来自 WireGuard 隧道的任何 IP 地址:允许服务器接收整个 Internet 而不仅仅是 10.66.66.2。
    • 不使用 NAT 规则
  • 在VPS上:

    • 除了 10.66.66.1 之外,还允许来自 WireGuard 隧道的 44.44.44.44
    • 将调用本地路由表的规则移至更高的优先级,以便为本地路由表的 例外情况留出空间,从而允许VPS路由属于其自身的 IP 地址。这可能是最重要的改变。
    • 添加 44.44.44.44 的代理 ARP 条目,以使VPS仍然应答其路由器的 ARP 请求,尽管对其进行路由(就像需要任何更常见的代理 ARP 情况一样)
  • 在服务器

    • 服务器可以选择设为多宿主,默认情况下优先通过隧道使用 44.44.44.44(因此不会导致不支持多宿主的 UDP 服务出现问题)。

这个答案必须经过检验。第一次尝试是行不通的。大多数测试是使用tcpdump和完成的ip route get。它没有考虑 WGserver 或 VPS 上使用的当前(和未知)防火墙规则可能产生的干扰。


设置

以下设置按顺序排序,旨在避免每个要配置的系统之间以及要运行的每个单独命令之间的连接丢失。不管怎样,人们应该在VPS上有一个远程控制台访问来解决问题。由于以下命令不会保存(除了wg-quick配置,除非选择wg直接使用),远程重置将恢复对VPS 的访问。

工作组服务器

最初应该是这样配置的:

ip link set dev eth0 up
ip address add 192.168.1.2/24 dev eth0
ip route add default via 192.168.1.1
Run Code Online (Sandbox Code Playgroud)
  • 至少在eth0和未来的接口(如wg0 )上设置为路由器(通常在 中配置/etc/sysctl.{conf,d/}):

    sysctl -w net.ipv4.conf.default.forwarding=1
    sysctl -w net.ipv4.conf.eth0.forwarding=1
    
    Run Code Online (Sandbox Code Playgroud)
  • wg-quick的更改配置:

    [Interface]
    Address = 10.66.66.1/24
    ListenPort = 1194
    PrivateKey = dGhpcyBpcyBub3QgdGhlIGtleSA7KQ==
    Table = off
    PostUp = 
    PostDown = 
    
    [Peer]
    PublicKey = dGhpcyBpcyBub3QgdGhlIGtleSBlYXRoZXIgOyk=
    PersistentKeepalive = 25
    AllowedIPs = 0.0.0.0/0
    
    Run Code Online (Sandbox Code Playgroud)

    不再有 NAT:流量将直接通过隧道路由,无需更改。只需确保防火墙规则允许所需流量通过,并且没有其他通用 NAT 规则即可。Table = off阻止wg-quick配置额外的路由,因为无论如何都会完成自定义路由。由于WGserver位于路由器的NAT后面,PersistentKeepalive因此应该用于刷新路由器的NAT关联表(例如:Linux路由器的conntrack )。

    由于任何 IP 流量都可以通过隧道,AllowedIPs 设置为 0.0.0.0/0,以将任何IP 与对等方关联,以实现 WireGuard 自己的加密密钥路由。

在应用以下设置之前,隧道必须已启动。wg-quick为了集成,人们也许可以创建一个从's PostUp/运行的自定义脚本PostDown,其中包括要遵循的配置。请注意,虽然当接口关闭时路由会消失,但ip rule即使接口被删除,条目也有更多的机会保留下来,因此应该正确清理,以避免以后出现重复和混乱。

  • 保持与 44.44.44.44 隧道本身相关的互联网流量通过路由器双向通过,并防止其受到最后添加在主表中的路由的影响。使用显式首选项,以便命令的顺序无关紧要:

    ip route add table 1000 192.168.1.1/32 dev eth0
    ip route add table 1000 default via 192.168.1.1 dev eth0
    
    ip rule add preference 1000 to 44.44.44.44 iif lo ipproto udp sport 1194 table 1000
    ip rule add preference 1001 from 44.44.44.44 to 192.168.1.2 iif eth0 ipproto udp dport 1194 table 1000
    
    Run Code Online (Sandbox Code Playgroud)
  • 可选:还可以通过路由器将 SSH 路由到隧道之外。如果没有它,WGserver在执行操作时将 ssh 到服务器ssh 44.44.44.44而不是VPS ,但仍然可以使用ssh 到VPSssh 10.66.66.2

    ip rule add preference 1002 to 44.44.44.44 iif lo ipproto tcp dport 22 lookup 1000
    ip rule add preference 1003 from 44.44.44.44 to 192.168.1.2 iif eth0 ipproto tcp sport 22 lookup 1000
    
    Run Code Online (Sandbox Code Playgroud)
  • 有来自服务器的源为 44.44.44.44 的一般流量,通过隧道进行路由。对于不涉及 44.44.44.44 的一般情况, WGserver本身不受影响,仍然使用路由器访问 Internet:

    ip route add table 2000 default dev wg0
    
    ip rule add preference 2000 from 44.44.44.44 iif eth0 lookup 2000
    
    Run Code Online (Sandbox Code Playgroud)

    注意:以前使用的iif eth0是来自router 的流量,而最后一次使用的iif eth0是来自server 的流量。路由规则无法区分使用不同的网关(路由器服务器)到达同一接口(eth0),但这不是问题,因为用于隧道的特定端口足以区分情况。

  • 添加一条路由(标准,使用表)以直接在 LAN 上到达server的 44.44.44.44 的剩余部分(既来自WGserver又用于通过隧道的路由流量):

    ip route add 44.44.44.44/32 dev eth0
    
    Run Code Online (Sandbox Code Playgroud)

    因此,家庭以太网广播域将看到两种本地地址:192.168.1.0/24 和 44.44.44.44/32(例如:ARP 从 192.168.1.2 获得 44.44.44.44)

虚拟专用服务器

假设最初配置如下(使用 44.44.44.1 作为VPS路由器):

ip link set dev eth0 up
ip address add 44.44.44.44/24 dev eth0
ip route add default via 44.44.44.1
Run Code Online (Sandbox Code Playgroud)
  • 设置为路由器:

    sysctl -w net.ipv4.conf.default.forwarding=1
    sysctl -w net.ipv4.conf.eth0.forwarding=1
    
    Run Code Online (Sandbox Code Playgroud)
  • wg-quick的更改配置:

    [Interface]
    PrivateKey = dGhpcyBpcyBub3QgdGhlIGtleSA7KQ==
    Address = 10.66.66.2/24
    Table = off
    PostUp = 
    PostDown = 
    
    [Peer]
    PublicKey = dGhpcyBpcyBub3QgdGhlIGtleSBlYXRoZXIgOyk=
    Endpoint = 33.33.33.123:1194
    PersistentKeepalive = 1000
    AllowedIPs = 10.66.66.1/32,44.44.44.44/32
    
    Run Code Online (Sandbox Code Playgroud)

    PersistentKeepalive这里只是为了确保对等WGserver收到初始握手,然后知道其对等端点(在WGserver上设置端点可能更简单,并且不需要在VPS上设置端点,但 OP 选择以相反的方式进行操作。许多规则取决于端口 1194 及其位置)。否则,如果没有任何初始传入流量,就不可能有任何来自 WGserver 的传出流量,因为它还不知道其端点。44.44.44.44/32 已添加到允许的 IP 列表中,因此它与 WireGuard 的加密密钥路由的对等方关联。

在应用以下设置之前必须先启动隧道(与之前一样,PostUp/PostDown可能用于包含以下设置)。

  • 将本地表规则移至更高位置,为必须绕过本地表的规则腾出空间。

    ip rule add preference 200 lookup local
    ip rule delete preference 0
    
    Run Code Online (Sandbox Code Playgroud)

    现在,优先级低于 200 的所有规则都可以在将相关流量分类为本地流量的规则之前发生:他们将能够防止这种情况发生,并将 44.44.44.44 路由到其他地方,尽管它是本地地址。

  • 隧道例外到稍后推出的例外规则:

    ip rule add preference 100 from 33.33.33.123 to 44.44.44.44 iif eth0 ipproto udp sport 1194 lookup local
    ip rule add preference 101 from 44.44.44.44 to 33.33.33.123 iif lo ipproto udp dport 1194 lookup main
    
    Run Code Online (Sandbox Code Playgroud)
  • 可选的 SSH 例外规则,允许任何互联网源在使用ssh时仍然连接到VPS,而不是服务器。可选,但没有它只能通过隧道进入。如果隧道配置错误,VPS访问就会丢失。

    ip rule add preference 102 to 44.44.44.44 iif eth0 ipproto tcp dport 22 lookup local
    ip rule add preference 103 from 44.44.44.44 iif lo ipproto tcp sport 22 lookup main
    
    Run Code Online (Sandbox Code Playgroud)
  • 添加代理 ARP 条目以保持 VPS 应答 44.44.44.44 的 ARP 请求,该请求现在由VPS路由,而其自己的路由器不知道:

    ip neighbour add proxy 44.44.44.44 dev eth0
    
    Run Code Online (Sandbox Code Playgroud)

    如果没有这个,在下一组规则之后,连接将无法正常工作,因为不再向 VPS 的路由器发出 ARP 应答(实际上,在 VPS 的路由器失败的 ARP 条目超时后,连接会偶尔工作,同时从 VPS 接收流量,但几秒钟后该条目将再次变为 FAILED,直到下一次超时)。

  • 一般情况的例外路由和规则:路由 44.44.44.44 而不是将其视为本地流量(某些路由只是从路由表中复制):

    ip route add table 150 44.44.44.0/24 dev eth0
    ip route add table 150 default via 44.44.44.1 dev eth0
    ip route add table 150 10.66.66.0/24 dev wg0 src 10.66.66.2
    ip route add table 150 44.44.44.44/32 dev wg0 src 10.66.66.2
    
    ip rule add preference 150 to 44.44.44.44 iif eth0 lookup 150
    ip rule add preference 151 from 44.44.44.44 iif wg0 lookup 150
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者,添加两条路由(一条从本地表复制)并在所有其他规则之前插入两条规则,以仍然允许VPS本身从 10.66.66.2 连接到服务器的 44.44.44.44(如果出于某种原因需要)。可能需要避免一些重复,但因为它是可选的......

    ip route add table 50 local 10.66.66.2 dev wg0
    ip route add table 50 44.44.44.44/32 dev wg0
    
    ip rule add preference 50 from 10.66.66.2 iif lo to 44.44.44.44 table 50
    ip rule add preference 51 from 44.44.44.44 iif wg0 to 10.66.66.2 lookup 50
    
    Run Code Online (Sandbox Code Playgroud)

    在VPS上使用来访问服务器的示例(配置后):

    ssh -b 10.66.66.2 44.44.44.44
    
    Run Code Online (Sandbox Code Playgroud)

    从服务器(配置后)访问VPS的使用示例:

    ssh 10.66.66.2
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者,只需使用qdisc 即可保护家庭免受通过VPStc ... netem路由的 DDoS 攻击。它设置在wg0的出口上,而将其设置在eth0的入口上可能会更有效(但更复杂)。

    例如,如果家庭可以通过WGserver的隧道承受约 50mbits/s 的传入带宽(实际上意味着router上有更多带宽):

    tc qdisc add dev wg0 root netem rate 49mbit
    
    Run Code Online (Sandbox Code Playgroud)

服务器

服务器最初应该是这样配置的:

ip link set dev eth0 up
ip address add 192.168.1.3/24 dev eth0
ip route add default via 192.168.1.1
Run Code Online (Sandbox Code Playgroud)

进行了以下更改:

  • 将与 192.168.1.2/32(这只是ip address+ip route命令的快捷方式)直接关联的 44.44.44.44 添加到eth0,使用WGserver作为路由器,优先选择 44.44.44.44 源:

    ip address add 44.44.44.44 peer 192.168.1.2/32 dev eth0
    ip route delete default
    ip route add default via 192.168.1.2 src 44.44.44.44
    
    Run Code Online (Sandbox Code Playgroud)
  • 可以选择完全删除 192.168.1.3 以仅保留 44.44.44.44:

    ip address delete 192.168.1.3/24 dev eth0
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者代替前面的命令,设置多宿主(44.44.44.44 保持默认使用状态):

    ip route add table 192 default via 192.168.1.1 dev eth0
    ip rule add from 192.168.1.3 iif lo lookup 192
    
    Run Code Online (Sandbox Code Playgroud)

    多宿主示例:

    如果服务器本身配置为托管容器或虚拟机的路由器+NAT,则 MASQUERADE iptables规则可能会选择错误的传出地址(因为它始终选择接口上的第一个地址,并且首先设置 192.168.1.3/24),这会干扰路线已到位。始终使用 SNAT 来确定结果。

    LXC 示例,使用 SNAT 而不是 MASQUERADE(应在 LXC 提供的lxc-net脚本命令内更改):

  • 或者,如果路径 MTU 发现在服务器和远程客户端或服务器之间无法正常工作(例如:ICMP 在某处被过滤),则直接将 MTU 设置为 WireGuard 隧道接口的 MTU 在某些情况下(当已建立的 TCP 连接似乎无法正常工作时)会有所帮助。保持冻结状态。这可以按路由而不是按接口进行设置,因此不会影响可选的多宿主 192.168.1.3 源路由。

    ip route delete default
    
    Run Code Online (Sandbox Code Playgroud)

    然后(推荐):

    ip route add default via 192.168.1.2 src 44.44.44.44 mtu 1420
    
    Run Code Online (Sandbox Code Playgroud)

    或者甚至不尝试 PMTUD:

    ip route add default via 192.168.1.2 src 44.44.44.44 mtu lock 1420
    
    Run Code Online (Sandbox Code Playgroud)

现在,服务器上托管的任何服务都可以通过 44.44.44.44 从 Internet 访问,但如果在VPS上使用该选项,则 SSH 除外,并且 Internet 上的任何服务都可以使用 44.44.44.44 源地址从服务器访问。