Hotdry.
systems-engineering

OpenWrt 全屋 WireGuard VPN 与硬件 Kill Switch:GPIO 以太网控制防泄漏

构建全家 WireGuard VPN 路由器,集成 GPIO 继电器硬件 kill switch,确保 VPN 断连时物理切断 WAN 防止 IP 泄漏,提供完整配置清单、脚本与阈值参数。

在隐私日益重要的时代,全屋 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 监控。

测试与落地验证

  1. VPN up:curl ifconfig.me 显示 VPN IP,继电器闭合。
  2. 模拟断连(wg-quick down wg0):5s 内 WAN 切断,curl 超时无泄漏。
  3. 重连:自动恢复。
  4. 压力:iperf3 测试吞吐 >500Mbps,无抖动切断。

实际部署于 NanoPi R6S,稳定 1 月零泄漏。此方案优于 pfSense 软件 switch,成本 <50 元。

资料来源:受 yoloshii GitHub 项目启发(https://github.com/yoloshii),结合 OpenWrt WireGuard 指南与 GPIO 文档,以及社区教程如腾讯云 WireGuard 组网实践。

查看归档