WireGuard:十分钟搭一个自己的 VPN

出门在外想连家里的机器、或者想在不可信的 WiFi 上安全地走自己的出口——WireGuard 是现在最省事的选择。

一、先想清楚:VPN 还是组网

需求方案
访问家里/公司的内网机器Tailscale / ZeroTier 更简单
让所有流量走自己的服务器出口WireGuard
两台服务器之间组内网WireGuard
不想装客户端、临时用SSH 隧道 / SOCKS 代理

WireGuard 本身非常轻(内核模块,几千行代码),配置也就十来行。它比 OpenVPN / IPSec 简单一个数量级。

二、安装

bash
sudo apt install -y wireguard

# 确认内核模块
sudo modprobe wireguard
lsmod | grep wireguard

三、生成密钥

WireGuard 用公私钥认证,每端一对:

bash
cd /etc/wireguard
umask 077                      # 重要:私钥权限

# 服务端
wg genkey | tee server.key | wg pubkey > server.pub

# 客户端(几个客户端就生成几对)
wg genkey | tee phone.key | wg pubkey > phone.pub

cat server.key   # 私钥,绝不能泄露
cat server.pub   # 公钥,配到对端

四、服务端配置

nginx
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <server.key 的内容>
Address = 10.8.0.1/24
ListenPort = 51820
SaveConfig = true

# 开启 IP 转发 + NAT(让客户端能访问公网/内网)
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

# 客户端 1
[Peer]
PublicKey = <phone.pub 的内容>
AllowedIPs = 10.8.0.2/32

# 客户端 2
[Peer]
PublicKey = <laptop.pub 的内容>
AllowedIPs = 10.8.0.3/32

系统层开启转发:

bash
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wg.conf
sudo sysctl --system

启动:

bash
sudo systemctl enable --now wg-quick@wg0
sudo wg show

防火墙放行 UDP 端口:

bash
sudo ufw allow 51820/udp
# 云服务器安全组也要放行 UDP 51820

五、客户端配置

nginx
# phone.conf
[Interface]
PrivateKey = <phone.key 的内容>
Address = 10.8.0.2/24
DNS = 1.1.1.1, 223.5.5.5

[Peer]
PublicKey = <server.pub 的内容>
Endpoint = your-server-ip:51820
AllowedIPs = 0.0.0.0/0, ::/0        # 全部流量走 VPN
PersistentKeepalive = 25

AllowedIPs 的区别(重要)

配置效果
0.0.0.0/0所有流量走 VPN(当作出国/安全出口用)
10.8.0.0/24只有访问内网段才走 VPN(分流)

服务端那侧的 AllowedIPs 含义不同,是路由 + 访问控制10.8.0.2/32 表示「这个 peer 的流量来自这个地址」。

六、手机端

最方便的方式是生成二维码:

bash
sudo apt install -y qrencode
qrencode -t ansiutf8 < phone.conf
# 用 App 扫即可

App:iOS / Android 都搜「WireGuard」,官方出品。

七、管理客户端

bash
# 运行时查看(不重启服务)
sudo wg show

# 查看握手时间、流量
sudo wg show wg0 transfer

# 临时禁用某个 peer(不删配置)
sudo wg set wg0 peer <pubkey> remove

# 加了 SaveConfig=true 时,wg set 的改动会写回配置文件
# 改配置文件后重启更安全
sudo systemctl restart wg-quick@wg0

八、排错

现象排查
握手一直不成功密钥配错 / 端口没放行 / Endpoint 写错
连上但上不了网服务端没开 ip_forward 或 NAT
能 ping 通内网但打不开网页MTU 问题,改小 MTU
连接频繁断开客户端加 PersistentKeepalive = 25
bash
# 看握手有没有成功
sudo wg show
# latest handshake: 12 seconds ago  ← 有就说明通了

# 看有没有收到包
sudo wg show wg0 | grep transfer
# transfer: 1.20 MiB received, 3.45 MiB sent

# MTU 调整(某些网络下需要)
# 在 [Interface] 里加 MTU = 1280

# 抓包确认 UDP 有没有到
sudo tcpdump -i eth0 -n udp port 51820

九、安全注意

  1. 私钥权限 600umask 077 生成);
  2. 不要为了省事把一份配置发给多个人用——每人一对密钥,方便单独吊销;
  3. 端口可以改成非标准,减少扫描噪音;
  4. 定期检查 wg show,看有没有不认识的 peer;
  5. 服务端配置里 AllowedIPs 要精确(/32),不要写 /24,否则路由会冲突。
bash
# 吊销某个客户端:从配置里删掉 [Peer] 段,重启
sudo systemctl restart wg-quick@wg0

十、和 Tailscale 怎么选

维度WireGuardTailscale
底层就是 WireGuard基于 WireGuard
配置手动分发密钥自动,登录即可
穿透 NAT需要公网服务器自动打洞
密钥管理自己管自动控制平面
可控性完全自控依赖第三方(可自建 Headscale)

我的用法:

  • 设备之间互访(我的笔记本 ↔ 家里的机器)→ Tailscale,零配置;
  • 需要固定出口 IP / 全部流量走自己服务器 → WireGuard。

WireGuard 的配置文件总共十几行,理解「Interface 是自己、Peer 是对端」就通了。