记录一次低成本 WireGuard 私有网络搭建与故障排查
记录基于低成本 VPS 的 WireGuard 私有网络搭建过程,包括 SSH 非标端口排障、多 Peer 管理、配置分发,以及一次网络出口兼容性实验与回滚。
近期为了做 Linux 网络与 WireGuard 相关实验,新租了一台小规格海外 VPS。主要用途是测试自有设备之间的私有网络互联、Linux 路由与 NAT 配置,以及多 Peer 管理。预算控制在每月 50 元以内,因此没有追求高 CPU 和大内存,而是重点考虑网络稳定性、流量额度和机器本身的资源开销。
本文整理的是当天实验中与 WireGuard 私有组网、Peer 管理和 Linux 网络排障相关的部分。测试过程中还进行过其他网络出口与代理兼容性实验,本文仅记录实验现象和回滚结果,不展开相关配置。正文中的配置也经过整理,主要展示自有设备之间的私网分流方案,并非逐条复现当天所有测试参数。
以下按实际排障与配置过程进行整理。
机器选择与成本
自己租用 VPS 搭建轻量私网隧道,机器硬件配置(如 1 核 1G)对 WireGuard 来说通常不是瓶颈,主要取决于网络链路质量、路由稳定性和晚高峰的延迟丢包情况。高规格专线往往价格较高,超出个人测试的预算。
对比之后选了 ByteVirt 洛杉矶 VPS 的一款优化网络套餐:
- 配置:1 vCPU / 1 GB RAM / 20 GB SSD
- 网络:500 Mbps 端口 / 2 TB 月流量 / 独立 IPv4 × 1
- 价格:月付 4 美元(折合人民币约 28 元)
- 系统:Debian 12
对个人实验环境及少量设备互联而言,500 Mbps 端口和 2 TB 的月流量上限完全够用。
排查非标准 SSH 端口
开通机器后,本地通过默认 22 端口尝试连接:
ssh root@<server-ip>
终端直接返回:
ssh: connect to host <server-ip> port 22: Connection refused
通过服务商提供的 Serial/Xterm.js 网页控制台进入系统,确认 sshd 服务本身处于运行状态:
systemctl status ssh
再通过 ss 查看实际监听的端口:
ss -lntp | grep -E ':22|sshd'
输出显示 sshd 实际监听在服务商预设的高位端口(如 210xx),而不是默认的 TCP/22。非标准 SSH 端口主要用于减少无意义的自动扫描噪声,并不能替代密钥认证、防火墙和最小权限等安全措施。本地在连接时指定实际端口即可正常登入:
ssh -p <ssh-port> root@<server-ip>
服务端 WireGuard 搭建
现代 Linux 内核提供 WireGuard 的内核态实现,用户空间通过 wireguard-tools 完成接口与 Peer 配置。协议和实现都比较精简,对小规格 VPS 的 CPU 与内存压力较低。
系统为 Debian 12,先安装工具并开启 IPv4 转发。由于实验中需要验证 Peer 间转发,因此通过独立的 sysctl 配置文件开启 IPv4 forwarding;如果仅用于客户端访问 WireGuard 服务端自身,而不存在 Peer 间转发或其他子网路由,则无需开启该功能:
apt update
apt install -y wireguard qrencode iptables curl
cat >/etc/sysctl.d/99-wireguard.conf <<'EOF'
net.ipv4.ip_forward=1
EOF
sysctl --system
生成服务端密钥对:
umask 077
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
编写服务端配置文件 /etc/wireguard/wg0.conf。当天全隧道测试阶段曾配置公网 NAT;本文整理后的 split tunnel 方案仅需保障 WireGuard 私网流量的收发与 Peer 间互通,不需要将客户端流量伪装到公网接口。因此公开配置移除了 SNAT/MASQUERADE 规则,并将 FORWARD 规则限定为 wg0 → wg0,不开放向公网接口的通用转发能力:
[Interface]
Address = 10.66.66.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
PostUp = iptables -A FORWARD -i wg0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -o wg0 -j ACCEPT
启动并设置开机自启:
systemctl enable --now wg-quick@wg0
运行 wg show 能看到 wg0 接口监听在 51820 端口,服务端基础配置完成。
客户端分发与配置管理
多设备连接需要注意:每台设备必须使用独立的 Peer 配置与唯一的内网 IP。WireGuard 的一个 Peer 通过公钥唯一标识,并维护当前可达的 Endpoint。如果两台设备共用同一套私钥和隧道地址,服务端可能不断将该 Peer 的 Endpoint 更新为最近发送有效数据包的来源地址,出现 Endpoint flapping,最终表现为连接不稳定、间歇性断流。因此原则上应保持“一台设备一套密钥、一条 Peer 配置、一个独立隧道地址”。
最初几个 Peer 是通过命令行循环批量生成的。实际使用一段时间后,为减少新增设备时重复生成密钥、分配地址和导出配置的操作,又将这一过程整理成了 /root/add-wg-client.sh:
#!/bin/bash
NAME="$1"
if [ -z "$NAME" ]; then
echo "用法: $0 <设备名>"
exit 1
fi
if [ -e "/root/${NAME}.conf" ]; then
echo "设备配置已存在:${NAME}"
exit 1
fi
WG_CONF="/etc/wireguard/wg0.conf"
SERVER_PUB=$(cat /etc/wireguard/server_public.key)
SERVER_IP="<server-ip>"
# 查找未占用的内网 IP
for N in $(seq 2 254); do
if ! grep -q "10.66.66.${N}/32" "$WG_CONF"; then
IP="$N"
break
fi
done
if [ -z "$IP" ]; then
echo "无可用 IP"
exit 1
fi
PRIV=$(wg genkey)
PUB=$(echo "$PRIV" | wg pubkey)
# 写入服务端配置
cat >> "$WG_CONF" <<EOF
# $NAME
[Peer]
PublicKey = $PUB
AllowedIPs = 10.66.66.${IP}/32
EOF
# 生成客户端配置
cat > "/root/${NAME}.conf" <<EOF
[Interface]
PrivateKey = $PRIV
Address = 10.66.66.${IP}/32
MTU = 1380
[Peer]
PublicKey = $SERVER_PUB
Endpoint = $SERVER_IP:51820
AllowedIPs = 10.66.66.0/24
PersistentKeepalive = 25
EOF
chmod 600 "/root/${NAME}.conf"
systemctl restart wg-quick@wg0
echo "已生成 /root/${NAME}.conf (IP: 10.66.66.${IP})"
qrencode -t ansiutf8 < "/root/${NAME}.conf"
关于该配置有三点技术细节说明:
- 路由分流:测试过程中曾根据不同实验目的调整过客户端路由策略。公开版本最终采用 split tunnel,仅将
10.66.66.0/24私网地址段交给 WireGuard,其余互联网流量仍经设备原有网络出口。这样更符合本文“自有设备私有组网与远程运维”的使用范围。 - MTU 调整:客户端的
MTU = 1380并不是固定通用值。实验初期曾采用较保守的 1280,后续根据链路表现提高到 1380。不同网络环境的路径 MTU 不同,实际部署应根据丢包、分片与吞吐表现测试调整。 - 配置热加载:为简化脚本首次实现,当前直接通过
systemctl restart wg-quick@wg0重载配置。这在少量个人设备时足够轻巧,但重启接口会让已有 Peer 短暂断连。设备数量较多或要求不中断已有连接时,可以改用wg syncconf wg0 <(wg-quick strip wg0)动态更新运行态配置。
赋予执行权限后,新增个人设备直接运行 /root/add-wg-client.sh phone-1。终端会直接打印出二维码,手机端 WireGuard 扫码即可导入;电脑端通过本地终端将生成的 .conf 拷贝下来导入客户端使用。
平时在服务器端执行 wg show wg0 可以查看各客户端的最新握手时间及上下行传输流量。
一次额外的出口实验与回滚
WireGuard 基础链路稳定后,我还短暂进行了不同网络出口的链路与地址分类兼容性测试。该实验只用于理解网络出口、ASN 与 IP 数据库之间的关系,本文不展开具体转发配置。
从技术层面看,该链路能够正常工作,出口地址也可以按预期切换。但进一步检查不同 IP 数据库后发现,同一地址在 IP range、ASN、Hosting/ISP 类型及 GeoIP 信息上的分类并不完全一致。
与服务商确认后得知,该地址虽然在 IP range 层级被分类为 ISP,但所属 ASN 仍属于 DCH/Datacenter Hosting,因此部分风控系统仍可能按机房网络处理。
由于该实验不符合预期,最终申请退款,并删除临时策略路由、停用额外转发服务,使网络恢复为单纯的 WireGuard 私有组网结构。
这次测试最大的收获反而是:所谓“ISP IP”“住宅属性”“ASN 类型”“Hosting 分类”是不同层次的信息,不能只根据产品名称判断一个地址的实际网络属性。
其他方案评估
在方案设计与后续使用过程中,也评估过其他用户空间网络工具在规则管理和多节点管理方面的能力。但当前实验只有一个固定 WireGuard 节点,主要需求仍是自有设备之间的私网互联,因此没有迁移,最终继续保留 WireGuard。
最终状态与运维总结
最终没有继续叠加额外代理或复杂控制层,而是保留最简单的 WireGuard 架构。Debian 12 VPS 运行 wg0,每台设备分配独立 Peer、密钥与私网地址;服务器负责私网路由与必要的转发控制,客户端之间不共享密钥。
对这类轻量用途而言,1 vCPU / 1 GB RAM 并没有成为明显瓶颈。实际体验更多取决于网络链路、UDP 丢包、MTU、路由质量以及不同时段的网络状况,而不是单纯提高 CPU 和内存。
后续如果设备数量继续增加,可以引入 Web 管理界面用于 Peer 生命周期管理和流量查看,但底层仍保持 WireGuard,不额外增加不必要的网络层。
本文由 择梦舟 执笔撰作,收录于 Zemengzhou Space。
Discussion
Comments
Share questions, corrections, or extra notes about this post.