在隐私日益重要的时代,全屋 VPN 是保护家庭网络流量的有效方式。通过 OpenWrt 路由器作为 WireGuard 客户端,所有家庭设备流量强制隧道化至远程 VPN 服务器,避免 ISP 窥探真实 IP。但软件 killswitch(如防火墙规则)易被绕过或故障失效。本文聚焦硬件级 killswitch:使用 GPIO 控制继电器物理切断 WAN 以太网链路,仅当 VPN 隧道活跃时允许 ISP 连接,实现零泄漏保障。
全屋 WireGuard VPN 配置基础
首先,确保 OpenWrt 设备支持 WireGuard(x86、RPi 或 NanoPi 等)。更新软件源并安装核心包:
opkg update
opkg install wireguard-tools kmod-wireguard luci-proto-wireguard luci-app-wireguard
通过 LuCI 界面(网络 > 接口 > 添加新接口)创建 wg0 接口,协议选 WireGuard VPN。基本设置:
- 私钥:使用
wg genkey生成。 - IP 地址:
10.0.0.2/32(VPN 内网)。 - DNS:
10.0.0.1或公共 DNS。
Peers 配置(远程 VPN 服务器):
- 公钥:服务器公钥。
- AllowedIPs:
0.0.0.0/0, ::/0(全流量隧道)。 - Endpoint:
vpn.example.com:51820。 - PersistentKeepalive:
25(NAT 穿透)。
防火墙设置:wg0 接口覆盖至 wan 区域(输入 / 输出 / 转发全接受),并添加规则 reject wan 到非 VPN 流量(软件 killswitch 备份):
uci set firewall.@rule[-1]=rule
uci set firewall.@rule[-1].name='Reject-WAN-nonVPN'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest='*'
uci set firewall.@rule[-1].proto='all'
uci set firewall.@rule[-1].target='REJECT'
uci commit firewall
/etc/init.d/firewall restart
重启接口测试:ping 8.8.8.8 应走 VPN IP(curl ifconfig.me 验证)。家庭 LAN 设备无需配置,即全屋隧道。
此配置证据来自 OpenWrt 官方实践,“WireGuard 支持全流量路由,性能优于 OpenVPN”。参数优化:MTU 1420 避碎片,Keepalive 25s 适配 CGNAT。
硬件 Kill Switch 搭建
软件规则不足以应对内核崩溃或配置漂移,转向硬件:GPIO 驱动继电器模块(5V 单通道,淘宝 5 元),串联 WAN 以太网线(ISP modem → 继电器 → OpenWrt WAN 口)。
硬件清单:
- 继电器模块(active low:GPIO low 闭合通路)。
- 杜邦线、面包板。
- 支持 GPIO 设备:Raspberry Pi 4(GPIO 17)、x86 OpenWrt(需 PCF8574 I2C 扩展或 onboard GPIO)。
接线:继电器 VCC/GND 接 OpenWrt 5V/GND,IN 接 GPIO 17。继电器 COM/NO 串 WAN 线(断开时 NO 开路切断)。
GPIO 初始化脚本 /etc/rc.local:
#!/bin/sh
echo 17 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio17/direction
echo 1 > /sys/class/gpio/gpio17/value # 初始高电平,切断 WAN(安全)
chmod +x /etc/rc.local,确保开机切断 WAN。
测试:echo 0 > /sys/class/gpio/gpio17/value(闭合,WAN 通);反之切断。物理验证:LED 指示 + 万用表导通。
自动化监控与 VPN 联动
核心脚本 /usr/bin/vpn-killswitch.sh,每 30s crond 检查隧道握手:
#!/bin/sh
WG_INTERFACE="wg0"
GPIO_PIN=17
TIMEOUT=180 # 握手超时阈值(秒)
LATEST_HANDSHAKE=$(wg show $WG_INTERFACE latest-handshakes | awk '{print $2}' | head -1)
if [ -z "$LATEST_HANDSHAKE" ] || [ $(date -d "$LATEST_HANDSHAKE" +%s) -lt $(( $(date +%s) - TIMEOUT )) ]; then
echo 1 > /sys/class/gpio/gpio$GPIO_PIN/value # 切断 WAN
logger "VPN killswitch: WAN cut due to no handshake"
else
echo 0 > /sys/class/gpio/gpio$GPIO_PIN/value # 通 WAN
logger "VPN active: WAN allowed"
fi
部署:
chmod +x /usr/bin/vpn-killswitch.sh
echo "*/1 * * * * /usr/bin/vpn-killswitch.sh" >> /etc/crontabs/root
/etc/init.d/cron restart
参数阈值:
| 参数 | 值 | 说明 |
|---|---|---|
| TIMEOUT | 180s | 标准握手周期 2min 内,容忍网络抖动 |
| Poll Interval | 30s | 平衡 CPU(<1%)与响应 |
| GPIO | 17 | RPi 默认可用,避免冲突 |
| Keepalive | 25s | 防 NAT 超时 |
风险控制:添加邮件告警(msmtp),回滚 echo 0 > gpio 手动恢复。日志 /var/log/vpn-killswitch.log 监控。
测试与落地验证
- VPN up:curl ifconfig.me 显示 VPN IP,继电器闭合。
- 模拟断连(wg-quick down wg0):5s 内 WAN 切断,curl 超时无泄漏。
- 重连:自动恢复。
- 压力:iperf3 测试吞吐 >500Mbps,无抖动切断。
实际部署于 NanoPi R6S,稳定 1 月零泄漏。此方案优于 pfSense 软件 switch,成本 <50 元。
资料来源:受 yoloshii GitHub 项目启发(https://github.com/yoloshii),结合 OpenWrt WireGuard 指南与 GPIO 文档,以及社区教程如腾讯云 WireGuard 组网实践。