VPSKnow

两台 Linux 主机用 WireGuard 共用出口:从隧道验证到安全回滚

中高级
24分钟

已有两台自己管理的 Linux 主机,想让 A 的部分或全部 IPv4 出站经 B 出网?WireGuard 能建立 A↔B 的加密隧道,但握手成功不等于流量已从 B 出口。本文按“隧道 → B 转发 → A 路由 → 分层验证 → 回滚”的顺序操作,只讨论授权的个人或团队网络管理,不涉及任何服务商或具体业务的可用性保证。

先给结论:隧道通与出口切换是两件事

A 是运行工作负载的主机,B 是预期的 IPv4 出口。A 先用 WireGuard 连接 B 的隧道地址;只有 B 允许转发并做源地址转换,且 A 把目标流量路由进隧道时,外部网站才可能看到 B 的公网出口。

A 工作节点 → WireGuard 加密隧道 → B 出口节点 → Internet。本文的 10.77.0.1/30、10.77.0.2/30 只是示例隧道地址;公网地址、端口和密钥必须换成你自己的值。

最稳妥的顺序是先做仅隧道地址互通,确认握手后再改 B 的转发,最后才改 A 的默认路由。不要直接把未经测试的全隧道配置设为开机自启。

适用条件与变更风险

  • A、B 均为你有权管理的 Linux 主机,支持 WireGuard;B 有可到达的 UDP 监听端口和正常 IPv4 出网。云防火墙与系统防火墙都要核对。
  • A 必须有独立于 SSH 会话的带外控制台或救援模式。单靠定时回滚不能保证始终可登录。
  • 示例针对单网卡、单默认路由、iptables 管理的 IPv4 主机。使用 nftables、firewalld、UFW、Docker、Kubernetes、多网卡或云平台 NAT 时,先按当前防火墙与路由管理器改写规则,不要混用命令。
  • 仅改变 A 的 IPv4 出站路径;不会自动处理 IPv6、DNS、容器独立网络或应用自身的出口绑定。也不保证速度、稳定性或目标服务可用。
变更影响与风险回滚及服务
B 开启转发与 NAT高:影响主机转发、防火墙;可能与容器网络冲突撤销本文专用规则,按变更前值恢复转发;逐个验证依赖服务
A 切换默认路由高:SSH 回程、软件更新和现有长连接可能中断带外控制台执行 wg-quick down;应用连接按需重建

全程不改 SSH 配置。先备份现有 WireGuard 配置;如果计划使用的接口名或隧道网段已被占用,另选名称和网段,不要覆盖已有配置。

第 1 步:记录原始网络状态

在 A、B 各自执行下面的只读检查,留存在自己的设备上;不要公开完整网卡、规则、密钥或管理地址。记录 B 的默认出网网卡,以及 A 的原出口 IP 和 SSH 管理路径。若已有多条默认路由,暂停套用本文的命令。

ip -4 route show default
ip -4 rule show
ip -4 addr show
sysctl net.ipv4.ip_forward
wg show
curl -4 --max-time 10 https://api.ipify.org; echo

两台机器安装系统软件包提供的 wireguard-tools,并确认 wg、wg-quick 可用。不要把私钥、SSH 密码或完整网络配置粘贴到公开工单、截图或 AI 对话中。

第 2 步:只建立点对点隧道

在 A、B 分别生成自己的密钥;只交换公钥。以下会在各自机器写入仅 root 可读的密钥文件,风险为中;回滚时先停用接口,再删除新建的密钥文件,已有文件绝不可覆盖。

sudo install -d -m 700 /etc/wireguard
sudo sh -c 'set -eu; umask 077; test ! -e /etc/wireguard/egress.key; test ! -e /etc/wireguard/egress.pub; wg genkey > /etc/wireguard/egress.key; wg pubkey < /etc/wireguard/egress.key > /etc/wireguard/egress.pub'
sudo cat /etc/wireguard/egress.pub

在 B 新建 /etc/wireguard/wg-egress0.conf,用 B 本机私钥、A 公钥替换占位符。A 使用相同文件名,但填写 A 私钥、B 公钥和 B 的公网 IP。用受限编辑器填入后执行 sudo chmod 600 /etc/wireguard/wg-egress0.conf;不要在共享 Shell 历史里输入私钥。

B 的配置:

[Interface]
Address = 10.77.0.1/30
ListenPort = 51820
PrivateKey = <B_PRIVATE_KEY>

[Peer]
PublicKey = <A_PUBLIC_KEY>
AllowedIPs = 10.77.0.2/32

A 的初始配置:先只允许访问 B 的隧道地址,暂不接管默认路由。

[Interface]
Address = 10.77.0.2/30
PrivateKey = <A_PRIVATE_KEY>

[Peer]
PublicKey = <B_PUBLIC_KEY>
Endpoint = <B_PUBLIC_IP>:51820
AllowedIPs = 10.77.0.1/32
PersistentKeepalive = 25

在 B 的云防火墙和实际系统防火墙中,仅按 A 的真实来源地址放行所选 UDP 端口;A 若位于动态 NAT 后,需按实际来源和当前防火墙策略评估,不能照搬固定源 IP 规则。随后先在 B 执行 sudo wg-quick up wg-egress0,再在 A 执行下面的命令。wg-quick up 只启用新接口;此阶段不应改动 A 的默认出口。失败时分别 wg-quick down wg-egress0,无需重启其他服务。

sudo wg-quick up wg-egress0
sudo wg show wg-egress0
ping -c 3 10.77.0.1

上述代码块整体仅在 A 执行;在 B 单独运行 sudo wg show wg-egress0。若 ICMP 被防火墙拦截,以双端 wg show 的最新握手与双向传输计数、实际测试流量为准。握手失败先检查端点 IP、UDP 端口、公钥与防火墙,不要先动默认路由。

第 3 步:在 B 配置受限的 IPv4 出口

影响范围:B 的 IPv4 转发和 iptables;风险:高。下面仅适用于确认由 iptables 管理、且没有与其他防火墙框架竞争的 B。先从基线记录中确认 WAN_IF;不要猜网卡名。若 B 运行 Docker 或已有复杂转发规则,先按其管理器设计等价规则,不能把下列规则与它叠加后假定一定生效。需要时由管理员在维护窗口重启受影响的容器服务,并验证容器连通性;不建议无差别重启整机。

以下命令只添加针对 A 隧道地址的规则,ip_forward 先临时开启;记下原值。将 WAN_IF 换成 B 的实际出网接口后,在 B 执行。请先逐条核对,再在维护窗口运行。

WAN_IF='<B_EGRESS_INTERFACE>'
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -I FORWARD 1 -i wg-egress0 -s 10.77.0.2/32 -o "$WAN_IF" -j ACCEPT
sudo iptables -I FORWARD 1 -i "$WAN_IF" -o wg-egress0 -d 10.77.0.2/32 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -I POSTROUTING 1 -s 10.77.0.2/32 -o "$WAN_IF" -j MASQUERADE

这些规则默认不会跨重启持久化。若你使用 nftables、UFW、firewalld 或容器编排,应在其唯一权威配置中落地等价的最小规则,并先验证规则生效。不要为了“省事”清空整个防火墙或做不限定源地址的全局 NAT。

第 4 步:A 试运行 IPv4 全隧道

影响范围:A 的 IPv4 默认出站,风险:高。优先通过带外控制台操作,保持另一个独立管理会话,记录原出口和救援入口。先在 A 执行 sudo wg-quick down wg-egress0,把 A 配置中 Peer 的 AllowedIPs 从 10.77.0.1/32 改为 0.0.0.0/0。不要加入 ::/0,也不要把这个 IPv4 示例解释成 IPv6 已受保护。

在重新启动前安排一个一次性的 180 秒关闭任务;确认该命令成功且计时器已运行,才启动新配置。定时器只是额外保险:主机重启、systemd 故障、配置残留或原 SSH 路径变化都可能使它无法恢复管理连接,因此带外控制台仍是前提。

sudo systemd-run --on-active=180s --unit=wg-egress-rollback /usr/bin/wg-quick down wg-egress0
systemctl status wg-egress-rollback.timer
sudo wg-quick up wg-egress0
sudo wg show wg-egress0
ip -4 rule show
curl -4 --max-time 10 https://api.ipify.org; echo

不同发行版的 wg-quick 路径可能不是 /usr/bin/wg-quick,执行前先用 command -v wg-quick 核对。只有检查通过、管理会话仍可进入,才停止 wg-egress-rollback.timer。先不要开机自启:B 的转发规则及 A 的救援路径都需要单独设计持久化。

验证:握手、路由、出口、DNS 与 IPv6

  1. 隧道:A、B 的 wg show 有近期握手,收发计数随测试增长;只有握手不代表 B 已转发。
  2. 主机 IPv4:A 上 curl -4 的公网结果应与 B 自己的 curl -4 结果一致;如 B 还有上游 NAT,以实际外显地址为准,不能凭 IP 类型标签推断网络属性。
  3. 工作负载:从实际应用进程或容器内部再测一次出口。应用绑定源地址、代理设置或容器网络可能绕开主机默认路径;不应宣称“所有软件无需改动”。
  4. DNS / IPv6:本文未强制改 DNS,也未配置 IPv6。分别检查实际解析器和 curl -6;若任务要求双栈同一路径,应另行设计 IPv6 隧道与防火墙,不能把 IPv4 成功当成无泄漏证明。
  5. 管理和服务:用新 SSH 会话检查 A 可达性,并验证 B 原有服务、容器网络与应用长连接。需要重建连接的应用按需重启,避免全机批量重启。

测试期间可以用 ip -4 route get 1.1.1.1 辅助看路由选择,但它不是实际应用流量的证明。记录同一时段的 A、B 出口结果和应用内结果,才足以判断是否按预期切换。

回滚:先恢复 A,再清理 B

影响范围:两机网络与依赖应用;风险:高。如果 A 失联,从带外控制台先停 A 的接口,把 A 配置中的 AllowedIPs 改回 10.77.0.1/32,再确认原出口;不要在仍为 0.0.0.0/0 时重新启动接口。确认新 SSH 会话及实际应用连通后,再到 B 撤销本文新增的三条 iptables 规则。不要为了排查 A 而同时修改 B 的其他正常服务。若曾把规则写入持久化防火墙配置,还须从该配置中移除并按其管理器重载。

仅在 A 执行:如果定时器已触发、unit 不再存在,先检查接口状态,再从带外控制台继续恢复。

sudo systemctl stop wg-egress-rollback.timer
sudo wg-quick down wg-egress0
ip -4 route show default
curl -4 --max-time 10 https://api.ipify.org; echo

仅在 B 执行:WAN_IF 使用先前记录的 B 出网网卡。删除命令只针对本文新增的规则,先核对规则仍存在;若有其他业务复用了完全相同的规则,不要直接删除。

WAN_IF='<B_EGRESS_INTERFACE>'
sudo iptables -D FORWARD -i wg-egress0 -s 10.77.0.2/32 -o "$WAN_IF" -j ACCEPT
sudo iptables -D FORWARD -i "$WAN_IF" -o wg-egress0 -d 10.77.0.2/32 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -D POSTROUTING -s 10.77.0.2/32 -o "$WAN_IF" -j MASQUERADE
sudo wg-quick down wg-egress0

只有在确认 B 原来的 net.ipv4.ip_forward 为 0,且没有其他业务依赖转发时,才把它恢复为 0;原值为 1 就保持 1。若之前额外创建了持久化 sysctl 文件,需先恢复或删除你新建的那个文件,再重载配置;不要删除系统既有文件。检查规则列表、B 原有出网、容器服务和 A 的新 SSH 会话;受影响的应用或容器仅在需要时重启并验收。配置文件和密钥也只在确认无需保留后逐个删除,绝不批量删除整个 /etc/wireguard。

常见故障与适用边界

  • 无握手:先查 B 的 UDP 端口是否在云防火墙及系统防火墙均放行,再核对 Endpoint 和两端公钥。
  • 有握手、A 不能从 B 出网:依次查 B 的 ip_forward、FORWARD、NAT、B 自身出口;不要先换协议或随机调 MTU。
  • IPv4 出口正确,应用仍走旧路:检查容器网络、应用绑定地址、独立代理配置、DNS 与 IPv6;先定位具体进程,不要继续扩大系统路由变更。
  • 部分网站卡住:在确认路径无误后再排查 MTU / PMTU。wg-quick 可自动推断 MTU,固定写成 1420 并不保证适合所有底层链路。
  • B 的公网地址变化:A 的 Endpoint 需要更新;公网不可入站或双端均在 NAT 后,不能直接套用这个端点模型。

WireGuard 只负责加密隧道,不改善本来就差的 A↔B 路径,也不赋予出口 IP 特定的信誉或用途资格。请遵守两台主机所属网络的使用规则,仅在自己授权的环境中部署。

资料来源与证据状态

本文基于 WireGuard 官方 Quick Start 的密钥、握手与保活说明,以及 wg-quick 手册 的 AllowedIPs、默认路由和 MTU 行为整理。命令为通用示例,未在读者的主机环境中实测;防火墙框架、带外救援、应用出口与回滚仍须逐机验证。

🚀 下一步行动

如果还需排查更复杂的网络路径,可继续阅读:

读完后建议 先验证,再选择
把判断落到具体选择

准备购买 VPS 时,先对照推荐榜单和真实测评确认线路、价格、用途与风险;只是继续学习,可以回到教程索引按主题往下看。