§ 环境 03 · OpenWrt
快喵VPN 在 OpenWrt 路由器上的部署:旁路由与主路由
路由器上装快喵VPN 只有三个变量:CPU 架构、剩余 flash 与接法;三者确认后再装包,架构不符的失败率从 46% 降到 0,旁路由接法的回滚时间约 1 分钟。
- 最低系统
- OpenWrt 21.02
- 核心包体积
- 2.87 至 3.12 MB
- 剩余 flash
- ≥ 24 MB
- 本页采集
- 2026-11-08 → 11-09
§ 01 · 先定架构
旁路由还是主路由:先定接法,再装包
同一个 ipk 在两种接法下的配置完全不同,先装后想是路由器上最常见的返工来源。选接法只看两件事:谁负责拨号,谁负责分流。
图 1:两种接法的拓扑差异。旁路由只接管网关,主路由同时接管拨号与转发(2026-11-08 于 OpenWrt 23.05.3 采集)表 1:旁路由与主路由的接法对照(2026-11-08 至 11-09 实测)| 对比项 | 旁路由(网关模式) | 主路由(拨号 + 分流) |
|---|
| 谁拨号 | 原主路由,保持不动 | 本机 PPPoE 拨号 |
| 改动范围 | 只改 DHCP 下发的网关与 DNS | 整网出口全部经过本机 |
| 单点故障 | 旁路由宕机时全网断外网 | 本机宕机时全网断网 |
| 吞吐上限 | 受旁路由 CPU 与内网带宽限制 | 受 CPU 与 NAT 转发能力限制 |
| 回滚成本 | 把网关改回去即可,1 分钟 | 需重新接线与拨号,10 分钟以上 |
| 适合谁 | 已有稳定主路由、只想加一层分流 | 希望一台设备统一出口 |
三条选择依据
- 不想动现有网络结构时选旁路由:只需要在 DHCP 里把网关与 DNS 指向旁路由地址,物理接线一根网线即可。
- 希望一台设备统管拨号、分流与防火墙时选主路由:接线更简单,但拨号参数、MTU 与防火墙都要在本机维护。
- 两者都想要时选混合接法:主路由拨号,旁路由做分流与出口,缺点是故障时定位跨两台设备。
图 2:三种接法的改动面与回滚成本。旁路由改动面最小,混合接法定位成本最高(2026-11-08 绘制)§ 02 · 装前条件
架构、flash、内核与 feeds:四项里任一项不对,opkg 会直接拒绝
OpenWrt 上的安装失败大多发生在 opkg 解析阶段,而不是运行阶段。四项条件可以在装包之前全部确认。
表 2:OpenWrt 装前条件(2026-11-08 于三台设备核实)| 条件 | 要求 | 确认命令 | 不满足时 |
|---|
| 系统版本 | OpenWrt 21.02 及以上 | cat /etc/openwrt_release | feeds 依赖找不到 |
| 内核版本 | 5.4 及以上 | uname -r | 3.6.9 之后的包无法加载 |
| CPU 架构 | aarch64 / x86_64 / mipsel_24kc | opkg print-architecture | 架构不匹配,直接拒绝 |
| 剩余 flash | ≥ 24 MB(含 LuCI 插件 31 MB) | df -h /overlay | 安装到一半空间不足 |
| 软件源 | feeds 与系统大版本一致 | cat /etc/opkg/distfeeds.conf | 依赖包版本冲突 |
架构怎么看
opkg print-architecture 第一行是主架构,例如 aarch64_cortex-a53 或 mipsel_24kc。ipk 文件名里的架构必须出现在这份列表里,否则 opkg 报 “package architecture ... not compatible”。文件名里的 generic 后缀表示该包不绑定具体子架构,可以装在多数同主架构设备上。
flash 空间为什么按 overlay 算
固件本身在只读分区里,装包写的是 overlay 分区。8 MB flash 的老设备 overlay 通常只剩 3 至 5 MB,装不下 3.1 MB 的核心包加 146 KB 的插件,表现为 “No space left on device”。判断时看 df -h /overlay 的可用列,不是看 / 的可用列。
装前四条命令
# cat /etc/openwrt_release | head -4
# uname -r
# opkg print-architecture
# df -h /overlay
OpenWrt 21.02 与 22.03 的 libc 版本不同,跨大版本装包会报符号未定义。确认 distfeeds.conf 里的版本号与 /etc/openwrt_release 一致再动手。
§ 03 · 装包四步
装包四步:刷源、装核心、装插件、重启服务
四步里第三步最容易被跳过。插件与核心版本不一致时,界面能开但选项不生效,比直接报错更难查。
STEP 01
刷新软件源
执行 opkg update,看到 Collected errors 为 0 才算成功。源不可达时先解决网络,不要在离线状态硬装。
STEP 02
安装核心包
按架构选 ipk:aarch64_generic / x86_64 / mipsel_24kc 三种,装完执行 /etc/init.d/kuaimiao enable 与 start。
STEP 03
安装 LuCI 插件
插件包 luci-app-kuaimiao 与核心包版本号必须一致(同为 3.9.6-1),装完刷新浏览器缓存再进界面。
STEP 04
重启服务并确认监听
用 netstat -lntp 确认端口,用 logread | tail -20 看启动日志是否出现 error。
表 3:三个核心 ipk 的适用设备(与安装包清单一致)| 文件名 | 体积 | 适用架构 | 典型设备 |
|---|
| kuaimiao_3.9.6-1_x86_64.ipk | 3.12 MB | x86_64 | 软路由、虚拟机、NAS 内嵌 OpenWrt |
| kuaimiao_3.9.6-1_aarch64_generic.ipk | 3.04 MB | aarch64_generic | GL-MT3000、红米 AX6000 等 ARM 路由 |
| kuaimiao_3.9.6-1_mipsel_24kc.ipk | 2.87 MB | mipsel_24kc | 小米 AX3000、MT7621 平台 |
安装与启动
# opkg update
# opkg install /tmp/kuaimiao_3.9.6-1_aarch64_generic.ipk
# opkg install /tmp/luci-app-kuaimiao_3.9.6-1_all.ipk
# /etc/init.d/kuaimiao enable && /etc/init.d/kuaimiao start
# logread | tail -20
- opkg install 失败时先看依赖名,再回 feeds 里确认包存在,不要在错误提示里找架构问题。
- 插件装完界面打不开时,清一次浏览器缓存或换无痕窗口,多半是旧的 LuCI 静态资源被缓存。
- 核心包升级前先 stop 服务,升级后再 start;直接覆盖安装会留下两个进程抢同一端口。
- 卸载用 opkg remove 而不是删文件,删文件会留下启动脚本,重启后服务仍会尝试拉起。
§ 04 · 旁路由接法
旁路由接法:改两处,验证三处
旁路由的配置面很小,但有三个隐含前提:旁路由自身能上网、DHCP 只由一台设备下发、防火墙允许转发。任一条不成立,表现都是全网断网。
第一步:给旁路由一个固定地址
在与主路由同网段的地址里挑一个未被占用的地址,例如主路由为 192.168.1.1 时给旁路由 192.168.1.2。网关必须指向主路由,DNS 可以指向公共解析或主路由,取决于是否要接管解析。
第二步:主路由的 DHCP 指向旁路由
在主路由的 DHCP 设置里把默认网关与 DNS 改成旁路由地址,租期建议缩短到 10 分钟,便于回滚时快速生效。若主路由不支持修改 DHCP 下发网关,这条路走不通,只能改用主路由接法。
第三步:旁路由上关掉 DHCP 并放行转发
旁路由侧确认
# uci show dhcp.lan.ignore # 应为 1
# uci show firewall | grep -i masq
# iptables -t nat -L POSTROUTING -n | head
# sysctl net.ipv4.ip_forward # 应为 1
表 4:旁路由常见故障与判断依据(2026-11-09 采集)| 现象 | 判断依据 | 处理方向 |
|---|
| 全网断外网 | 旁路由自身 ping 不通外网 | 先修旁路由上网,再谈分流 |
| 部分设备断网 | 这些设备仍在用旧网关 | 缩短 DHCP 租期或手动续租 |
| 能上外网不能上内网 | 内网网段未加直连规则 | 把私网网段加入直连 |
| 连接正常但速度减半 | 旁路由单臂转发受限于网口 | 改用主路由接法或换多网口设备 |
第四步:DNS 接管与一步回滚
旁路由接法里 DNS 有两种处理:指向公共解析(简单,但分流按域名判断时会失效),或指回旁路由自身让 dnsmasq 接管(能按域名分流,但旁路由一挂全网解析失败)。日常使用建议后者,因为按域名分流是这套接法的主要收益。
回滚只需把主路由 DHCP 下发的网关与 DNS 改回主路由地址,再把租期改成 1 分钟逼设备续租,两分钟内全网恢复。回滚后旁路由可以保留在线,不影响任何设备。
- 改 DHCP 前先记录原值,截图即可,别依赖记忆。
- 租期从 24 小时改为 10 分钟,回滚时设备才会快速换回原网关。
- DNS 接管时把旁路由地址同时写进 DHCP 的 DNS 字段,只写网关不生效。
图 3:旁路由接法下的流量路径。设备到旁路由再到主路由,旁路由承担一次额外转发(2026-11-09 采集)
图 4:旁路由接法的改动面。只需两处配置,回滚一步即可(2026-11-09 绘制)§ 05 · 主路由接法
主路由接法:拨号、MTU 与防火墙一起配
主路由接法把本机放到出口位置,拨号参数错一位就上不了网。三个关键参数:PPPoE 账号、MTU 1492、防火墙区域划分。
STEP 01
接线:光猫桥接,网线进 WAN 口
光猫必须桥接,否则双层 NAT 会让分流转发失效;接线前先记录原主路由的账号密码。
STEP 02
建立 PPPoE 拨号
网络 → 接口 → WAN 选择 PPPoE 协议,填账号;MTU 填 1492,MSS 钳制开启。
STEP 03
划分防火墙区域
WAN 区域输入拒绝、输出接受;LAN 区域输入接受;转发区域 LAN 到 WAN 允许。
STEP 04
启用分流并验证
启用后从 LAN 侧设备访问外网,同时用 traceroute 确认第一跳是主路由地址。
MTU 为什么是 1492
PPPoE 有 8 字节封装开销,1500 减 8 得 1492。MTU 填 1500 时,大包会被静默丢弃,表现为网页能开、视频卡住、下载中断。判断办法:ping -M do -s 1472 8.8.8.8 不通而 -s 1450 通,说明链路 MTU 被压到 1492 附近。
表 5:主路由接法的关键参数(2026-11-09 于 x86_64 虚拟机与 GL-MT3000 复核)| 参数 | 取值 | 填错的后果 |
|---|
| PPPoE MTU | 1492 | 大包被丢,网页能开、视频卡 |
| MSS 钳制 | 开启(clamp to PMTU) | TCP 建连后立即卡死 |
| 转发区域 | LAN → WAN 允许 | 能上路由管理页但设备无外网 |
| DNS 转发 | dnsmasq 监听 LAN 口 | 设备解析失败,域名打不开 |
图 5:主路由接法的链路与 MTU 位点。MTU 在 PPPoE 封装处生效,钳制在转发层生效(2026-11-09 采集)§ 06 · 混合接法
混合接法:主路由拨号,旁路由做出口,故障定位分两段
混合接法把拨号与分流拆到两台设备,好处是任一台崩溃时另一半仍可工作,代价是排障要按两段走。
表 6:混合接法的分段定位(2026-11-09 采集)| 现象 | 先查哪一段 | 证据 |
|---|
| 全网断网 | 主路由拨号段 | 主路由 WAN 状态是否为已连接 |
| 能上网但分流不生效 | 旁路由分流段 | 旁路由日志里是否有规则命中记录 |
| 延迟抖动大 | 两段之间的跳数 | traceroute 第二跳是否出现双倍延迟 |
| 内网设备互访失败 | 旁路由直连规则 | 私网网段是否被误分流 |
为什么推荐混合接法
家庭网络里最常见的故障是拨号掉线,这类故障与分流无关。混合接法把拨号留在原来的主路由上,分流设备出问题时只需把 DHCP 网关改回主路由,整网即可恢复,平均恢复时间从改接线并重新拨号的 12 分钟压到 1 分钟以内。
- 两台设备之间建议用有线连接,无线中继会引入额外 8 至 30 ms 抖动。
- 旁路由的地址不要落在主路由的 DHCP 池内,避免地址冲突。
- 两段的时间同步都要开,日志时间不一致时无法对齐故障时刻。
- 混合接法下 MTU 只需在主路由设置,旁路由按默认 1500 透传即可。
§ 07 · 防火墙差异
fw3 与 fw4:同样的规则,两套写法
OpenWrt 22.03 起默认使用 fw4(nftables),21.02 及以前是 fw3(iptables)。照旧教程写的规则在 fw4 上不生效,是 3.8.7 之前版本最常被反馈的问题。
表 7:fw3 与 fw4 的差异(2026-11-09 于 21.02 与 23.05 对照)| 项目 | fw3(21.02 及以前) | fw4(22.03 起) |
|---|
| 底层工具 | iptables / ip6tables | nftables |
| 查看规则 | iptables -t nat -L -n | nft list ruleset |
| MASQUERADE | 在 nat 表 POSTROUTING | 在 nft 的 inet fw4 表里 |
| 自定义链 | 写入 /etc/firewall.user | 写入 /etc/nftables.d/*.nft |
| 规则生效 | /etc/init.d/firewall restart | fw4 reload |
为什么旧规则“看起来生效了”
fw3 的规则写在 /etc/firewall.user 里,fw4 不再读取该文件。文件还在、语法也还算合法,于是没人报错,但规则没进 nft 表。判断办法只有一条:nft list ruleset | grep -i masq,看不到条目就是没生效。
确认转发是否真的在改写源地址
# nft list ruleset | grep -i masq
# nft list chain inet fw4 srcnat | head -20
# iptables -t nat -L POSTROUTING -n 2>/dev/null | head # fw4 下通常为空
在 fw4 上执行 iptables 命令不会报错,因为兼容层会把规则翻译成 nft 语句,但翻译结果不一定落到 inet fw4 表里。判断时以 nft list ruleset 为准。
§ 08 · 吞吐实测
三种架构的吞吐:数字来自同一份测试脚本
吞吐是选设备的主要依据。同一份 ipk 在三种架构上的差异可以达到 10 倍,与固件优化无关,纯粹是 CPU 加解密能力。
表 8:三种架构的吞吐实测(单连接,2026-11-08 至 11-09)| 设备 / 架构 | CPU | 吞吐中位 | 1000 个包的抖动 |
|---|
| x86_64 虚拟机 | 2 vCPU(宿主 i7-12700H) | 780 Mbps | 1.8 ms |
| GL-MT3000 / aarch64 | 双核 1.3 GHz | 350 Mbps | 4.2 ms |
| 小米 AX3000 / mipsel_24kc | 双核 880 MHz | 118 Mbps | 9.6 ms |
测试脚本为单线程 TLS 下载 200 MB,取三次中位;抖动按 1000 个 ICMP 包的首尾差计。mipsel_24kc 平台缺少 AES 指令集,是吞吐落在 118 Mbps 的主因,与客户端版本无关。
图 6:三种架构的吞吐对比。x86_64 与 mipsel_24kc 相差 6.6 倍(2026-11-08 至 11-09 采集)
图 7:抖动分布随架构变化。mipsel_24kc 的尾部分布明显更宽(样本各 1000 包)为什么同一份包差 6 倍
差异来自加解密指令集,不来自客户端代码。x86_64 有 AES-NI,aarch64 多数带 ARMv8 Crypto 扩展,mipsel_24kc 两者都没有,只能走软件实现,单核跑满时约 120 Mbps。同一台设备上升级固件对吞吐的影响通常在 5% 以内,换架构的影响在 4 倍以上,选设备比调固件更重要。
另一个容易忽略的因素是会话表大小:并发 200 个连接时,mipsel_24kc 的 NAT 会话表开始出现丢包,而 x86_64 在 2000 个连接时仍稳定。家用场景通常达不到这个量级,但多设备同时看视频时会更早触发。
选设备的三个经验值
- 带宽 300 Mbps 以下:aarch64 双核即可,mipsel_24kc 在 150 Mbps 以上会明显排队。
- 带宽 500 Mbps 以上:优先 x86_64,或支持 AES 指令集的 ARM 四核设备。
- 需要多设备并发时,按单设备吞吐的 60% 估算,因为分流规则与 NAT 会话表都会额外消耗 CPU。
§ 09 · 路由器侧报错
路由器侧四类高频报错与判断顺序
路由器上的报错比其他两个环境更集中:几乎全部发生在 opkg 解析、服务启动与转发规则三处。
表 9:四类高频报错与取证动作(2026-11-09 采集)| 报错片段 | 成因 | 取证动作 |
|---|
| package architecture ... not compatible | ipk 架构与设备不符 | opkg print-architecture 对比文件名 |
| satisfy_dependencies_for: cannot satisfy | feeds 未刷新或版本不符 | opkg update 后看 distfeeds 版本 |
| No space left on device | overlay 空间不足 | df -h /overlay |
| kuaimiao: not found | 只删了文件未 remove 包 | opkg remove 后重启 |
- 依赖报错里的包名要与 feeds 里的实际包名一致,名字对不上时先怀疑 distfeeds 版本。
- 空间不足时优先删旧固件备份,再考虑扩容 overlay,不要直接删系统包。
- 服务起不来时先看 logread 最后 20 行,再考虑重装,重装会丢掉已有配置。
- 卸载后端口仍被占用,说明进程没退出,先 kill 再 remove。
四类报错里,只有第一类能在装包之前排除。其余三类都发生在装包或启动之后,因此装前确认架构与空间的价值最高:它把最耗时的一类问题提前到了 30 秒内。
从 2026-10 到 11 月的 96 次路由器部署记录看,架构不符 44 次(占 46%)、空间不足 21 次(22%)、feeds 版本不符 18 次(19%)、卸载残留 13 次(13%)。前两类都能在装前用四条命令挡掉,合计 65%。
图 8:四类报错的取证动作矩阵。前三类在装包阶段,最后一类在卸载阶段(2026-11-09 绘制)§ 10 · 回退
回退到 3.6.9:什么时候需要,怎么做
回退在路由器上比在桌面端更常见,因为内核版本不能随时升级。3.6.9 是官方保留的回退锚点。
两个需要回退的条件
- 内核为 4.4 系列:3.9.x 的 DNS 分流会在启动 40 秒内崩溃,回退到 3.6.9 可复现地恢复。
- 固件为 21.02 且未升级 fw4:3.8.7 之后的转发规则依赖 nftables,旧固件上表现为能连不能用。
回退三步
# /etc/init.d/kuaimiao stop
# opkg remove luci-app-kuaimiao kuaimiao
# opkg install /tmp/kuaimiao_3.6.9-1_aarch64_generic.ipk
# /etc/init.d/kuaimiao start && logread | tail -10
回退后要重新确认两件事:配置目录是否被新版本改写过、防火墙规则是否残留 fw4 写法。前者看 /etc/config/kuaimiao 的修改时间,后者用 nft list ruleset 确认没有重复条目。
- 回退锚点版本
- 3.6.9(2026-07-02)
- 适用内核
- 4.4 及以上
- 回退耗时
- 约 4 分钟
- 需重配项
- 分流规则、DNS 接管
数据 · 关键数字
关键数字与它们的采集条件
每个数字后面都跟着条件,换了机器与版本数字会变,判断顺序不变。下面七条是本站各页共用的基础数据。
在 OpenWrt 23.05.3 x86_64 环境下实测吞吐中位 780 Mbps,单连接样本 3 次取中位(核心 3.9.6,2026-11-08)。
aarch64 双核 1.3 GHz 设备吞吐 350 Mbps,mipsel_24kc 双核 880 MHz 设备 118 Mbps,测试条件为千兆有线且未开硬件加速。
核心包 3.1 MB,加 LuCI 插件后 3.3 MB,overlay 可用空间建议不低于 24 与 31 MB,来源为 ipk 清单。
架构不符在 96 次部署记录中占 44 次(46%),统计数据来自 2026-10 至 11 月的部署日志。
旁路由接法的回滚耗时约 1 分钟,主路由接法约 12 分钟,测试环境为同一台 x86_64 设备(2026-11-09)。
MTU 1492 对应 PPPoE 的 8 字节封装开销,填 1500 时大包丢弃率在实测中达到 12%(1400 字节负载条件)。
fw4 与 fw3 的规则文件路径不同,判断规则是否生效只需 1 条命令,环境为 21.02 与 23.05 对照(2026-11-09 采样)。
这七条数据在安装页、校验页与排错页里被反复引用,三处数字始终一致;若你发现某页与另一页冲突,以数据采集日期较新的那一页为准,同时欢迎按页脚邮箱反馈。
§ 11 · 采集口径
本页数字的三台设备
路由器侧的数值受固件、CPU 与网络环境影响最大,因此每张表都标了设备。换设备后数字会变,判断顺序不变。
- x86_64 采集机
- OpenWrt 23.05.3 · KVM 2 vCPU
- aarch64 采集机
- GL-MT3000 · 双核 1.3 GHz
- mipsel 采集机
- 小米 AX3000 · 双核 880 MHz
- 核心版本
- 3.9.6
可复测有线连接未开硬件加速单连接样本
吞吐测试走有线千兆,未开启软件或硬件加速,未做多队列优化;抖动测试使用 1000 个 ICMP 包,间隔 20 ms。若你的结果差异超过 30%,先确认是否开启了硬件加速,它会显著抬高吞吐但会隐藏 MTU 问题。
- 所有命令在 OpenWrt 23.05.3 上验证,21.02 上的 fw3 写法另见表 7。
- 吞吐数字来自单连接,多连接并发会因 CPU 排队而下降。
- 快照与备份在测试前完成,测试后已恢复原固件配置。
- 本页不含任何账号信息,只描述部署与验证行为。
三台设备的固件均为官方稳定分支,未刷第三方编译版本。第三方固件若裁剪了 nftables 或 dnsmasq 组件,本节命令可能部分不可用,此时以 opkg list-installed 的输出为准确认组件是否在位。