WireGuard VPN 完全指南:为你的 Homelab 构建安全高效的远程访问通道

从零搭建 WireGuard VPN 实现 Homelab 远程安全访问。覆盖原生部署、Docker (wg-easy) 部署、多客户端管理、Split Tunneling、Site-to-Site 组网及踩坑记录。

前言

玩 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 行)。短小精悍意味着攻击面小、审计容易

特性WireGuardOpenVPNIPSec/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, ... )

核心原理:

  1. WireGuard 使用 Cryptokey Routing:每个 peer 的公钥对应一组允许的 IP 范围
  2. 服务端开启 IP 转发 + NAT,将 VPN 流量桥接到物理内网
  3. 客户端只需配置 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)

  1. 安装 WireGuard App
  2. 扫描 wg-easy 生成的二维码或导入 .conf
  3. 点击连接

典型客户端配置文件:

 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 流量进行深度限速。

缓解方案

  1. 换端口:不用默认的 51820,改用 443(伪装成 HTTPS 流量)
  2. udp2raw:将 UDP 包封装成 TCP(伪装成 TCP 连接),成本是额外 ~5% 开销
  3. 换运营商:电信/联通对 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 自建TailscaleZeroTier
控制面自管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 最值得的投资之一。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计