前言

本文记录了将一台搭载Debian系统的R2S设备配置为高性能旁路网关的过程。最终目标是实现一个可以为局域网内所有设备提供WireGuard VPN服务的透明网关,同时支持IPv4和IPv6,并具备智能DNS分流功能。

最终方案的核心组件包括:

  • Debian 12: 作为主操作系统。
  • WireGuard: 用于建立VPN连接。
  • uog: 一个流量混淆工具,用于将WireGuard的UDP流量伪装成其他协议(本文为HTTPS),以适应复杂的网络环境。
  • dnsproxy: AdGuard出品的高性能DNS代理,用于实现DNS-over-HTTPS (DoH)以及基于域名的DNS分流。
  • iptables/ip6tables: 用于配置网络地址转换(NAT),实现VPN共享。

准备工作

1. 安装系统与基础软件

首先,为R2S安装最新版本的Debian系统。您可以从FriendlyELEC的官方Wiki获取镜像和相关说明:

安装过程略过,系统启动后,请执行以下操作:

# 更新系统并安装必要工具
sudo apt update && sudo apt upgrade -y
sudo apt install -y zsh wireguard-tools dnsutils

# (可选) 更换为您喜欢的shell
chsh -s /bin/zsh

2. 启用IP转发

作为旁路网关,设备需要能够转发网络包。编辑 /etc/sysctl.conf 文件:

sudo vim /etc/sysctl.conf

找到并取消以下两行的注释(如果它们被注释了的话),确保值为 1:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

保存文件后,应用设置:

sudo sysctl -p

核心服务配置

我们将使用 systemd 来管理 dnsproxy 和 uog 这两个核心服务,以确保它们能开机自启并保持稳定运行。建议将二进制文件存放在 /home/pi/bin 目录下。

mkdir -p /home/pi/bin

1. 配置 dnsproxy

dnsproxy 负责处理所有DNS请求。它的关键任务是:

  1. 将用于 uog 连接的特定域名解析请求,转发给主路由,避免DNS污染和路由循环。
  2. 将其余所有DNS请求通过DoH发送,保护隐私。

下载 dnsproxy:

从 dnsproxy的GitHub Releases页面 下载最新的 linux-arm64 版本,解压后将 dnsproxy 二进制文件放入 /home/pi/bin。

创建 systemd 服务:

创建 /etc/systemd/system/dnsproxy.service 文件:

sudo vim /etc/systemd/system/dnsproxy.service

写入以下内容:

[Unit]
Description=dnsproxy
After=network-online.target network.target
Wants=network-online.target

[Service]
Restart=always
ExecStart=/home/pi/bin/dnsproxy -u "[/*.your_domain.com/]192.168.31.1:53" -u https://dns0.eu/dns-query -u https://open.dns0.eu/dns-query --http3 --cache --cache-min-ttl=600 --edns --edns-addr=<your_public_ip_for_cdn>
ExecReload=/bin/kill $MAINPID
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=5s
PrivateTmp=true
PrivateDevices=true
ProtectHome=false
ProtectSystem=full

[Install]
WantedBy=multi-user.target

配置说明:

  • 请将 your_domain.com 替换为您 uog 服务实际使用的域名。
  • 192.168.31.1 是我局域网的主路由地址,请根据您的实际情况修改。
  • <your_public_ip_for_cdn> 是一个用于优化CDN解析的公网IP地址,您可以填写一个您所在地区的IP,或者直接移除 --edns 和 --edns-addr 参数。

启动 dnsproxy:

sudo systemctl daemon-reload
sudo systemctl enable dnsproxy --now

2. 配置 uog

uog 负责将WireGuard的流量伪装后转发到真实的VPN服务器。

下载 uog:

从 uog的GitHub Releases页面 下载最新的 linux-arm64 版本,将 uog 二进制文件放入 /home/pi/bin。

创建启动脚本:

为了方便管理,我们创建一个包装脚本 /home/pi/uog.sh:

vim /home/pi/uog.sh

内容如下:

#!/bin/bash
/home/pi/bin/uog 0.0.0.0:2928 https://uog.your_domain.com:443 <your_password>
  • 0.0.0.0:2928: uog 的本地监听地址和端口,WireGuard将连接到这里。
  • https://uog.your_domain.com:443: uog 远端服务器的地址,请替换为您的实际地址。
  • <your_password>: 连接密码。

给脚本添加执行权限:

chmod +x /home/pi/uog.sh

创建 systemd 服务:

创建 /etc/systemd/system/uog.service 文件:

sudo vim /etc/systemd/system/uog.service

写入以下内容:

[Unit]
Description=uog client
After=network-online.target network.target
Wants=network-online.target

[Service]
Restart=always
ExecStart=/home/pi/uog.sh
ExecReload=/bin/kill $MAINPID
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=5s
PrivateTmp=true
PrivateDevices=true
ProtectHome=false
ProtectSystem=full

[Install]
WantedBy=multi-user.target

启动 uog:

sudo systemctl daemon-reload
sudo systemctl enable uog --now

配置 WireGuard

这是所有配置的核心,它将所有组件串联起来。

1. 创建动态路由脚本

为了防止 uog 的流量被WireGuard错误地捕获,我们需要在WireGuard启动时,动态地为 uog 服务器的IP添加一条静态路由,让它直连主路由。

创建目录:

mkdir -p /home/pi/wg

创建 wgup.sh 脚本:

vim /home/pi/wg/wgup.sh
#!/bin/bash
STATE_FILE="/home/pi/wg/uog_server.ip"
DEST_IP=$(host -t A uog.your_domain.com | awk '/has address/ {print $4}')

if [ -n "$DEST_IP" ]; then
    # 为 uog 服务器 IP 添加静态路由,强制经由主路由
    ip route add $DEST_IP/32 via 192.168.31.1 dev eth0
    echo "$DEST_IP" > "$STATE_FILE"
    echo "Route added for uog.your_domain.com -> $DEST_IP"
fi

创建 wgdown.sh 脚本:

vim /home/pi/wg/wgdown.sh
#!/bin/bash
STATE_FILE="/home/pi/wg/uog_server.ip"

if [ -f "$STATE_FILE" ]; then
    DEST_IP=$(cat "$STATE_FILE")
    # 删除对应的静态路由
    ip route del $DEST_IP/32 via 192.168.31.1 dev eth0
    rm "$STATE_FILE"
    echo "Route removed for uog.your_domain.com -> $DEST_IP"
fi

给脚本添加执行权限:

chmod +x /home/pi/wg/wgup.sh /home/pi/wg/wgdown.sh

记得将脚本中的 uog.your_domain.com 和 192.168.31.1 替换为您的配置。

2. 编写 wg0.conf

创建 /etc/wireguard/wg0.conf 文件:

sudo vim /etc/wireguard/wg0.conf

写入以下配置:

[Interface]
PrivateKey = <your_wireguard_private_key>
Address = 192.168.9.2/24, fd00:9:28::28/128
DNS = 192.168.9.2
MTU = 1280

# IPv4 NAT and Forwarding Rules
PostUp = iptables -A FORWARD -i eth0 -j ACCEPT; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PostDown = iptables -D FORWARD -i eth0 -j ACCEPT; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE

# IPv6 NAT and Forwarding Rules
PostUp = ip6tables -A FORWARD -i eth0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PostDown = ip6tables -D FORWARD -i eth0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o wg0 -j MASQUERADE

# Dynamic route for uog server
PostUp = /home/pi/wg/wgup.sh
PostDown = /home/pi/wg/wgdown.sh

# (Optional) Add static routes for IPs that should bypass the VPN
# PostUp = ip route add 114.114.114.114/32 via 192.168.31.1 dev eth0
# PostDown = ip route del 114.114.114.114/32 via 192.168.31.1 dev eth0

[Peer]
PublicKey = <your_wireguard_server_public_key>
AllowedIPs = ::/0, 0.0.0.0/5, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/3, 160.0.0.0/5, 168.0.0.0/6, 172.0.0.0/12, 172.32.0.0/11, 172.64.0.0/10, 172.128.0.0/9, 173.0.0.0/8, 174.0.0.0/7, 176.0.0.0/4, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4, 192.168.9.0/24
Endpoint = 127.0.0.1:2928
PersistentKeepalive = 25

配置说明:

  • PrivateKey 和 PublicKey: 替换为您自己的密钥。
  • Address: R2S在VPN网络中的地址,192.168.9.2 也是它作为DNS服务器的地址。
  • DNS: 将DNS指向设备自身,由 dnsproxy 提供服务。
  • PostUp/PostDown: 核心部分,负责添加/删除防火墙NAT规则和执行动态路由脚本。eth0 是我的R2S的LAN口,请根据您的设备接口名称修改。
  • AllowedIPs: 这是实现国内/外流量分流的关键。这个列表排除了大部分私有地址,使得访问这些地址的流量直连,其余流量走VPN。您可以根据自己的需求调整。
  • Endpoint: 关键点,指向本地 uog 服务的监听地址。

防火墙规则 (iptables/ip6tables) 详解:

PostUp 中的两对 iptables 和 ip6tables 命令是实现VPN共享的关键,它们的作用如下:

  1. iptables -A FORWARD -i eth0 -j ACCEPT:

    • 这条规则被添加到 FORWARD 链中,用于处理需要被转发的数据包。
    • -i eth0 指定了规则应用于从 eth0 (LAN口) 进入的数据包。
    • -j ACCEPT 表示接受并允许这些数据包被转发。
    • 作用: 允许来自局域网设备的数据包通过R2S。
  2. iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE:

    • -t nat 表示操作 nat 表,用于网络地址转换。
    • -A POSTROUTING 规则被添加到 POSTROUTING 链,在数据包即将离开本机时进行处理。
    • -o wg0 指定了规则应用于即将从 wg0 (WireGuard接口) 出去的数据包。
    • -j MASQUERADE (伪装) 是一个特殊的NAT操作。它会自动将所有来自局域网的数据包的源IP地址,修改为 wg0 接口的IP地址。
    • 作用: 这就是“共享VPN”的核心。它将所有局域网设备的流量“伪装”成来自R2S本身,这样VPN服务器看到的就是一个客户端,而当返回流量到达R2S时,它能根据记录自动将流量转发回正确的局域网设备。

ip6tables 的命令与 iptables 完全相同,只是它们分别用于处理IPv6和IPv4的流量。而 PostDown 中的命令则使用 -D (Delete) 来移除这些规则,确保在VPN断开后网络恢复原状。

3. 启动 WireGuard

现在,可以启动WireGuard服务了:

sudo systemctl enable wg-quick@wg0 --now

检查服务状态:

sudo wg
sudo systemctl status wg-quick@wg0

如果一切正常,您应该能看到与Peer的握手信息。

验证

将局域网内的一台设备的网关和DNS服务器地址都设置为R2S的IP地址(例如 192.168.31.64,请根据您的R2S的实际LAN口IP修改)。

然后在该设备上:

  • 访问 ip.sb 或类似网站,检查公网IP是否为VPN服务器的IP。
  • 尝试访问国内网站,确认速度正常。
  • ping 局域网内其他设备,确认内网通信正常。

至此,您的R2S旁路网关就搭建完成了。