在之前的文章中,我介绍过一种比较直接 的链式 VPN 方案:所有设备先连接到自己搭建的WireGuard 服务器,再由服务器把流量转 发到 Gluetun,最终通过上游 VPN 服务商的出口访问互联网。
这个方案的核心价值很明确:
- 所有设备只需要配置一个 WireGuard;
- 上游 VPN 只需要在服务器端维护;
- 可以把手机、电脑、平板、家用设备统一接入同一个虚拟局域网;
- 出口 IP 由商业 VPN、公司 VPN 或其他上游 VPN 提供,而不是直接暴露 VPS IP;
- 整套系统可以通过 Docker 部署,尽量不污染宿主机环境。
- 相比于直连VPN,该方案下VPN服务商能看到的只是你的VPN网关出口(你的VPS服务 器),而不是每个设备的真实 IP。
- 另外,本地的ISP等也看不到你是否是在使用主流VPN,因为他们只能知道你在连接到一个 VPN网关(你的VPS服务器),但流量最终去了哪里是未知的。
不过,随着使用场景变多,原来的结构也逐渐暴露出一些局限。最典型的问题是,对流量的 控制不够细粒度。默认情况下所有流量都必须进入上游 VPN 隧道,这对于某些服务可能会 触发风控,或者导致访问问题。而且比较难方便地进行流量工程,对不同服务采用不同的出 口策略。原先通过 iptables 和路由表的方式虽然能实现分流,但规则一多就难维护。
因此,我把原来的方案重新整理成了一个更完整的个人 VPN 网关架构。新版方案不再只是
简单的 WG-Easy + Gluetun,而是变成了:
WG-Easy + sing-box + Gluetun + AdGuard Home + config.yaml 统一配置生成
对我来说,这套方案已经不只是“VPN 套 VPN”,而是一个可以长期维护、可扩展、可观察的 个人网络出口。它既可以服务日常上网,也可以服务远程办公、家庭内网访问、开发测试和 多设备统一管理。如果你只需要最简单的全局 VPN 转发,旧版思路仍然够用。但如果你希 望在隐私、可控性、分流规则和 DNS 管理之间取得更好的平衡,新版架构会更合适。
这篇文章会介绍新版架构的设计思路、流量路径、适合的使用场景,以及相比旧方案的主要 改进。如果你对新版方案感兴趣,或者想直接部署使用,可以直接查看我在 GitHub 上的 项目仓库。
为什么需要新版架构
最早的链式 VPN 方案其实已经能解决很多问题。比如我在家里、办公室、外出网络中都可 以使用同一个 WireGuard 配置接入 VPS,然后通过 VPS 上的 Gluetun 进入上游 VPN。这 样所有设备都共享同一个上游 VPN 出口,也能避免在每台设备上反复安装、登录、配置不 同 VPN 客户端。
这个方案实际我平时使用下来也很稳定,性能也能够满足我的需求,基本上没有什么大问 题。但长时间使用下来,我还是遇到了几大痛点。
不是所有流量都适合走上游 VPN
我在实际的使用中发现,某些服务可能会因为 VPN 出口触发风控,例如账号登录、支 付、AI 服务等。比如一些我常用的流媒体平台,对于VPN有着严格的限制,有时这些流量更 适合直连。还有就是,我有时候需要网文在校园网内部的课程服务器,有时候会涉及远程桌 面,这需要比较低的延迟。这种情况下,走VPN的话即使是本国出口体验也非常不佳。
因此,我希望能有更细粒度的分流能力。比如通过规则集把我信任的一些服务的流量绕过上 游 VPN,直接从服务器侧访问互联网。这样既能保持上游 VPN 的隐私保护,又能避免一些 不必要的访问问题。以前的做法更多依赖 iptables、路由表和容器网络。能工作,但规则 一多就难维护。
在通过调研和测试后,我发现 sing-box 的 TUN 模式非常适合做这种基于规则的分流。它 支持丰富的规则类型和灵活的路由策略,可以根据域名、IP等多维度来决定流量的下一跳。 通过把 sing-box 放在 WG-Easy 和 Gluetun 之间,我就能实现更智能的流量分流,而不是 简单的全局 VPN。然后singbox能够引用远程的规则集,例如 geosite-openai、geosite-paypal 等,这样我就不需要自己维护这些规则了。还有就是, 相比于部署一个openwrt虚拟机,singbox的部署和维护都更轻量级,对docker更友好。
如此一来,我就能够更灵活地进行流量工程了。比如:默认流量,为了隐私保护需要它们走 VPN。而有些在特定区域的服务,我希望从另外的VPN 出口访问;有些服务我希望直接访 问;有些服务我希望通过特定的 VPN 出口访问。通过sing-box 的规则分流,我可以更方便 地实现这些策略。
配置需要集中管理
原先仓库中配置都是分散在conf目录下,修改网段的等配置本来就不太方便。在加入
sing-box后,Docker Compose、wg-easy hook、sing-box JSON、AdGuardHome 配
置、iptables 规则一起维护,就比较痛苦了。所以,新版方案我用config.yaml 作为单
一配置入口,再通过模板生成 runtime 文件。
每次修改配置后,直接运行生成up.sh脚本就能把所有相关配置文件更新到位,避免了“改
了这个忘了改那个”的问题。
更完善的网络监控
原来的方案主要依赖日志来观察网络状态。我有时候像看一下当前有哪些设备现在连接了 WireGuard,这些设备都会访问什么服务,有没有异常流量等。在原先的方案里,这些信息 都需要自己在容器里查看日志,或者额外安装一些监控工具。新版方案通过singbox提供的 API接口,可以配合MetaCubeXD等工具来实时查看流量分布、规则命中、上游访问等信息, 提升了可观测性。
因此,新版架构的目标不是单纯“再套一层 VPN”,而是构建一个更像家庭或个人使用的可控 网络出口。
新版方案的组件
新版方案主要由四个核心容器组成。
WG-Easy:WireGuard 接入层
WG-Easy 仍然负责最基础也最重要的部分:提供 WireGuard 服务端和 Web 管理界面。所有 手机、电脑、平板、服务器都作为 WireGuard 客户端连接到 WG-Easy。用户可以通过 WG-Easy 的 Web UI 创建 peer、下载配置文件或扫码导入手机端。
在新版架构中,WG-Easy 不再只是把流量直接交给 Gluetun,而是通过 hook 和 policy routing 把客户端流量导入更复杂的网关路径。
AdGuard Home:统一 DNS 与过滤层
AdGuard Home 负责 DNS 解析、广告过滤、跟踪域名拦截和 DNS 查询日志。
新版架构中,来自 WireGuard 客户端的普通 DNS 请求会被限制到 AdGuard Home。也就是
说,客户端不能随便把 DNS 发到 8.8.8.8、1.1.1.1 或其他外部 DNS 服务器。
这样做的好处是:
- 可以集中设置上游 DNS;
- 可以统一管理过滤列表;
- 可以查看客户端 DNS 查询;
- 可以降低 DNS 泄露风险;
- 可以避免每台设备单独配置过滤软件。
当然,这并不等于可以完全阻止所有形式的 DNS 绕过。比如 DoH、DoT 或某些应用内置解 析仍然需要额外策略处理。但对于普通 UDP/TCP 53 DNS 请求,网关可以做到统一收口。
sing-box:规则分流层
sing-box 是新版架构中最关键的变化。
它通过 TUN inbound 接收 WG-Easy 转发过来的流量,然后根据规则决定下一跳:
- 命中
bypass_rule_sets的流量直接出站; - 私有 IP 流量直接出站,避免误送进上游 VPN;
- 其他默认流量打上 routing mark,交给 Linux policy routing,再进入 Gluetun;
- 规则集可以使用远程
.srs文件,例如 geosite-openai、geosite-paypal 等。
如果你看对应的singbox的配置文件,会发现一个比较奇怪的点:sing-box 里的 gluetun
outbound 在配置上也是 direct类型,但它带有 routing_mark。实际上,这个 mark
会被Linux policy routing 捕获,把流量导向 Gluetun。因此它并不是普通意义上的直
连,而是“通过系统路由送到 Gluetun”。
换句话说,sing-box 在这里更像一个智能分流器,而 Gluetun 是最终的上游 VPN 出口。 这里除了通过gluetun,singbox自己也可以通过类似的方式配置其他类型的 outbound,例 如 WireGuard、VLESS、Trojan 等,来适配更多样化的上游服务。如果你不需要gluetun提 供的各种便利性服务,甚至可以在这里就把它换成其他 VPN 客户端或直接的互联网出口。
需要注意的是,singbox在这里是拿不到域名信息,所以我们在这里需要开启sniff 功能来识别域名。这样才能基于域名的规则集来做分流。对于一些不支持sniff的协议或加 密流量,可能就只能基于IP规则来做分流了。
Gluetun:上游 VPN 出口层
Gluetun 负责连接商业 VPN、公司 VPN 或其他支持的上游 VPN 服务。
它的优势是支持大量 VPN 服务商,并且把 OpenVPN / WireGuard 客户端、认证参数、防火 墙规则、健康检查等逻辑都封装在容器里。
在新版架构中,绝大多数默认流量最终都会进入 Gluetun,再由 Gluetun 通过上游 VPN 隧 道访问互联网。这样客户端看到的是自己的 WireGuard 网络,而互联网看到的是上游 VPN 的出口 IP。
整体网络拓扑
新版架构可以理解为下面这个路径:
flowchart TD
subgraph devices["Your Devices"]
phone["Phone"]
pc["PC"]
laptop["Laptop"]
end
subgraph server["Your Server"]
wgeasy["WG-Easy (WireGuard Server)"]
adguard["AdGuard Home (DNS Filtering)"]
singbox["sing-box (TUN Router / Rule Engine)"]
gluetun["Gluetun (VPN Provider Client)"]
end
phone -- WireGuard --> wgeasy
pc -- WireGuard --> wgeasy
laptop -- WireGuard --> wgeasy
wgeasy -- DNS only --> adguard
wgeasy -- regular traffic --> singbox
singbox -- bypass_rule_sets --> direct["Direct Internet"]
singbox -- default route --> gluetun
gluetun -- VPN tunnel --> provider["VPN Provider"]
provider --> internet["Internet"]
direct --> internet
从流量角度看,可以分成三类:
- DNS 流量:WireGuard 客户端的 DNS 请求被固定转发到 AdGuard Home。
- 命中绕过规则的流量:例如 OpenAI、PayPal 或其他你放进
bypass_rule_sets的规则集,可以走 direct。 - 默认流量:没有命中绕过规则的普通互联网流量会进入 Gluetun,再通过上游 VPN 出口访问互联网。
此外,还可以配置 direct_subnets,让特定网段绕过 sing-box。这适合一些明确的内网
访问场景,例如访问家庭局域网、特定 Docker 网络或某些专用子网。
配置管理:从手写配置到生成式配置
新版方案的另一个重要变化是配置管理方式。
以前你可能需要同时修改:
docker-compose.yml- WireGuard hook
- iptables 规则
- Gluetun 环境变量
- DNS 配置
- sing-box JSON
- AdGuard Home 配置
这样虽然灵活,但维护成本很高。尤其是网络结构稍微变化后,很容易出现“一个地方改
了,另一个地方忘了改”的问题。新版方案把主要配置集中到
config.yaml,
然后通过生成脚本把它渲染成 runtime/ 下的各种实际的配置文件。
因此,普通用户只需要改 config.yaml。而高级用户如果要调整更多的配置,则可以修改
templates/ 下的 Jinja2 模板。这样既保证了配置的集中管理,也保留了足够的灵活性。
需要注意的是,我建议不要直接修改 runtime/ 目录下的文件。它们是生成物,每次重新运行都会被覆
盖。
sing-box 分流规则如何工作
新版方案中,sing-box 的规则大致可以理解为:
{
"route": {
"rules": [
{ "inbound": "tun-in", "action": "sniff" },
{ "ip_is_private": true, "outbound": "direct" },
{
"rule_set": ["geosite-openai", "geosite-paypal"],
"outbound": "direct"
},
{ "outbound": "gluetun" }
]
}
}
这表示:
- 先对流量做 sniff,识别域名等信息;
- 私有 IP 地址直接走 direct;
- 命中规则集的流量走 direct;
- 其他所有流量走
gluetunoutbound。
bypass_rule_sets 的含义是“绕过上游 VPN”,不是“绕过你的服务器”。
例如你配置了:
singbox:
bypass_rule_sets:
- tag: "geosite-openai"
url: "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-openai.srs"
- tag: "geosite-paypal"
url: "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-paypal.srs"
那么这些服务的流量仍然会经过你的 WireGuard 服务器和 sing-box,只是不再进入 Gluetun 的上游 VPN 隧道,而是由服务器侧直接访问互联网。
这对一些对 VPN 出口敏感的服务很有帮助。比如有些服务看到商业 VPN IP 会要求额外验 证,甚至直接拒绝访问。通过规则绕过上游 VPN 后,可以减少这类问题。
extra_rule_sets 是什么
新版配置里还有一个 extra_rule_sets:
singbox:
extra_rule_sets:
- tag: "geosite-google"
url: "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-google.srs"
- tag: "geosite-apple"
url: "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-apple.srs"
它的作用是:下载并缓存这些规则集,但不参与当前路由匹配。也就是
说,extra_rule_sets 不会改变流量路径。只有放进 bypass_rule_sets,或者在
sing-box 模板里显式引用,规则才会真正生效。
我保留这个配置项,是为了方便未来扩展。例如我可能想先把 Google、Apple、Amazon 等
规则集准备好,但不马上启用。等到需要时,只需要把对应规则移到
bypass_rule_sets,或者添加新的 route rule。
如果你追求最简配置,也可以把 extra_rule_sets 设置成空数组:
singbox:
extra_rule_sets: []
注意,YAML 中最好写成显式空数组,而不是只写一个空 key:
# 推荐
extra_rule_sets: []
# 不推荐,容易被解析成 null
extra_rule_sets:
DNS:为什么要默认引入 AdGuard Home
在 VPN 网关中,DNS 是一个很容易被忽略的问题。如果只管普通流量,不管 DNS,就可能 出现这种情况:
- 浏览器流量走了你的 VPN 网关;
- DNS 查询却发给了本地网络、运营商 DNS 或某个公共 DNS;
- 最终造成 DNS 泄露,或者规则分流判断不准确。
新版架构里,WireGuard 客户端的普通 DNS 请求会被限制到 AdGuard Home。这样你可以在 网关侧统一管理 DNS。
AdGuard Home 可以带来几个好处:
- 广告和跟踪域名过滤;
- 自定义上游 DNS;
- 查询日志;
- 本地域名重写;
- 对不同客户端做差异化策略。
不过需要注意,如果你想完全禁止所有 DNS 绕过,还需要考虑 DoH/DoT/QUIC等情况。本文 中的 DNS 限制主要针对传统 UDP/TCP 53 查询。
适合的使用场景
新版架构可以覆盖的场景比旧版更多,综合考虑下,主要适用于以下几种情况:
1. 多设备共享一个上游 VPN
这是最基础的使用方式。
你只需要在服务器上配置一次上游 VPN,所有设备通过 WireGuard 接入。手机、电脑、平 板、备用机都不需要分别安装上游 VPN 客户端。
这对于设备数量较多、平台较杂,或者上游 VPN 客户端体验不佳的情况尤其有用。
2. 远程访问家庭或办公网络
所有设备接入同一个 WireGuard 网络后,可以形成一个统一的虚拟局域网。
你可以用它访问:
- 家里的 NAS;
- 办公室内网服务;
- 私有 Git 服务;
- 家庭媒体服务器;
- SSH 管理入口。
如果配合 direct_subnets,还可以让部分内网访问不经过复杂的 sing-box 分流逻辑。
3. 对不同服务采用不同出口策略
有些服务适合走商业 VPN,有些服务则不适合。
例如:
- 默认流量走 Gluetun 上游 VPN;
- OpenAI、PayPal 等敏感服务走 direct;
- Torrent、P2P 流量走Gluetun或者其他专门的 VPN 出口;
- 私有 IP 和内网地址不进入上游 VPN;
- 特定规则集预先下载,但暂不启用。
这种结构比旧版本的“全局代理”更灵活,也比纯手写 iptables 规则更容易维护。
5. 低侵入式部署
整套方案基于 Docker Compose。宿主机只需要安装 Docker 和 Docker Compose,主要网络 逻辑都在容器和生成配置中完成。这对 VPS、家用服务器、软路由、树莓派都比较友好。
部署流程概览
实际部署时,流程大致是:
git clone https://github.com/saturneric/wg-easy-gluetun.git
cd wg-easy-gluetun
然后编辑:
vim config.yaml
至少需要配置:
- 上游 VPN 的 WireGuard / OpenVPN 参数;
- WG-Easy 管理密码;
- 服务器公网地址或域名;
- AdGuard Home 上游 DNS;
- sing-box 绕过规则;
- 必要的服务端口和固定容器 IP。
启动时使用:
./up.sh -d
不要直接运行普通的 docker compose up,因为 runtime compose 文件和相关配置需要
先由生成器创建。up.sh 会先运行配置生成逻辑,再启动完整 stack。
安全注意事项
这类网关方案虽然方便,但也需要注意安全边界。
1. 不要使用默认密码
config.yaml 里的 WG-Easy 密码、Clash API secret、AdGuard Home 凭据都应该修改。
尤其是管理界面如果暴露在公网,默认密码会非常危险。
2. 谨慎暴露管理端口
通常只应该公开 WireGuard UDP 端口。WG-Easy、MetaCubeXD、AdGuard Home 管理界面最 好不要直接暴露在公网。
3. 确认上游 VPN 服务条款
多设备共享、网关转发、链式 VPN 是否被允许,取决于你的上游 VPN 服务条款。部署前应 该自己确认。
4. 注意 DNS 绕过
本方案会限制普通 DNS 查询,但不能自动阻止所有应用层 DoH / DoT 行为。如果你需要更 严格的 DNS 策略,需要额外做域名、IP、SNI 或应用层策略控制。
总结:相比旧版方案的主要变化
和旧版 WG-Easy + Gluetun 相比,新版架构主要有这些变化:
| 方面 | 旧版 | 新版 |
|---|---|---|
| 接入层 | WG-Easy | WG-Easy |
| 上游 VPN | Gluetun | Gluetun |
| 分流能力 | 主要依赖路由和 iptables | sing-box 规则集分流 |
| DNS | 需要额外配置 | 默认集成 AdGuard Home |
| 配置方式 | 多文件手动维护 | config.yaml + 模板生成 |
| 规则管理 | 粗粒度 | geosite / rule-set 级别 |
| 可观测性 | 主要看日志 | 可配合 MetaCubeXD 查看 sing-box |
| 扩展能力 | 相对有限 | 更适合未来加入更多规则和服务 |
总而言之,旧版更简单,适合只想把所有流量送进上游 VPN 的用户。新版则更适合长期使用,尤其适 合需要分流、DNS 过滤、集中管理和多场景适配的用户。