VPN怎么又双叒叕掉了,我直接换方案 - WireGuard 部署实录
背景
上次费了好大劲修的 VPN,效果还是不太行 😮💨
每次都是 rekey,重协商失败,没招了。
你这样不如写个后台脚本,定时重连吧,你这怎么只有第一次连接的时候才会成功呀,重协商就失败了呀,很难绷啊
估计是这玩意本身的 bug,我反正修不好。但是我总得交差呀,公司的人用这个,没法用啊。
WARNING
既然修不好,那就换。在不影响之前功能的前提下,新搞一个东西。
方案选型:WireGuard
我搞的东西叫 WireGuard。
不是,这玩意
yum能下载kmod-wireguard吗?我曹威
很显然:
- CentOS 7 内核 3.10 不原生支持 WireGuard
- ELRepo 已不再提供可直接安装的
kmod-wireguard
因此使用 wireguard-linux-compat 编译当前内核的外置模块。
1. 安装依赖
确认当前内核版本,并安装 WireGuard 工具与编译依赖:
uname -r
yum install -y wireguard-tools gcc make perl elfutils-libelf-devel \
kernel-devel-$(uname -r)
2. 编译并加载内核模块
运行外置模块安装脚本:
chmod 700 /root/install-wireguard-external-module.sh
bash /root/install-wireguard-external-module.sh
验证内核模块已加载:
lsmod | grep wireguard
modinfo wireguard | head -n 5
成功示例:
wireguard 193586 0
ip6_udp_tunnel 12755 1 wireguard
udp_tunnel 14423 1 wireguard
3. 服务端配置
DANGER
文件位置:/etc/wireguard/wg0.conf。私钥必须由服务器本地生成,权限为 600;不得在聊天、工单或文档中公开。
生成密钥:
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
chmod 600 /etc/wireguard/server.key /etc/wireguard/wg0.conf
单用户示例(公钥替换为实际值):
[Interface]
Address = <隧道服务器地址>
ListenPort = 51820
PrivateKey = <服务器私钥>
SaveConfig = false
PostUp = iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT
PostUp = iptables -I INPUT 1 -i %i -s 10.66.0.0/24 -j ACCEPT
PostUp = iptables -I FORWARD 1 -i %i -o eth0 -s 10.66.0.0/24 -d <目标内网IP>/32 -j ACCEPT
PostUp = iptables -I FORWARD 1 -i eth0 -o %i -d 10.66.0.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
PostUp = iptables -t nat -I POSTROUTING 1 -s 10.66.0.0/24 -d <目标内网IP>/32 -o eth0 -j MASQUERADE
PostDown = iptables -D INPUT -p udp --dport 51820 -j ACCEPT
PostDown = iptables -D INPUT -i %i -s 10.66.0.0/24 -j ACCEPT
PostDown = iptables -D FORWARD -i %i -o eth0 -s 10.66.0.0/24 -d <目标内网IP>/32 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o %i -d 10.66.0.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -s 10.66.0.0/24 -d <目标内网IP>/32 -o eth0 -j MASQUERADE
[Peer]
PublicKey = <Windows 用户 1 公钥>
AllowedIPs = <用户1 隧道地址>
WARNING
规则必须使用 -I 插入链首。若使用 -A 追加到 firewalld 已有 REJECT/DROP 规则之后,UDP 51820 虽可被 tcpdump 捕获,但可能无法进入 WireGuard socket,表现为没有 latest handshake。
4. Windows 客户端配置
安装官方 WireGuard 客户端,创建空隧道。Windows 私钥仅保存在本机。
[Interface]
PrivateKey = <Windows 自动生成的私钥>
Address = <用户隧道地址>
[Peer]
PublicKey = <服务器 /etc/wireguard/server.pub 内容>
Endpoint = <服务器公网IP>:51820
AllowedIPs = <目标内网IP>/32, <其他目标网段>
PersistentKeepalive = 25
| 参数 | 说明 |
|---|---|
PersistentKeepalive = 25 | 用于维持客户端位于 NAT 后的 UDP 映射 |
AllowedIPs | 仅下发目标的主机路由,网页、外网应用和 DNS 继续走本地网络 |
TIP
每增加一位用户,分配新的隧道地址与新的独立公钥。
这是一个很简单的配置,具体内容就是为远程主机分配相应的 IP,私钥服务器存储,很基础的内容,不再展开了。
5. 多用户管理
每位用户一个 [Peer] 块。服务端的 AllowedIPs 只填写该用户的隧道地址;不要将多个用户分配为同一地址。
[Peer]
# 用户 2
PublicKey = <用户 2 Windows 公钥>
AllowedIPs = 10.66.0.3/32
[Peer]
# 用户 3
PublicKey = <用户 3 Windows 公钥>
AllowedIPs = 10.66.0.4/32
日常新增或撤销用户无需重启服务。编辑完 /etc/wireguard/wg0.conf 后,使用以下命令将 peer 实时同步到运行中的 wg0:
wg syncconf wg0 <(wg-quick strip wg0)
wg show
TIP
wg syncconf 不会断开现有 WireGuard 用户;新增 peer 后应在 wg show 中看到其 public key,连接后出现 latest handshake。
WARNING
撤销用户时,先删除对应 [Peer] 块,再执行相同的 wg syncconf 命令;同时从用户设备移除该隧道配置。
systemctl restart wg-quick@wg0 也能应用配置,但会短暂中断所有用户,只用于接口修复或维护窗口。
提示一下,当使用 WireGuard 客户端新建隧道的时候就可以看见客户端私钥。
总结
已经严肃使用一天,未发生掉线情况。
我曹威终于好了 🎉
TIP
回头看,WireGuard 相比之前的方案:配置简洁、内核态运行、基于 UDP 抗 NAT 抖动,关键是没有 rekey 死循环。
