3.3 你读了别人的路由器项目。这章反过来——自己动手,在你的路由器上开发一个真正有用的功能。目标不只是"抄一份配置",而是学会造功能的思路:任何路由器功能,你都能想清目标、拆成学过的原语、选实现层、配好、验证。我们用一个自托管者的经典需求当例子:从任意地方(公司、咖啡厅、另一个城市)安全访问家里的 LAN——你的 NAS、你的智能家居。它正好会撞上你在 2.6 / 加餐章见过的 CGNAT 问题,而你现在有能力解决它。这一章是把整门课攒的原语,拧成一个你会天天用的能力。
开发一个路由器功能 = 想清目标 → 拆成学过的原语 → 选实现层(内核 / 守护进程 / 配置)→ 配置 → 验证。本章用"WireGuard 远程访问家里 LAN"当例子走一遍,顺带解决 CGNAT。
1造一个功能的通用流程
任何路由器功能,都能按同一个流程造。这个流程比任何单个功能都值钱:
- 想清目标:用一句话说清"要什么"和"成功的样子"(能从外网 ping 通家里 NAS)。含糊的目标造不出清晰的功能。
- 拆成原语:这功能由哪些学过的积木组成?(隧道?路由?NAT?防火墙?DNS?)——这步就是 2.7 的"解构"反着用:不拆别人的,拆你要造的。
- 选实现层:每块原语在哪层实现?内核(nftables/ip route,1.2/1.3)、守护进程(WireGuard/dnsmasq,1.6/2.3)、还是配置系统(UCI/NixOS,2.2/3.2)。同一功能可有不同实现层(3.3 的 eBPF vs nftables)。
- 配置:把选好的实现落成实际配置(命令 / UCI / NixOS 声明)。
- 验证:定义"怎么算成功",逐步测——每加一块验一块,别攒到最后一起调。
为什么先讲流程:功能千变万化(远程访问、分流、限速、去广告…),但造它们的流程是同一个。学会流程,你面对任何新需求都不慌——先套这五步,功能自然浮现。
2.7 教你把别人的"高级功能"拆回原语(解构);这章教你把自己的需求组装成功能(建构)。解构和建构是同一种能力的两面——都建立在"你认识那些原语"之上。你已经认识它们了,现在学着用它们造东西。
2选题:从任意地方访问家里 LAN
用第一步(想清目标)说清楚:要什么——在外面(公司/咖啡厅/另一城市)的笔记本或手机,能访问家里 LAN 的设备(NAS 的 192.168.10.x、智能家居);成功的样子——外网设备连上 WireGuard 后,能 ping 通家里 NAS、能打开 NAS 的 Web 界面,就像在家一样。
为什么用 WireGuard(1.6):现代、简单、快的 VPN——一对公私钥、一个 UDP 端口,就能在两台设备间建一条加密隧道。1.6 你学过"隧道 = 一个虚拟接口 + 把流量路由进去",WireGuard 正是这套的最佳实践。但有个绕不开的现实:家里路由器要能被外面连到。有公网 IP(2.6)就直接连;若在 CGNAT 后面(2.6/加餐章:你 WAN 拿到的是运营商私网),外面根本连不进来——这正是端口转发在 CGNAT 下失效的同一个问题。第 3 节处理它。
还记得加餐章和 2.6 反复说的 CGNAT 吗?"外部主动连不进你家"在这里从一个抽象警告,变成一个你必须解决的实际障碍。好消息:你现在懂它的成因(WAN 拿到的不是真公网),也就懂怎么绕——不硬闯运营商的 NAT,而是让家和外部设备都主动连向一个双方都能到达的中间点。
3拆成原语并实现
第二步(拆成原语),这个功能 = 三块积木:隧道(1.6)——两端各配一个 WireGuard 接口 wg0、公私钥配对建加密隧道;路由(1.2)——告诉外部设备"去家里 LAN 的流量走 wg0";防火墙(2.4)——放行 WireGuard 的 UDP 端口、允许隧道流量转发进 LAN。看图:
第三、四步(选层 + 配置),最小配置。家里路由器侧:
[Interface]
Address = 10.66.66.1/24 # 隧道内网段(和家里 LAN 不同)
ListenPort = 51820 # WireGuard UDP 端口
PrivateKey = <家里路由器私钥>
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = nft add rule inet filter forward iifname "wg0" oifname "eth1" accept # 隧道→LAN 放行 (2.4)
PostUp = nft add rule ip nat postrouting ip saddr 10.66.66.0/24 oifname "eth1" masquerade # 让 NAS 能回包 (1.3)
[Peer] # 你的外部设备
PublicKey = <外部设备公钥>
AllowedIPs = 10.66.66.2/32 # 该 peer 在隧道里的地址
外部设备(手机 / 笔记本)侧:
[Interface]
Address = 10.66.66.2/24
PrivateKey = <外部设备私钥>
[Peer] # 家里路由器
PublicKey = <家里路由器公钥>
Endpoint = 你家公网IP:51820 # ← 若在 CGNAT 后,这里连不上,见下
AllowedIPs = 10.66.66.0/24, 192.168.10.0/24 # 隧道网段 + 家里 LAN
外部设备的 AllowedIPs = 192.168.10.0/24 是精髓:它同时是"这个 peer 能用的地址范围"和"哪些流量走这条隧道"的路由——1.2 的路由决策,在 WireGuard 里就浓缩成这一行。把家里 LAN 网段写进去,去 LAN 的流量才走隧道。
Endpoint = 你家公网IP 连不上,因为你没真公网 IP。解法:加一台有公网 IP 的小 VPS 当会合点——家里路由器和外部设备都主动连向 VPS(主动出站,CGNAT 允许),VPS 把两边的隧道流量转接。这样不需要家里有公网 IP,两边都"往外连"到一个公共点,绕开了"外部主动连进 CGNAT"这个死结。(可用 WireGuard 的 hub-and-spoke 组网,或 Tailscale / headscale 这类基于 WireGuard 的中继方案帮你自动会合。)
你刚搭的是最简单的"一个 peer 连回家"。把它扩展——多个设备、多个站点(家、公司、云服务器)都加进来,每对之间能通,就是 WireGuard mesh(网状组网)。原理不变:每个节点一个 wg 接口、用 AllowedIPs 声明"谁的流量走哪条隧道"。你学的 1.6 隧道 + 1.2 路由,规模化一下就是一张私有网络。
4验证:它真的通了吗
第五步——按"每加一块验一块"的顺序测,每步失败都能定位到具体哪块:
- 隧道建立了吗:
wg show看握手时间和收发字节——有最近握手 = 隧道通了。没握手 → 查端口放行(2.4)、Endpoint 可达(CGNAT?)、公私钥配对。 - 能到隧道对端吗:从外部设备 ping 家里路由器的隧道地址
10.66.66.1——通 = 隧道内路由对。不通 → 查 AllowedIPs、两端隧道网段。 - 能到家里 LAN 吗:ping 家里 NAS 的
192.168.10.x——通 = 全线打通。不通 → 查家里路由器的转发(ip_forward)、forward 放行(2.4)、以及回程(NAS 靠家里路由器 masquerade 掉隧道源地址才能回包)。
这个"分层验证"就是流程第五步的落地:别一上来 ping NAS 失败就抓瞎,按隧道 → 对端 → LAN 逐层测,每层对应你搭的一块,失败立刻知道是哪块。这也是调试任何网络功能的通法——沿着数据包的路径,一跳一跳验。
现在它"能用"了,但离"可靠"还有距离——密钥怎么安全保管、隧道断了怎么自动重连、VPS 中转的安全加固、配置怎么持久化(3.1/3.2 的老问题)。这些"从能用到能扛"的事,是下一章 3.5 生产加固要讲的。
停下来看看你刚做了什么:你把 1.6 的隧道、1.2 的路由、2.4 的防火墙、还有对 CGNAT(加餐章/2.6)的理解,组装成了一个你会天天用的功能。没有查一篇"WireGuard 远程访问教程"照抄——你是按流程,从目标推出每一块该用什么、在哪配、怎么验。这就是"从零到路由器"的终点风景:你不再需要教程,因为你理解了组成一切的原语,能自己把它们组装成任何你需要的东西。
本章小结
- 造任何路由器功能的通用流程:想清目标 → 拆成学过的原语 → 选实现层 → 配置 → 验证。流程比单个功能值钱;它是 2.7"解构"的反向(建构)。
- 例子功能:WireGuard 远程访问家里 LAN,拆成三块——隧道(1.6)+ 路由(1.2)+ 防火墙放行(2.4)。
- WireGuard 的
AllowedIPs一行同时是"peer 地址范围"和"哪些流量走隧道"的路由——1.2 的路由决策浓缩于此;把家里 LAN 网段写进去,去 LAN 的流量才走隧道。 - CGNAT(加餐章/2.6)下家里没公网 IP、外部连不进——解法是加一个公网 VPS 当会合点,两边都主动出站连它,绕开死结;扩展到多节点就是 WireGuard mesh。
- 分层验证(wg show → ping 对端 → ping LAN),每层对应一块、失败即定位;这是调试任何网络功能的通法。通向生产(密钥/重连/加固/持久化)是 3.5。
动手练习
- 用五步流程,给另一个功能(如"给孩子的设备定时断网""访客网限速")写出:目标一句话、拆成哪些原语、每块在哪层、大致怎么配、怎么验。不用真做,练"从需求到方案"的思路。
- (有条件时)搭本章的 WireGuard 远程访问:家里一台设备当服务端、手机当外部设备,验证三层(wg show → ping 隧道地址 → ping 家里另一台设备)。若在 CGNAT 后,试试 Tailscale / headscale 这类中继方案。
- 思考题:外部设备的 AllowedIPs 为什么必须包含家里 LAN 网段(192.168.10.0/24)?去掉它会怎样?(它是路由——不写,去 LAN 的流量不走隧道,自然到不了家。)
- 进阶:画出你 ping 家里 NAS 时,数据包从外部设备到 NAS 再回来的完整路径,标出每跳用的是你搭的哪块(隧道封装 1.6 → 家里路由器转发 1.2 → forward 放行 2.4 → 到 NAS → 回程)。这是第 4 节"分层验证"的数据包视角版。