家庭网络分层拓扑:从远端笔记本到双出口的完整链路
目录 / Step 导航
上一篇《OpenWrt 双出口分流》讲的是旁路网关内部怎么做第二出口。这一篇把镜头拉远,讲整张网络的分层拓扑:一台远端的公司笔记本,是怎么穿过 NAS 的 VPN、被两段策略路由接力、最终从境外出口上网的;以及家里每一类设备各自走哪条路、为什么。
文中所有公网 IP、商业服务商品牌、个人域名与主机名均已抹去,只保留可复用的结构。
一、全景图
先上完整的数据流图,后面逐层拆解:
┌──────────────────────────────────────────────┐
公司笔记本(远端,任意网络) │ 家庭内网 192.168.0.0/24 │
│ │ │
│ VPN 隧道(加密) │ ┌─────────── NAS (.4) ────────────┐ │
└───────────────────────────┼──►│ VPN Server → tun0 172.x.y.0/24 │ │
│ │ │ │
│ │ ip rule: from 172.x.y.0/24 │ │
│ │ lookup 100 │ │
│ │ table 100: default via .254 ────┼──┐ │
│ │ │ │ │
│ │ NAS 自身流量: default via .1 ───┼──┼──► │──► 国内家宽(直连)
│ └─────────────────────────────────┘ │ │
│ ▼ │
家里普通设备(手机/电视/PC)───────┼──────────────────────────────► 旁路网关 (.254)│
│ OpenWrt 虚拟机 │
│ │ │
│ TPROXY 全局透明代理 │ │
│ fwmark 0x1 → lookup 100 → 代理内核 │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ 默认(未命中规则) 命中媒体域名 │
│ │ │ │
└────────┼───────────────────────┼─────────────┘
▼ ▼
主出口(境外A) 第二出口(境外B,
金融/工作/默认 WireGuard 节点池
+ 自动故障切换)
三个层次一句话概括:
- 接入层(NAS):把远端设备"拉进"家庭内网,并用策略路由决定它的流量交给谁。
- 代理层(旁路网关):把到达的流量透明地劫进代理内核,按域名分流到两个境外出口。
- 出口层:主出口(生命线)+ 第二出口(媒体流量、多节点冗余)。
二、四类终端,四种出口画像
同一张家庭网络,不同设备的流量走完全不同的路——这是整个设计的出发点:
| 终端 | 路径 | 最终出口 | 为什么 |
|---|---|---|---|
| 公司笔记本(远端) | VPN → NAS → 策略路由 → 旁路网关 → 代理 | 境外(主出口/分流) | 人在外面,也要和在家一样的网络环境 |
| 家里普通设备 | 默认网关指向旁路网关 → 代理 | 境外(主出口/分流) | 全家默认出海,域名分流自动生效 |
| NAS 本机 | 默认路由直指上游网关 | 国内直连 | NAS 跑的是下载/备份/内网服务,走国内又快又稳,也不占代理带宽 |
| 开发用笔记本 | 自己的独立 VPN 隧道 | 境外(独立于本拓扑) | 故障隔离:排查家庭网络时,这台机器不受影响,反之亦然 |
注意最后一行的价值:留一台不依赖这套拓扑的机器。旁路网关重启、代理挂掉时,你需要一台还能上网、还能 SSH 进各设备排障的"生命线终端"。
三、第一棒:NAS 上的接入与策略路由
远端的公司笔记本通过 VPN 拨进 NAS(很多 NAS 系统自带 VPN Server 套件),拿到一个 VPN 子网的地址(本文记作 172.x.y.0/24,NAS 侧接口是 tun0)。
默认情况下,VPN 客户端的流量会跟着 NAS 自己的默认路由走——也就是国内直连。但我们想让它走代理。在 NAS 上加两条东西即可:
# 1. 独立路由表:VPN 客户端的"默认路由"指向旁路网关(而不是上游网关)
ip route add default via 192.168.0.254 dev <内网接口> table 100
ip route add 172.x.y.0/24 dev tun0 table 100 # 回程路由也要在这张表里
# 2. 策略路由:只有源地址来自 VPN 子网的流量才查这张表
ip rule add from 172.x.y.0/24 lookup 100
生效后的 ip rule 长这样:
0: from all lookup local
1: from 172.x.y.0/24 lookup 100 ← 只有 VPN 客户端命中
32766: from all lookup main ← NAS 自身流量照旧
32767: from all lookup default
这一段的精髓是按源地址切割路由决策:
- 命中
from 172.x.y.0/24的(= 公司笔记本),默认路由被替换成"下一跳旁路网关"。 - NAS 自己的流量源地址是内网地址,不命中,继续查 main 表直连国内——NAS 的下载、备份、内网服务完全不受影响。
别忘了打开转发和 NAT/放行(各系统写法不同,思路一致):VPN 子网 → 内网接口允许 FORWARD;如果旁路网关上没有回程路由,就在 NAS 上对这段做 SNAT,让回包能找回来。
四、第二棒:旁路网关上的透明代理
流量到达旁路网关后,进入上一篇讲过的代理平面,这里只画重点。
旁路网关是台 OpenWrt 虚拟机,单臂部署(只有一个桥接口,既收内网流量,也从同一条线出去)。它不做路由层分流,而是全局透明代理:
到达的转发流量 / 本机流量
│ 防火墙 mangle 链打上 fwmark 0x1
▼
ip rule: from all fwmark 0x1 lookup 100
▼
table 100: local default dev lo ← 流量被"扣留"在本机
▼
TPROXY 重定向 → 代理内核监听端口
▼
按域名分流:
├─ 默认(金融/工作/一切未命中)──► 主出口(境外A)
└─ geosite:youtube 等媒体域名 ───► 第二出口(境外B,WireGuard 节点池)
配套机制(详见上一篇):
- DNS 全量劫持到代理内核的 DNS 端口,远程解析,无污染——域名分流因此可靠。
- 防泄漏(kill switch):自制 nft 规则 DROP 掉"绕过代理直连外网"的转发——代理挂了宁可断网也不裸奔。
- 第二出口节点池 + cron 自动故障切换:单节点挂了沿节点环轮转,绝不回落主出口。
五、两段 ip rule 的接力:各管一段,互不知情
这套拓扑里最容易混淆的,是 NAS 和旁路网关上各有一条 lookup 100 的 ip rule,但它们是完全不同的两回事:
| NAS 上的规则 | 旁路网关上的规则 | |
|---|---|---|
| 规则 | from 172.x.y.0/24 lookup 100 | from all fwmark 0x1 lookup 100 |
| 匹配依据 | 源地址(谁发的) | 防火墙标记(被 mangle 链盖过章的) |
| table 100 内容 | default via 旁路网关 | local default dev lo |
| 作用 | 把 VPN 客户端流量送到网关 | 把打了标的流量扣进代理 |
| 谁维护 | 手工/开机脚本 | 代理服务自动增删 |
表号都叫 100 纯属巧合(两台机器各有各的路由表空间),但正好提醒我们:策略路由是逐跳生效的。NAS 只负责"下一跳给谁",它不知道也不需要知道网关后面是代理;网关只管"到达我的流量按域名分流",它不在乎流量是家里设备发的还是 VPN 穿进来的。两段规则通过"把包送到对方门口"完成接力,没有任何共享状态。
这种分层解耦的直接好处:加一台新的接入设备(比如再来一路 VPN),只动 NAS 的规则;换一个出口节点,只动网关的代理配置——互不牵连。
六、故障域分析:每一层挂了会怎样
设计时把"谁挂了影响谁"想清楚,出问题时就不会慌:
| 故障 | 影响范围 | 表现与恢复 |
|---|---|---|
| 旁路网关重启 | 家里设备 + 公司笔记本断网 | 代理内核拉起需要几十秒,期间"打不开",自愈,不用管 |
| 第二出口节点挂 | 只有媒体域名 | 自动故障切换约 6 分钟内换下一个节点;期间媒体域名连接失败,其余一切正常 |
| 主出口挂 | 默认流量(金融/工作) | 不会自动切到第二出口——宁可暂时不通,也不换国家 IP 去登录银行 |
| NAS 挂 | 只有公司笔记本 | 家里设备不经过 NAS,完全无感;笔记本重连 VPN 即可 |
| 上游家宽挂 | 全部 | 物理层问题,谁也救不了 |
| 代理挂但网关活着 | 家里设备 + 笔记本 | kill switch 兜底:断网而不是裸奔直连 |
两个值得强调的设计决策:
- 主出口挂 ≠ 切第二出口。金融和工作服务的 IP 归属地突变,轻则风控验证,重则封号。所以默认流量没有任何 fallback 规则——这是故意的。
- 重启网关前心里有数。接入层(NAS 的 ip rule)是静态的,重启网关不影响它;恢复顺序永远是"网关代理拉起 → 全链路自愈",不需要人工干预任何一层。
七、一个运维细节:会悄悄残留的重复 ip rule
旁路网关重启后,偶尔会看到 fwmark 规则出现两条一模一样的副本:
32764: from all fwmark 0x1 lookup 100
32765: from all fwmark 0x1 lookup 100
翻代理服务的脚本能找到原因——它的启动/停止逻辑是不对称的:
# start 时:
ip rule add fwmark 1 lookup 100 # 加一条
# stop 时:
ip rule del fwmark 1 lookup 100 # 只删一条(del 一次只删一个实例)
开机过程中 start 逻辑被触发了两次(没有经过 stop),就叠成两条。之后每次 restart 都是"删一条、加一条",净数不变——这个重复副本不会自愈,会永久残留。
处理原则:
- 功能上完全无害:两条规则字节级相同,匹配等价,零开销。不处理也没任何问题。
- 想清理的话,
ip rule del fwmark 1 lookup 100恰好只删一个实例,剩下那条继续工作,流量无感知。 - 但绝不能删光——这条规则是整个代理平面的命脉,删光则所有代理流量(包括穿过 NAS 进来的公司笔记本)全断,直到代理服务下次重启才恢复。删之前先
ip rule show数清楚还剩几条。
八、小结
回看整张图,这套拓扑的骨架就三句话:
- 接入归接入,代理归代理。NAS 用"源地址策略路由"决定谁的流量交给网关,网关用"fwmark + TPROXY"决定流量怎么出海——两段 ip rule 各管一段,通过下一跳接力,零共享状态。
- 出口画像按设备定制。远端笔记本全量出海、家里设备默认出海、NAS 直连国内、开发机独立隧道互为备份——同一张网,四种画像。
- 故障域预先划清。每一层挂掉影响谁、会不会自愈、要不要 fallback,都是设计时定好的——尤其是"主出口挂了绝不自动换国家"这条底线。
分层的代价是多一跳、多一处配置;换来的是每一层都可以独立变更、独立排障、独立演进。对一张要长期运行的家庭网络来说,这笔账很划算。