前言
玩 Homelab 的人迟早会面临一个问题:人在外面,怎么安全地访问家里的服务?
把每个服务都通过端口映射暴露到公网?不安全。给每个服务配 SSL + 认证?麻烦。用 TeamViewer/AnyDesk 远程桌面?治标不治本。
正确姿势:打一条 VPN 隧道回家。
本文将从零开始,带你搭建 WireGuard VPN,实现一个端口(UDP 51820)打通整个家庭内网。涵盖:
- 原生安装(适合极致性能党)
- Docker 部署 wg-easy(适合追求开箱即用)
- 多客户端管理、Split Tunneling、Site-to-Site 组网
- 常见踩坑与排查
1. 为什么选 WireGuard?
WireGuard 于 2020 年并入 Linux 5.6 内核主线,代码量仅约 4,000 行(OpenVPN 约 100,000 行,IPSec 约 400,000 行)。短小精悍意味着攻击面小、审计容易。
| 特性 | WireGuard | OpenVPN | IPSec/IKEv2 |
|---|
| 代码量 | ~4,000 行 | ~100,000 行 | ~400,000 行 |
| 内核集成 | ✅ Linux 5.6+ 原生 | ❌ tun/tap 用户态 | ✅ XFRM |
| 加密套件 | ChaCha20 + Poly1305 | 可选(OpenSSL) | 可选 |
| 密钥交换 | Curve25519 (Noise) | X.509 证书 | IKEv2 |
| 配置复杂度 | 🏆 极简(一个 ini 文件) | ❌ 复杂(证书体系) | ❌ 复杂 |
| 漫游支持 | ✅ 原生(无状态 UDP) | ⚠️ 需重连 | ⚠️ 需重连 |
| 延迟增量 | ~0.1ms | ~5-10ms | ~2-5ms |
| 吞吐量 | 🏆 接近线速 | ⚠️ 用户态瓶颈 | ✅ 高 |
结论:对于 Homelab 远程访问场景,WireGuard 是压倒性的首选。
2. 架构概览
1
2
3
4
5
6
7
8
9
10
11
| 📱 手机/笔记本 (10.6.0.x)
│ WireGuard 加密隧道
│ UDP 51820
▼
🌐 公网 → your-ddns.com:51820
│ 路由器端口转发
▼
🖥️ WG Server (内网 192.168.1.x, WG IP 10.6.0.1)
│ 解密 → 转发到内网
▼
🏠 内网服务: 192.168.1.0/24 (NAS, PVE, HA, ... )
|
核心原理:
- WireGuard 使用 Cryptokey Routing:每个 peer 的公钥对应一组允许的 IP 范围
- 服务端开启 IP 转发 + NAT,将 VPN 流量桥接到物理内网
- 客户端只需配置 peer 的公钥、endpoint 和 AllowedIPs
3. 方案一:原生部署(Debian/Ubuntu)
适用场景:你对性能敏感,愿意手动管理配置。
3.1 安装 WireGuard
1
2
3
4
5
6
7
8
9
10
11
12
| # 更新系统并安装
sudo apt update && sudo apt upgrade -y
sudo apt install wireguard -y
# 确认内核模块加载
sudo modprobe wireguard
lsmod | grep wireguard
# 输出: wireguard xxxxx 0
# 开启 IP 转发(关键!否则 VPN 流量无法到达内网)
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
|
3.2 生成密钥对
1
2
3
4
5
6
7
8
9
10
11
| # 创建密钥目录
sudo mkdir -p /etc/wireguard/keys && sudo chmod 700 /etc/wireguard/keys
# 服务端密钥
wg genkey | sudo tee /etc/wireguard/keys/server_private.key | wg pubkey | sudo tee /etc/wireguard/keys/server_public.key
# 客户端密钥(每新增一个客户端就生成一对)
wg genkey | sudo tee /etc/wireguard/keys/phone_private.key | wg pubkey | sudo tee /etc/wireguard/keys/phone_public.key
# 保护私钥
sudo chmod 600 /etc/wireguard/keys/*_private.key
|
3.3 服务端配置 /etc/wireguard/wg0.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| [Interface]
Address = 10.6.0.1/24
ListenPort = 51820
PrivateKey = <填入 server_private.key 的内容>
# NAT 规则 — 将 wg0 流量转发到物理网卡
# 注意:eth0 改为你的实际公网/内网出口网卡名
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# DNS(可选,推送给客户端)
DNS = 192.168.1.1
# 客户端 1:手机
[Peer]
PublicKey = <填入 phone_public.key 的内容>
AllowedIPs = 10.6.0.2/32
# 客户端 2:笔记本
[Peer]
PublicKey = <填入 laptop_public.key 的内容>
AllowedIPs = 10.6.0.3/32
|
关键说明:AllowedIPs 决定了该 peer 能路由哪些 IP。设为 10.6.0.x/32 表示该客户端只能使用这个 VPN IP。如果要让该 peer 访问内网(192.168.1.0/24),客户端侧设置即可(见下文)。
3.4 启动服务
1
2
3
4
5
6
7
8
| # 设置开机自启
sudo systemctl enable wg-quick@wg0
# 启动
sudo systemctl start wg-quick@wg0
# 查看状态
sudo wg show
|
4. 方案二:Docker 部署 wg-easy(推荐)
wg-easy 提供了 Web UI,支持扫码添加客户端、一键生成配置,极大降低管理成本。
4.1 docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| version: "3.8"
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
environment:
# 必填:公网 IP 或 DDNS 域名
- WG_HOST=your-ddns.duckdns.org
# Web UI 密码(bcrypt hash)
- PASSWORD_HASH=$$2a$$12$$...your_bcrypt_hash...
# 可选配置
- WG_PORT=51820
- WG_DEFAULT_ADDRESS=10.6.0.x
- WG_DEFAULT_DNS=192.168.1.1
- WG_ALLOWED_IPS=192.168.1.0/24,10.6.0.0/24
- WG_PERSISTENT_KEEPALIVE=25
# 语言
- LANG=zh
volumes:
- ./wg-easy:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp" # Web UI
|
生成 bcrypt 密码哈希:
1
| docker run --rm ghcr.io/wg-easy/wg-easy:15 wgpw "你的密码"
|
4.2 启动与使用
1
2
3
4
| docker compose up -d
# 查看日志确认启动
docker compose logs -f
|
然后访问 http://<服务器IP>:51821,登录后即可:
- 点击「新建客户端」生成配置
- 扫码或下载
.conf 文件导入手机/电脑 - 在 UI 中启用/禁用客户端
优势:无需手动编辑 wg0.conf、无需执行 wg 命令、客户端增减在 Web UI 一点即可。
5. 客户端配置
5.1 手机(iOS/Android)
- 安装 WireGuard App
- 扫描 wg-easy 生成的二维码或导入
.conf - 点击连接
典型客户端配置文件:
1
2
3
4
5
6
7
8
9
10
11
| [Interface]
PrivateKey = <客户端私钥>
Address = 10.6.0.2/24
DNS = 192.168.1.1
[Peer]
PublicKey = <服务端公钥>
PresharedKey = <预共享密钥,可选>
Endpoint = your-ddns.duckdns.org:51820
AllowedIPs = 192.168.1.0/24, 10.6.0.0/24
PersistentKeepalive = 25
|
AllowedIPs 的值决定了哪些流量走隧道:
192.168.1.0/24, 10.6.0.0/24 → 仅内网流量走 VPN(Split Tunneling,推荐)0.0.0.0/0 → 全部流量走 VPN(类似全局代理)
5.2 桌面端(Windows/macOS/Linux)
1
2
3
4
5
6
7
8
9
| # Linux Desktop
sudo apt install wireguard -y
# 导入配置
sudo cp phone.conf /etc/wireguard/wg0.conf
sudo systemctl start wg-quick@wg0
# 查看连接状态
sudo wg show
|
6. 高级配置
6.1 Split Tunneling:只让内网流量走 VPN
默认如果客户端 AllowedIPs = 0.0.0.0/0,所有流量(包含访问百度、Google)都会经过家里的网络。大多数场景只需要访问内网服务。
正确做法:
1
2
| # 客户端配置只路由内网网段
AllowedIPs = 192.168.1.0/24, 10.6.0.0/24
|
这样你访问公网走本地 WiFi/5G,访问内网(如 NAS 的 192.168.1.100:5000)走 WireGuard 隧道。速度更快、延迟更低、不占用家庭宽带上行。
6.2 DNS 泄漏防护
如果你需要让 DNS 查询也走隧道(避免暴露浏览记录),在客户端配置中指定 DNS:
1
2
3
4
5
| [Interface]
DNS = 192.168.1.1 # 使用家里的 DNS
# 或者用公共 DNS over WG
# DNS = 1.1.1.1, 8.8.8.8
|
6.3 Site-to-Site:连接两个局域网
假设你有一台云服务器(阿里云/腾讯云),想让它能访问家里的内网设备。
云的 WG 配置(作为客户端加入你家网络):
1
2
3
4
5
6
7
8
9
| [Interface]
Address = 10.6.0.10/24
PrivateKey = <云主机私钥>
[Peer]
PublicKey = <家里的服务端公钥>
Endpoint = home.your-ddns.com:51820
AllowedIPs = 192.168.1.0/24
PersistentKeepalive = 25
|
云主机连上后,就能直接用 ssh user@192.168.1.100 访问家里的机器了。
6.4 PersistentKeepalive 的作用
PersistentKeepalive = 25 表示每 25 秒发一个空包维持 NAT 会话。这对于:
- 运营商 NAT 后面的客户端(如手机 4G/5G)
- 长时间不活跃的连接
非常关键:不加这个参数,NAT 映射超时后服务端无法主动联系客户端,直到客户端主动发包。
7. 踩坑记录
❌ 坑 1:能连上但 ping 不通内网
现象:wg show 显示握手成功,但 ping 192.168.1.1 不通。
排查:
1
2
3
4
5
6
7
8
9
10
11
| # 1. 检查 IP 转发是否开启
sysctl net.ipv4.ip_forward
# 应输出: net.ipv4.ip_forward = 1
# 2. 检查 iptables NAT 规则
sudo iptables -t nat -L POSTROUTING -v
# 确认 MASQUERADE 规则存在
# 3. 检查防火墙
sudo ufw status
# 确保 UDP 51820 已放行
|
修复:
1
2
3
4
5
6
7
8
| # 如果转发没开
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
# 如果 NAT 规则缺失,手动添加
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT
|
❌ 坑 2:Docker 部署后宿主机自身无法访问 VPN 内网
现象:外部手机能正常访问内网,宿主机上却 ping 不通客户端的 VPN IP (10.6.0.x)。
原因:Docker 的 bridge 网络与宿主机网络栈隔离,宿主机默认没有到 10.6.0.0/24 的路由。
修复:在宿主机上添加静态路由:
1
| sudo ip route add 10.6.0.0/24 via <wg-easy容器IP> dev docker0
|
更优雅的方式是把 wg-easy 的网络模式改为 host(但会失去容器网络隔离):
1
2
| network_mode: host
# 使用 host 网络后不再需要 ports 映射
|
❌ 坑 3:国内部分运营商 UDP QoS 严重限速
现象:白天 WireGuard 速度正常,晚高峰降到几百 Kbps。
原因:部分运营商(尤其是移动 4G/5G)对 UDP 流量进行深度限速。
缓解方案:
- 换端口:不用默认的 51820,改用 443(伪装成 HTTPS 流量)
- udp2raw:将 UDP 包封装成 TCP(伪装成 TCP 连接),成本是额外 ~5% 开销
- 换运营商:电信/联通对 UDP 限速相对宽松
1
2
3
4
5
6
7
| # 更改监听端口为 443
# wg-easy docker-compose:
- WG_PORT=443
ports:
- "443:443/udp"
# 路由器端口转发也改为 443
|
❌ 坑 4:DDNS 域名解析 IP 更新延迟
现象:公网 IP 变化后,客户端连不上。
修复:WireGuard 的 DNS 解析只在启动时进行一次。可以写一个脚本监控 endpoint 的 IP 变化并重启接口:
1
2
3
4
5
6
7
8
9
| #!/bin/bash
# wg-resolve.sh — 每 5 分钟检查 DNS 并重连
while true; do
wg show wg0 endpoints | while read -r line; do
# 如果 endpoint 不可达,重连
:
done
sleep 300
done
|
更简单的方法:用 wg syncconf + systemd timer 每 5 分钟刷新一次配置。
8. 与 Tailscale / ZeroTier 的对比
| 维度 | WireGuard 自建 | Tailscale | ZeroTier |
|---|
| 控制面 | 自管 | Tailscale 协调服务器 | ZeroTier 根服务器 |
| 打洞能力 | ❌ 无(需公网 IP 或端口转发) | ✅ NAT 穿透优秀 | ✅ 支持 UDP 打洞 |
| 配置复杂度 | ⚠️ 中等 | 🏆 极简 | 🏆 简单 |
| 成本 | 🏆 免费 | 免费(3 用户,100 设备) | 免费(25 节点) |
| 依赖外部服务 | 🏆 无 | ✅ 需要 | ✅ 需要 |
| 性能 | 🏆 最高(直连) | ⚠️ DERP 中继有瓶颈 | ⚠️ 中继有瓶颈 |
| 适合场景 | 有公网 IP & 追求控制权 | 复杂 NAT 环境 & 省心 | 大量节点 & SDN 玩法 |
结论:
- 有公网 IP → WireGuard 自建,性能最高,零外部依赖
- 没公网 IP / 对等网络复杂 → Tailscale,开箱即用
- 大量节点 + 需要 SDN 拓扑 → ZeroTier
9. 安全加固清单
部署完成后的安全检查:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # 1. 确认私钥权限正确
ls -la /etc/wireguard/keys/
# 私钥应为 600 (rw-------)
# 2. 确认只开放了 UDP 51820(不要开放 TCP 51820 除非需要 wg-easy UI)
sudo ss -tuln | grep 51820
# 3. 确认 iptables 规则正确
sudo iptables -L FORWARD -v
sudo iptables -t nat -L POSTROUTING -v
# 4. 检查 wg 接口状态
sudo wg show
# 确认只有预期的 peer 列表
# 5. 禁用不需要的客户端
# wg-easy: 在 Web UI 中禁用
# 原生: 注释掉 /etc/wireguard/wg0.conf 中对应 [Peer] 段后执行
sudo wg syncconf wg0 <(wg-quick strip wg0)
|
总结
| 维度 | 结论 |
|---|
| ✅ 推荐方案 | Docker wg-easy 用于日常管理,原生用于性能极致场景 |
| ✅ 关键配置 | net.ipv4.ip_forward=1 + MASQUERADE NAT 规则 |
| ✅ 生产建议 | 开 Split Tunneling + PersistentKeepalive + 定期检查 peer 列表 |
| ⚠️ 注意 | 国内运营商 UDP QoS 问题,必要时换 443 端口或用 udp2raw |
| 🔗 关联阅读 | Traefik 反向代理 + SSL 指南 |
一句话:花半小时搭好 WireGuard,你就获得了随时随地的家庭内网安全入口——这是 Homelab 最值得的投资之一。