个人服务器组网与防护实践(一):WireGuard 打通云端与家庭网络
个人服务分布在云主机和家庭小主机上,开发电脑也需要访问这些服务。这里通过 WireGuard 建立私有网络,让跨主机访问使用隧道地址,普通上网和现有公网业务保持原来的路径。
本篇完成组网;
第二篇解释 Docker 与防火墙的关系;
第三篇记录端口防护方案。
1 网络规划
- 云主机:阿里云 ECS,Ubuntu 24.04,
10.10.0.1。 - 家庭小主机:Ubuntu,
10.10.0.2。 - 开发电脑:Windows 10,
10.10.0.3。 - 隧道网段:
10.10.0.0/24,使用前确认不与局域网、云 VPC、Docker 和其他 VPN 网段冲突。 - 云主机入口:
infra.xuqiudong.cn:51820/UDP,域名解析到云主机公网地址。
text
Windows 10.10.0.3 ← 隧道 → 云主机 10.10.0.1 ← 隧道 → 小主机 10.10.0.2
- Windows 和小主机主动连接云主机,二者互访经云主机转发。
- 家庭侧无需公网 IP,也无需为 WireGuard 配置路由器端口转发。
- 只将
10.10.0.0/24送入隧道,不接管全部上网流量,也不自动接入整个家庭局域网。 - WireGuard 各节点都是 Peer;这里按部署职责称云主机为中心节点。
2. Linux 安装与密钥
云主机和小主机分别执行:
bash
sudo apt update
sudo apt install -y wireguard
# 每台机器独立生成密钥;umask 077 限制新文件权限。
sudo sh -c 'umask 077; cd /etc/wireguard && wg genkey | tee private.key | wg pubkey > public.key'
# 只将公钥提供给对端,私钥留在本机配置中。
sudo cat /etc/wireguard/public.key
下面配置中的中文占位值需替换为对应节点的实际密钥。
3. 云主机配置
3.1 隧道
文件:/etc/wireguard/wg0.conf。
ini
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = 云主机私钥
[Peer]
PublicKey = 小主机公钥
AllowedIPs = 10.10.0.2/32
[Peer]
PublicKey = Windows公钥
AllowedIPs = 10.10.0.3/32
- 云端每个 Peer 分配独立
/32地址,避免互相覆盖。 AllowedIPs参与出站 Peer 选择,并校验该 Peer 发来的隧道内源地址;它不负责端口授权。
3.2 转发与防火墙
先检查云主机是否已开启 IPv4 转发:
bash
sysctl net.ipv4.ip_forward
- 输出为
1:已开启,无需重复设置。安装 Docker 后,该值可能已由 Docker 开启。 - 输出为
0:无法在两个 Peer 之间转发,需要开启。 - Ubuntu 通常默认关闭此项;以当前检查结果为准,不能将 Docker 开启后的状态当作系统默认值。
仅在需要自行持久化开启时,在 /etc/sysctl.d/ 下新增配置,例如 99-wireguard-forward.conf。这是自定义文件名,不是 WireGuard 自带文件;若已有配置管理此参数,直接沿用,避免重复。
ini
# 允许云主机在 Windows 和小主机之间转发 IPv4 数据包。
net.ipv4.ip_forward=1
bash
# 仅在新增上述文件后执行,加载该文件中的内核参数。
sudo sysctl -p /etc/sysctl.d/99-wireguard-forward.conf
防火墙规则:
bash
# 隧道外层入口;阿里云安全组也需要开放 UDP 51820。
sudo ufw allow 51820/udp
# 解密后访问云主机自身服务的流量。
sudo ufw allow in on wg0 from 10.10.0.0/24
# 解密后由云主机转发给另一个 Peer 的流量。
sudo ufw route allow in on wg0 out on wg0 \
from 10.10.0.0/24 to 10.10.0.0/24
- UDP 51820 放行的是加密报文,解密后的报文仍需按目标经过本机入站或转发规则。
- 本机入站规则与转发规则用途不同,不能互相替代。
- 本方案信任隧道内节点,允许整个隧道网段入站;需要细分权限时,再按目标端口收紧。
- Docker 发布端口走转发路径,不能仅凭 UFW 入站规则判断是否受保护,详见后两篇。
4. 家庭小主机配置
文件:/etc/wireguard/wg0.conf。
ini
[Interface]
Address = 10.10.0.2/32
PrivateKey = 小主机私钥
[Peer]
PublicKey = 云主机公钥
Endpoint = infra.xuqiudong.cn:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
bash
# 允许隧道内节点访问小主机自身服务。
sudo ufw allow in on wg0 from 10.10.0.0/24
PersistentKeepalive = 25:空闲时每 25 秒发送保活包,维持家庭 NAT 映射。- 小主机只作为访问终点,不转发到家庭 LAN,因此此处不需要启用 IP 转发或配置 NAT。
5. Windows 配置
安装 WireGuard 官方客户端,新建空隧道;客户端生成独立密钥,将其公钥填入云端配置。
ini
[Interface]
PrivateKey = Windows私钥
Address = 10.10.0.3/32
[Peer]
PublicKey = 云主机公钥
Endpoint = infra.xuqiudong.cn:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
保存并启用隧道。这里不配置 0.0.0.0/0,也无需为普通上网更换 DNS。
6. 启动与验证
6.1 Linux 启动
两台 Linux 分别执行:
bash
sudo chmod 600 /etc/wireguard/wg0.conf
sudo systemctl enable --now wg-quick@wg0
# 查看握手时间与收发量;有配置不代表已成功握手。
sudo wg show
ip -4 addr show wg0
wg-quick@wg0显示active (exited)属于正常状态,接口已由脚本创建。- 修改配置后执行
sudo systemctl restart wg-quick@wg0,期间隧道会短暂中断。 - 分享配置或排查输出前,去除私钥;不要公开完整配置文件。
6.2 连通性
Windows PowerShell:
powershell
ping 10.10.0.1
ping 10.10.0.2
# 服务启动且允许访问后,再检查具体 TCP 端口。
Test-NetConnection 10.10.0.1 -Port 3306
小主机:
bash
ping -c 3 10.10.0.1
排查顺序:
- 无握手:检查 Endpoint 解析、密钥、UDP 51820 和云安全组。
- 能访问云端,不能访问另一 Peer:检查云端 IP 转发、UFW route 和双方
AllowedIPs。 - 节点可达但服务不通:检查服务监听地址、发布端口、Docker 防火墙规则和应用认证。
ping失败也可能是 ICMP 被拦截,结合握手和实际服务端口判断。
7. 应用访问方式
- 跨主机:云端 MySQL 用
10.10.0.1:3306,Redis 用10.10.0.1:16379,Meilisearch 用http://10.10.0.1:7700。 - 同机 Docker:加入同一个
xqd-net,使用mysql:3306、redis:6379、http://meilisearch:7700;这些名称是网络内的服务名或别名。 - 服务只监听
127.0.0.1时,无法通过隧道地址访问。改为监听隧道地址或0.0.0.0后,必须同时检查公网隔离。 - MySQL 从库可通过云端隧道地址连接主库;复制账号、权限和同步状态仍需单独配置与检查。
- Jenkins 的 SSH/SCP 可按需继续使用原地址。
实测 Windows → 云机、小主机 → 云机、Windows → 小主机连通。接入具体服务时,还应分别检查隧道访问和公网隔离,节点连通不代表服务配置已完成。
这套组网依赖中心云主机。云主机不可用时,节点间的隧道通信也会中断,原有公网业务和普通上网仍按各自路径运行。
8. 组网之后遇到的问题
节点互通后,我发现:云主机的 Redis 部署在 Docker 中,即使没有在 UFW 中放行对应端口,Windows 仍能通过 10.10.0.1 访问它。
为什么隧道内的宿主机服务需要 UFW 放行,而 Docker 发布端口表现不同?这是否也会影响公网端口防护?第二篇从报文路径和 iptables 规则解释这个问题。
附录:常用命令
A. 隧道管理
bash
# 启动并设为开机启动;停止时不会取消开机启动。
sudo systemctl enable --now wg-quick@wg0
sudo systemctl stop wg-quick@wg0
# 修改配置后重启,隧道会短暂中断。
sudo systemctl restart wg-quick@wg0
# 查看运行状态、是否开机启动。
sudo systemctl status wg-quick@wg0
sudo systemctl is-enabled wg-quick@wg0
# 查看本次开机的最近 50 条服务日志;-u 指定服务,-b 限定本次开机。
sudo journalctl -u wg-quick@wg0 -b -n 50 --no-pager
B. 握手、路由与监听
bash
# 查看 Peer、最近握手时间、Endpoint 和收发量。
sudo wg show wg0
# 查看接口地址,以及到小主机实际选择的路由。
ip -4 addr show wg0
ip -4 route get 10.10.0.2
# 查看 IPv4 转发状态。
sysctl net.ipv4.ip_forward
# 查看 UDP 51820 的监听;-l 监听,-u UDP,-n 数字显示。
sudo ss -lun 'sport = :51820'
# 查看 TCP 服务监听地址及进程,区分回环、隧道地址和全地址监听。
sudo ss -lntp
C. 防火墙与连接测试
bash
# status 查看规则;show added 查看通过 UFW 添加的规则命令,包括 route 规则。
sudo ufw status verbose
sudo ufw show added
# 在 Linux 检查云主机连通性。
ping -c 3 10.10.0.1
Windows PowerShell:
powershell
# 查看指定目标的 TCP 端口是否可达,不验证数据库账号等应用认证。
Test-NetConnection 10.10.0.1 -Port 3306
# 查看 IPv4 路由,排查 VPN 或局域网网段冲突。
route print -4
GitHub 登录
Gitee 登录
QQ 登录
请围绕文章内容交流,勿发布广告、违法信息或他人隐私。