Phase 3 开始——最后一跃:自己造一台路由器。前两阶段你看懂了数据包(Phase 0)、手搓了内核能力(Phase 1)、拆穿了 OpenWRT(Phase 2)。现在把 OpenWRT 拿掉:给你一台普通 Linux + 两个网口,用你学过的裸原语,把它变成一台真能用的路由器。这一章就是证明——你确实懂路由器了。因为你会看到:一台路由器的本质,不过是 Linux + IP 转发 + NAT + 一个 DHCP/DNS 服务 + 几条防火墙规则,大约三十行配置。OpenWRT 只是在这之上加了配置管理、网页界面和打磨。
最小路由器 = 一台有两个网口的 Linux(一个朝 WAN、一个朝 LAN)+ 五样东西:两侧配地址、打开 ip_forward、WAN 做 NAT、基本防火墙、LAN 跑 dnsmasq。就这些,一台能用的路由器。
1目标:Linux + 两个网口
路由器最本质的定义就是"连接两个(或多个)网络、并在它们之间转发的设备"——一台有两个网口的 Linux 天生具备这个身体。硬件:任何有两个网口的 x86/ARM 机器都行(软路由小主机、带双网卡的旧电脑、甚至加个 USB 网卡的单网口机器)。一个口接光猫 / 上级网络(WAN),一个口接你的交换机 / 设备(LAN)。
光猫 / 上级路由
- 配地址1.2
- 开 ip_forward0.3
- WAN masquerade0.6 / 1.3
- 有状态防火墙1.3
- LAN 跑 dnsmasq2.3
交换机 / 电脑 / 手机
回想 0.3 的实验:你在 namespace 里搭的那个路由器 r,两个接口各属一个网段、打开转发。现在只是把 r 从 namespace 搬到真实机器:eth0=WAN、eth1=LAN。同一个东西,从沙盒到实体。目标状态:LAN 口接一台设备,它能自动拿到 IP、能上网——达成这个,你就有了一台路由器。
这台"最小路由器"你在 1.4 就搭过雏形——namespace r 就是它的沙盒版。1.4 说过"namespace 是练路由器的安全沙盒",现在沙盒毕业,搬上真机。你不是在学新东西,是把练过的搬到现实。
2五步配方:从裸机到能上网
五步,每步都是你单独学过的一条命令。
① 配地址(1.2)
# WAN 口:当 DHCP 客户端从上级拿地址
udhcpc -i eth0 # 或 dhcpcd eth0(2.6 的 WAN 侧)
# LAN 口:配一个静态网关地址(你内网的网关)
ip addr add 192.168.10.1/24 dev eth1
ip link set eth1 up
② 打开转发(0.3)——关键一步
③ WAN 做 NAT(0.6 / 1.3)
nft add table ip nat
nft 'add chain ip nat postrouting { type nat hook postrouting priority 100 ; }'
nft add rule ip nat postrouting oifname "eth0" masquerade # 出 WAN 改源地址
④ 基本有状态防火墙(1.3)
nft add table inet filter
nft 'add chain inet filter forward { type filter hook forward priority 0 ; policy drop ; }'
nft add rule inet filter forward iifname "eth1" oifname "eth0" accept # LAN→WAN 放行
nft add rule inet filter forward ct state established,related accept # 回包放行
# input 链同理:放行 lan、放行回包、默认 drop(见 1.3)
⑤ LAN 上跑 dnsmasq(2.3)
# dhcp-option 3 = 网关,6 = DNS(都指向本机 dnsmasq)
dnsmasq --interface=eth1 \
--dhcp-range=192.168.10.100,192.168.10.200,12h \
--dhcp-option=3,192.168.10.1 \
--dhcp-option=6,192.168.10.1
这五步就是一台路由器的全部骨架。插一台设备到 eth1,它拿到 192.168.10.x、网关 192.168.10.1,就能上网了。每一步你都单独学过——ip addr(1.2)、ip_forward(0.3)、masquerade(0.6/1.3)、有状态防火墙(1.3)、dnsmasq(2.3)。摆在一起,就是路由器。
把这五步和 0.3 的实验并排看,几乎一一对应:0.3 里你也是给接口配地址、ip_forward=1、然后 ping 通。区别只是:0.3 两端是 namespace 里的 h1/h2,这里是真实的上级网络和你的设备;0.3 没配 NAT/DHCP/防火墙(实验环境不需要),这里补上了让它面向真实互联网所需的三样——NAT 出公网、DHCP 发地址、防火墙保安全。
3这就是路由器:OpenWRT 加了什么
上面三十行已经是一台能用的路由器了。你可能会想:那 OpenWRT 那一大堆东西(UCI、netifd、procd、LuCI…)是干嘛的?对照来看,它们都是在这个最小核心之上的"生活品质"层:
- UCI(2.2):把你手敲的一堆命令,变成
/etc/config里可管理的配置(而非散落脚本); - netifd(2.2):把"配地址 + 开转发 + 建接口"自动化、可 reload;
- fw4(2.4):把你手写的 nftables,变成 zone 模型让人好维护;
- dnsmasq/odhcpd 集成(2.3):把 DHCP/DNS 纳入统一配置;
- LuCI:给这一切一个网页界面;procd(2.1):开机自动拉起、崩了重启。
换句话说:OpenWRT = 这个最小路由器 + 配置系统 + 服务管理 + Web UI + 一堆打磨。核心那台"路由器"就是你这三十行。
这回答了 2.1 开头那个视角:"路由器 = 内核机制 + 一堆守护进程"。现在你亲手验证了——内核机制(转发/NAT/防火墙)+ 最少的守护进程(dnsmasq)= 能用的路由器;OpenWRT 的其余进程(netifd/procd/uhttpd…)是为了"好用、好管、好活",不是"能用"的必需。你已经能造出"能用"的那台了。
4从"能跑一次"到"一个系统"
但有个现实问题:你上面敲的 ip addr、sysctl、nft、dnsmasq,全是运行时状态——机器一重启,全丢了,又变回一台普通 Linux。要成为一台可靠的"路由器",这些配置必须:
- 持久化:重启后依然生效;
- 开机自启:各服务(dnsmasq 等)自动拉起(procd 在 OpenWRT 里干这个);
- 可复现:换台机器、重装系统,能一键回到同样的配置。
传统做法是写一堆脚本(rc.local、systemd unit、iptables-save…)——能用,但零散、易漂移(改一处忘一处)、难迁移。这正是 2.2 说的"配置状态 vs 运行状态"问题的根源。OpenWRT 的答案是 UCI(集中配置 + procd 自启);而 Phase 3 接下来要看另一种更彻底的答案。
下一章 3.2 用 NixOS 造路由器:你不再敲命令改运行状态,而是写一份声明("这台机器就该有这些接口、这条 NAT、这个 dnsmasq"),系统保证实际状态永远等于声明——持久、可复现、可回滚。你这三十行的"意图",会变成一份可版本管理的声明文件。最小路由器解决了"能用",3.2 解决"可靠、可复现"。
本章小结
- 最小路由器 = 一台双网口 Linux + 五步:配地址(1.2)、开 ip_forward(0.3)、WAN masquerade(0.6/1.3)、基本有状态防火墙(1.3)、LAN 跑 dnsmasq(2.3)。约三十行。
- 它就是 0.3 那个 namespace 路由器
r搬上真机——1.4 的沙盒毕业;五步和 0.3 实验几乎一一对应,只是补上了面向真实互联网的 NAT/DHCP/防火墙。 - ip_forward 是把"主机"变"路由器"的那一行(0.3/1.4);核心中的核心。
- OpenWRT = 这个最小核心 + UCI + netifd/fw4 + procd + LuCI + 打磨;核心那台路由器就是你这三十行。
- 差距在持久化 / 可复现:命令重启即失,要变可靠系统需持久 + 自启 + 可复现——Phase 3 后面(3.2 NixOS 声明式)解决。
动手练习
- 把五步配方和 0.3 的 namespace 实验并排写出来,逐条对应:哪几步是 0.3 已有的、哪几步是这里新增(NAT/DHCP/防火墙)、为什么新增。
- (有双网口机器 + 敢折腾时)在一台非生产 Linux 上试搭最小路由器:配 LAN 地址、开 ip_forward、masquerade、dnsmasq,插一台设备验证能拿 IP 上网。务必在不影响主网络的隔离环境里做。
- 思考题:为什么只开 ip_forward、不做 NAT,内网设备(私网地址)还是上不了外网?(私网地址在公网不可路由,0.6——必须 masquerade 改成公网源。)
- 进阶:列出你上面敲的所有命令里,哪些是"运行时状态"(重启即失)。想想要让这台机器重启后依然是路由器,每一条该怎么持久化——这就是 3.2 要系统解决的问题。