我有一个无头 Ubuntu 系统,专门用作 LAN 上其他设备(目前为一台设备)的 WireGuard 客户端。也就是说,它旨在通过隧道转发所有未发送到本地子网的 enp1s0(ETH1)输入——所有非 SSH 输入。隧道的另一端是云 VPS 上的 WG 服务器。
以下是启动 WireGuard 的 SSH 记录:
vpnpeer:~$ sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.4.0.2 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x
[#] ip -4 route add 10.4.0.1/32 dev wg0
[#] ip rule add not to 192.168.1.0/24 iif enp1s0 table 248
[#] ip route add default table 248 via 10.4.0.1 dev wg0
此时 SSH 会话已挂起:它不响应键盘输入(例如 Enter 或 Ctrl-C)。从另一个终端尝试启动另一个 SSH 会话会导致超时。经过约 2 分钟的间隔后,此行出现在上面显示的最后一行之后:
client_loop: send disconnect: Broken pipe
...SSH 客户端终端会显示提示。在最初的硬挂起期间,Ubuntu 系统对按住电源按钮关闭电源没有反应;我拔下并重新插入电源插头以重新启动它。不过,如果我等到显示 SSH 错误消息,问题系统的电源按钮就会关闭它。
以下是 WG 配置文件内容:
[Interface]
PrivateKey = ...
Address = 10.4.0.2
DNS = 1.1.1.2, 1.0.0.2
# filter to pass only nonlocal traffic input on ethernet...
PostUp = ip rule add not to 192.168.1.0/24 iif enp1s0 table 248
# ...to the other end of the tunnel via the WG interface at this end
PostUp = ip route add default table 248 via 10.4.0.1 dev %i
##############The previous command is the last one displayed
##############before SSH hangs
# to local subnet, in from tunnel:
PostUp = ip rule add to 192.168.1.0/24 iif %i table 359
# to any, next hop = gw via ETH1:
PostUp = ip route add default table 359 via 192.168.1.1 dev enp1s0
PostUp = ufw route allow in on enp1s0 out on %i
PostUp = ufw route allow in on %i out on enp1s0
####### PreDown commands omitted
[Peer]
PublicKey = ...
AllowedIPs = 10.4.0.1 # address of virtual remote end of tunnel
Endpoint = ...
非常感谢您的帮助!
答案1
# ...to the other end of the tunnel via the WG interface at this end PostUp = ip route add default table 248 via 10.4.0.1 dev %i
WireGuard 隧道是没有 MAC 地址的“第 3 层隧道”,因此无法使用选择特定网关的路由via
- 所有此类路由的行为都类似于直接dev wg0
路由。(这同样适用于 GRE 隧道、PPP 接口和“tun”接口。)
问题在于:由于缺少 L2 地址,WireGuard 会使用AllowedIPs=
内部选择将数据包转发到哪个对等点。但是,与“via”不同,它基于 IP 标头,而不是 L2 标头,因此只有那些最终目标IP匹配 AllowedIPs 将被允许通过隧道。
这意味着如果您想将 WireGuard 对等体用于默认路由,则必须将该对等体的 AllowedIPs 设置为0.0.0.0/0
(并::/0
设置为 IPv6)。
这样做会将隧道限制到一个对等点;如果您想通过几个不同的下一跳拥有多个默认路由,则需要单独的 WireGuard 隧道(每个对等点一个)。
(请注意,wg-quick 将根据 AllowedIPs 通过 %i 自动插入路由,因此请确保指定Table = 248
以便它们进入正确的表。然后,您可以从 PostUp 中删除手动路由添加。或者,通过 禁用 wg-quick 的自动化Table = off
。)
答案2
我认为问题在于这一点:
ip rule add not to 192.168.1.0/24 iif enp1s0 table 248
你真正想要的iif
是lo
,它用于指代“输出”流量(出站流量源自此主机本身,而iif enp1s0
指从其他主机到达 的流量enp1s0
)。
有上述规则意味着,除非有另一个优先级更低(优先级更高)的规则与案件相关的,to 192.168.1.0/24 iif lo
流量将查找表248
(其中包含通向 WG 隧道的默认路由),因为这些流量是“不是” to 192.168.1.0/24 iif enp1s0
。
类似地,稍后添加的规则to 192.168.1.0/24 iif %i table 359
(当未指定时,优先级较低/优先级较高priority
)也会不是to 192.168.1.0/24 iif lo
也因而掩盖此案iif %i
。
事实上,在你的情况下,你几乎不需要手动设置任何 IP 规则或路由,除非你不希望这个“中继客户端”本身使用 WG 服务器互联网流量(更准确地说,是没有被任何前缀长度 > 0 的路由覆盖的流量),或者存在非默认路由,实际上需要覆盖。
默认情况下(当Table=
未明确设置为除 之外的值时auto
)default
wg-quick 将导致任何原本由表中的路由覆盖的流量main
被路由到隧道中,而非默认路由(前缀长度 > 0)覆盖的流量不会受到影响。
尽管由于 wg-quick 执行命令的顺序存在缺陷ip
,您在设置时仍会遇到断线的情况。如果这让您感到烦恼,请修改wg-quick
(它只是一个 bash 脚本),将route
上面链接中突出显示的行放在rule
它之前的两行之后,即来自:
cmd ip $proto route add "$1" dev "$INTERFACE" table $table
cmd ip $proto rule add not fwmark $table table $table
cmd ip $proto rule add table main suppress_prefixlength 0
到
cmd ip $proto rule add not fwmark $table table $table
cmd ip $proto rule add table main suppress_prefixlength 0
cmd ip $proto route add "$1" dev "$INTERFACE" table $table
(当然,只要系统中的 wireguard-tools 包更新,它就会被重置。)
我不太清楚你真正想要什么:
到本地子网,从隧道进入
您是否真的想让远程主机(WG 客户端,不是您的 LAN 主机之一)能够通过 WireGuard 客户端访问 LAN 上的其他设备?如果是这种情况,请告诉我,我会提供更多信息。