SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-09-01

WireGuard 如何路由到家庭局域网

WireGuard 握手正常但无法访问 192.168.20.10?检查客户端 AllowedIPs、服务器 AllowedIPs、IP 转发和返回路由,4 项中任一项错误都不会显示日志或警告。

为什么家庭 LAN 无法通过 WireGuard 响应

要通过 WireGuard 路由到家庭 LAN,必须同时正确配置4项设置。即使其中3项正确,隧道看起来仍然完全正常,这正是问题难以排查的原因。wg show显示最近完成过握手,ping 10.8.0.1在几毫秒内返回响应,而 ping 192.168.20.10 完全没有返回。

以下是数据包依次经过的完整检查项。LAN 表示局域网,即家庭路由器后面的私有网络。

  1. 客户端上的 AllowedIPs 必须覆盖远程子网,否则数据包根本不会进入隧道。
  2. 服务器上的 AllowedIPs 必须覆盖客户端的隧道地址,否则数据包解密后会立即被丢弃。
  3. 服务器上的 net.ipv4.ip_forward 必须设为 1,因为 Linux 会丢弃所有目标地址不是本机的数据包。
  4. LAN 必须知道返回 10.8.0.0/24 的路由。可在服务器上配置 masquerade 规则,或在家庭路由器上配置静态路由。

这些设置中的任何一项出错时,都不会显示错误消息。不会记录日志,也不会发出警告,握手会始终正常工作。按顺序检查这些设置,通常约1分钟即可找出出错项。

本指南使用的网络

下面的所有地址都只是示例。请替换为您自己的地址,并保持替换结果一致,因为配置只更新了一部分是此问题的第二常见原因。

  • 家庭 LAN 为 192.168.20.0/24。家庭路由器为 192.168.20.1
  • WireGuard 服务器是该 LAN 中的一台 Linux 主机。其 LAN 接口 enp1s0 使用 192.168.20.5,隧道接口 wg0 使用 10.8.0.1
  • 要访问的主机是位于 192.168.20.10 的 NAS(网络附加存储)。
  • 客户端是一台位于其他网络中的笔记本电脑,在隧道内使用 10.8.0.2

服务器是 LAN 中的一台主机,不是路由器本身。通常是 Raspberry Pi 或旧的 mini PC。这一点与规则 4 有关:除非您告知路由器,否则路由器不知道隧道的存在;LAN 中的每台主机都会将发往子网外的流量发送到该路由器。

如果您的家庭网络连接没有公网 IP 地址,这些配置无法单独工作,因为互联网中的任何主机都无法向您的家庭网络发起握手。通过 VPS 中转一节介绍这种情况。相同的四条规则仍然适用,但还需要额外维护一个对等端。

AllowedIPs 有两种不同的含义

同一个设置承担两项功能。在连接两端用同一种方式解读它,是大多数此类工单的根本原因。WireGuard 将这一机制称为加密密钥路由,详见WireGuard 如何将公钥绑定到 IP 地址范围

从出站方向看,AllowedIPs 是路由表。 wg-quick 会将每个条目转换为指向 wg0 的路由。只有当某个对等方声明了包含 192.168.20.10 的地址范围时,发往 192.168.20.10 的数据包才会被加密并发送给该对等方。只列出 10.8.0.0/24 时,您的笔记本电脑会将 LAN 流量改从本地 Wi-Fi 发出,结果要么无法到达,要么会到达完全不同的 192.168.20.10

从入站方向看,AllowedIPs 是访问控制列表。 WireGuard 从对等方解密数据包后,会将内部源地址与该对等方的 AllowedIPs 进行比对;如果不匹配,就丢弃数据包。此丢弃操作不会产生日志,也没有对应的计数器。数据包会直接消失。

因此,两个配置文件绝不是镜像关系。客户端列出希望通过服务器访问的目标。服务器列出允许该客户端用作源地址的地址。

匹配的配置文件对

客户端,/etc/wireguard/wg0.conf

[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32

[Peer]
PublicKey = <server public key>
Endpoint = home.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.20.0/24
PersistentKeepalive = 25

服务器,/etc/wireguard/wg0.conf

[Interface]
PrivateKey = <server private key>
Address = 10.8.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <laptop public key>
AllowedIPs = 10.8.0.2/32

家庭路由器还需要配置端口转发,将 UDP 51820 转发到 192.168.20.5;否则握手不会开始,客户端日志中会出现 Handshake for peer 1 did not complete after 5 seconds, retrying。本指南假定您已经完成这一步。

这里有 4 行配置不同于普通的全隧道设置,而且每一处差异都有明确目的。

  • 客户端使用 AllowedIPs = 10.8.0.0/24, 192.168.20.0/24,而不是 0.0.0.0/0, ::/0。这是分流隧道:隧道子网和家庭 LAN 通过 wg0,其他流量继续使用本地路由。网页浏览不会经过家庭网络连接;如果您只需要访问 NAS,通常应采用这种设置。
  • 服务器使用 AllowedIPs = 10.8.0.2/32,而不是一个地址范围。请在此处填写 10.8.0.0/24,这样该单个客户端可以使用隧道内的任意地址。之后如果添加地址范围重叠的第二个 peer,流量会转到最后配置的 peer,且任何位置都不会打印错误。
  • 仅在客户端使用 PersistentKeepalive = 25。客户端位于 NAT(网络地址转换)之后,其路由器在静默 1 到 2 分钟后会忘记 UDP 映射,因此服务器将无法再访问客户端。服务器有公网地址,不需要 keepalive。
  • 目前还不要添加 DNS = 行。添加后会更改整个客户端计算机的名称解析。下面的 DNS 部分会在您启用此配置前解释其作用。

全隧道同样可以访问 LAN,因为 0.0.0.0/0 匹配所有地址。但它会承载您的全部流量,并导致客户端无法解决的子网冲突。

两端使用相同子网会导致连接失败

选择一个几乎不会与其他网络重复的家庭子网,例如 192.168.20.0/2410.44.7.0/24192.168.1.0/24192.168.0.0/24 是大多数家用路由器的出厂默认值,因此你的笔记本迟早会接入某个咖啡馆或酒店网络,而该网络恰好使用相同的地址范围。

地址冲突会直接阻止连接建立,并且在两种模式下表现不同。使用分流隧道时,wg-quick 会尝试为一个已存在于 Wi-Fi 接口上的前缀添加路由,ip route add 会拒绝该操作,导致接口无法启动:

RTNETLINK answers: File exists

使用全隧道时,wg-quick 会安装策略路由规则,有意让主路由表中更具体的路由失效。本地的 192.168.1.0/24 路由优先于隧道,因此所有发往远程 LAN 的数据包都会通过本地链路发送。隧道已建立,握手正常,但仍无法访问 NAS。真正的解决办法只有为家庭 LAN 重新编号。

将服务器配置为路由器

ip route show default
printf 'net.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward

第一条命令会显示 LAN 接口的实际名称。当前镜像通常使用类似 enp1s0ens3 的名称,很少使用 eth0。如果伪装规则指定了错误的接口,就不会匹配任何流量。最后一条命令应输出 net.ipv4.ip_forward = 1。直接执行 sudo sysctl -w 也会设置相同的值,但该设置会在下一次重启后丢失,这正是“之前一直正常,直到星期二突然不行了”这类问题的典型原因。

转发还必须通过防火墙。在启用 ufw 的 Ubuntu 上,除非在 /etc/default/ufw 中设置 DEFAULT_FORWARD_POLICY="ACCEPT",否则转发的数据包会被丢弃。Docker 会自动设置相同的策略。因此,如果你从未手动配置过防火墙,但在某台服务器上执行 sudo iptables -S FORWARD | head -1 输出 -P FORWARD DROP,说明该设置是 Docker 完成的;隧道流量仍需要显式的允许规则。

为什么回复始终无法返回

正确配置规则 1 到 3 后,ping 确实能到达 NAS。但您仍然看不到响应,因为回复没有返回路径。NAS 向 10.8.0.2 回复。该地址不在 NAS 自身的子网中,因此 NAS 会将数据包交给默认网关,也就是位于 192.168.20.1 的家用路由器。该路由器从未配置过 10.8.0.0/24 的路由,因此会将回复转发给自己的默认网关,也就是您的互联网连接,随后数据包被丢弃。请求到达了,但回复被丢弃。

选项 A:在 WireGuard 服务器上配置 masquerade。 服务器会将每个转发数据包的源地址改写为 192.168.20.5,也就是服务器自身的 LAN 地址。此时 NAS 会认为请求来自同一子网中的邻居,并直接向服务器回复。服务器再还原地址改写,并通过隧道将回复发回。LAN 中的其他设备无需修改配置。

将规则写入服务器的 [Interface] 块,使其随接口一同创建和删除:

PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp1s0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o enp1s0 -j MASQUERADE

如果设备已经由 nftables 管理,则改为写入 /etc/nftables.conf

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.8.0.0/24 oifname "enp1s0" counter masquerade
  }
}

保留 counter 关键字。没有它,sudo nft list ruleset 会显示规则,但不会显示数据包计数。该计数正好可以告诉您规则是否正在生效。

Masquerade 还有一个容易忽略的好处。许多主机运行的防火墙只接受来自本地子网的连接。Windows 文件共享默认采用这种方式,许多 NAS 管理面板也一样。即使路由完全正确,来自 10.8.0.2 的数据包仍会被目标主机丢弃。启用 masquerade 后,源地址会变成本地 LAN 地址,因此这些防火墙规则可以匹配。代价是,所有隧道客户端在每台 LAN 主机的日志中都会显示为 192.168.20.5。因此,您无法区分不同客户端,LAN 设备上的按客户端规则也无法生效。

选项 B:在家用路由器上配置静态路由。 告诉路由器 10.8.0.0/24 位于 192.168.20.5 后面。在 Linux 路由器上只需执行一条命令:

sudo ip route add 10.8.0.0/24 via 192.168.20.5

家用路由器通常会在高级设置中提供名为 Static Routes 或 Routing 的页面:目标地址为 10.8.0.0,掩码为 255.255.255.0,网关为 192.168.20.5。请将其保存到路由器的持久配置中,因为在 Linux 主机上临时执行的 ip route add 会在下次重启时丢失。

这种方式会保留客户端的真实地址,因此 LAN 中的日志和按客户端规则仍然有效。它要求路由器支持静态路由,并且只对将该路由器用作默认网关的主机有效。使用按子网限制的本地防火墙的主机,仍需为 10.8.0.0/24 单独添加规则。建议先使用 masquerade,因为它不需要修改您当前控制范围之外的设备;当您需要保留真实客户端地址时,再改用静态路由。

如何判断四项中是哪一项有问题

从客户端开始逐层向外检查。每一步都能说明数据包是否已经到达该位置。

数据包是否进入隧道? 在客户端执行:

ip route get 192.168.20.10

输出应显示 dev wg0。如果显示的是 Wi-Fi 接口,则规则 1 有误,客户端的 AllowedIPs 未覆盖 LAN 子网。出现 ping: connect: Network is unreachable 也说明问题在同一行。

数据包是否到达服务器? 在服务器上运行以下命令,然后从客户端 ping NAS:

sudo tcpdump -ni wg0 icmp

正常路径会显示 IP 10.8.0.2 > 192.168.20.10: ICMP echo request。其中,ICMP 是互联网控制消息协议,也是 ping 使用的协议。握手正常但此处没有任何输出,说明是规则 2 的问题:服务器上该对等端的 AllowedIPs 不包含 10.8.0.2,因此数据包在解密前就被丢弃,尚未到达 wg0

数据包是否离开服务器并进入 LAN? 在服务器上监控 LAN 侧:

sudo tcpdump -ni enp1s0 icmp

如果在 wg0 上能看到请求,而此处没有输出,则是规则 3 的问题,说明转发未启用,或 FORWARD 规则丢弃了数据包。如果此处能看到源地址为 10.8.0.2 的请求但没有回复,则是规则 4 的问题,说明回复没有返回路由。如果此处能看到源地址为 192.168.20.5 的请求但没有回复,则说明 masquerade 规则正常工作,目标主机本身拒绝了请求,应检查 NAS 上的防火墙。将 icmp 替换为 port 445 或所需的其他端口后,同样的排查顺序也适用于其他服务。

我可以访问 IP,但无法解析名称

ssh 192.168.20.10 可用,而 ssh nas.home.arpa 失败:

ssh: Could not resolve hostname nas.home.arpa: Name or service not known

隧道没有问题。名称解析走的是独立路径,您的笔记本电脑仍在向本地 Wi-Fi 下发给它的解析器发送请求。该解析器不了解您家庭网络中的名称。

要使家庭网络名称正常工作,必须满足两个条件。解析器地址必须位于客户端的 AllowedIPs 中,否则 DNS(域名系统)查询不会进入隧道。解析器还必须愿意回答源地址为 10.8.0.2 的查询。许多家庭解析器默认会拒绝此类请求:以 local-service 运行的 dnsmasq 只回答来自直接连接子网的查询,Pi-hole 提供的监听模式也只允许本地请求。伪装规则会隐藏这个问题,因为重写后,查询会以 192.168.20.5 作为源地址到达解析器。

客户端只需添加一行:

DNS = 192.168.20.1

在 Linux 客户端上,需要设置 openresolv 或等效配置,否则 wg-quick 会以 resolvconf: command not found 停止运行。在设置之前,请先了解它在 systemd-resolved 系统上的行为:wg-quick 会独占注册这些服务器,因此隧道建立后,笔记本电脑上的所有查询都会发送到家庭解析器,而不只是家庭网络名称。使用 resolvectl status wg0 检查结果。如果您希望家庭网络名称由家庭解析器解析,其他名称仍由本地解析器解析,这就是分离 DNS;修复 WireGuard 隧道上的 DNS 将完整介绍配置方法。

家中没有公网 IP?将 VPS 放在中间

如果路由器状态页显示 WAN 地址位于 100.64.0.0/10,或者显示私有 192.168.x.x 地址,则说明您处于 CGNAT(运营商级网络地址转换)之后,来自互联网的握手无法到达您的家庭网络。出站握手仍可正常工作,因此解决方案是增加一个具有公网地址的第三节点。由一台小型 VPS 运行中继节点,家中的主机主动连接到该 VPS。

四条规则不变。现在它们要跨越两跳,因此需要维护的配置增加一倍。

  • 在 VPS 上,家中主机的对等端条目使用 AllowedIPs = 10.8.0.3/32, 192.168.20.0/24:填写其自身的隧道地址,以及它被允许代为传输的子网。
  • 在 VPS 上,笔记本电脑的对等端条目仍使用 AllowedIPs = 10.8.0.2/32
  • 在笔记本电脑上,VPS 对等端使用 AllowedIPs = 10.8.0.0/24, 192.168.20.0/24,因为现在所有流量都发往中继节点。
  • 在家中主机上,VPS 对等端使用 AllowedIPs = 10.8.0.0/24,并且家中主机使用 PersistentKeepalive = 25,因为它现在位于 NAT 后方。
  • VPS 还需要 net.ipv4.ip_forward = 1,并且其转发链必须允许 wg0wg0,因为笔记本电脑的流量从同一个接口进入并离开。为普通全隧道 VPS 编写的防火墙恰好会阻止这种流量。

如果您还没有配置 VPS 端,在 VPS 上设置 WireGuard介绍了密钥生成、防火墙和 systemd 单元的配置方法。关于如何访问无法接受入站连接的主机,请参阅从 CGNAT 后方建立反向隧道。如果不想再手动维护对等端地址,运行 Tailscale 子网路由器可以完成相同的路由工作,并自动维护地址配置。

使其在重启后仍能运行

sudo systemctl enable --now wg-quick@wg0
sudo systemctl enable --now nftables
sudo wg show

enable --now 是最容易被忽略的部分。手动运行的 wg-quick up wg0 在下一次内核升级并重启后就会消失。wg show 应列出该对端,并显示最近的 latest handshake 记录,同时两个方向的传输计数器都应为非零值。

之后添加第二个客户端不需要重启,因为重启会断开当前已连接的所有客户端:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

wg-quick strip 会输出配置,但不会包含只有 wg-quick 能识别的密钥;syncconf 会在保持活动会话运行的情况下应用差异。它只更新对端。修改 Address 或新增 PostUp 行,仍需要完整执行 down 和 up。

FAQ

为什么可以 ping 通 WireGuard 服务器,却无法访问家庭 LAN 中的其他设备?

能够 ping 通 10.8.0.1 只能证明隧道已建立。LAN 中的其他设备无法访问,原因是路由配置有问题。客户端的 AllowedIPs 必须包含 192.168.20.0/24,否则数据包不会进入隧道。服务器需要将 net.ipv4.ip_forward 设置为 1,否则会丢弃所有目标地址不是自身的数据包。LAN 还需要存在返回 10.8.0.0/24 的路由。在服务器上运行 sudo tcpdump -ni enp1s0 icmp,同时执行 ping:如果看到请求以 10.8.0.2 作为源地址发出,却没有返回响应,说明缺少返回路径。

家庭路由器上是否需要静态路由?

只有在不使用 masquerade 规则时才需要。WireGuard 服务器上的 masquerade 规则会将隧道流量的源地址改写为服务器自身的 LAN 地址。这样,LAN 主机会向已知的相邻设备返回响应,路由器也无需参与。另一种方式是添加一条通过服务器 LAN 地址访问 10.8.0.0/24 的静态路由。当您希望 LAN 主机的日志中保留真实客户端地址,或希望在这些主机上配置按客户端区分的防火墙规则时,静态路由值得配置。

为什么两端使用相同子网会导致隧道故障?

您的笔记本无法为同一个前缀同时保留两条路由。如果本地网络分配 192.168.1.0/24,而家庭 LAN 也是 192.168.1.0/24,则分离隧道的 wg-quick up 会在 ip route add 拒绝并返回 RTNETLINK answers: File exists 时失败。完整隧道可以建立,但 wg-quick 会安装策略规则,使主路由表中更具体的路由失效,因此本地网络优先,远程 LAN 仍无法访问。将家庭 LAN 重新编号为较少使用的网段,例如 192.168.20.0/24。客户端没有其他修复方法。

可以通过 IP 访问 NAS,但无法通过名称访问。缺少什么配置?

名称解析不会自动通过隧道传输。将家庭解析器 DNS = 192.168.20.1 添加到客户端的 [Interface] 块中,并确保该地址位于对端的 AllowedIPs 内,否则查询不会进入隧道。然后确认解析器允许来自自身子网之外的查询,因为 dnsmasq 配合 local-service,以及 Pi-hole 的仅本地监听模式,都会拒绝此类查询。WireGuard 服务器上的 masquerade 规则可以通过改写查询的源地址来绕过这一限制。

家庭网络没有公网 IP。仍然可以访问 LAN 吗?

可以,但需要第三个节点。在 CGNAT 后面时,路由器的 WAN 地址是私有地址,因此互联网中的对端无法主动与其发起握手;但由内向外发起的握手通常正常。将 WireGuard 运行在具有公网地址的 VPS 上,让家庭主机通过 PersistentKeepalive = 25 主动连接 VPS,并在 VPS 上为家庭主机配置对端条目,使其包含一个 AllowedIPs,其中写入家庭主机的隧道地址以及 192.168.20.0/24。随后还需要在 VPS 上启用转发,并添加允许 wg0wg0 的转发规则。