Skip to content

为什么做 Landscape ​

想法出现是在一次 OpenWrt 崩溃。

崩溃本身并非 OpenWrt 的问题。如果只是使用原版 OpenWrt,那么确实挺稳定的;问题出在我用的几个第三方插件之间。反复遇到这类兼容性问题之后,我开始认真考虑换个思路。

长期使用中积累的问题 ​

NAT 策略粒度不够。 在我当时使用的固件和插件组合中,NAT 行为基本是全局设置,很难针对不同设备或者目标分开配置。比如组网是需要 NAT1,但其他程序却没这个必要,而且那种视频网站总是想偷你的上传。

插件配置缺少清晰的边界。 分流插件会统一修改系统中的 DNS、路由和防火墙状态。它们本身解决了很多问题,但不同设备的策略仍然共享同一套运行环境;插件之间一旦出现兼容问题或配置错误,被波及的往往远不止需要它们处理的那部分流量。

自定义固件更新比较繁琐。 OpenWrt 的 sysupgrade 可以保留标准配置,但我的自定义固件还包含额外的插件和文件。升级前需要逐一确认并备份,之后再重新刷入完整固件。自己编译固件耗时较长,构建环境或插件组合发生变化时,还可能在最后一步才发现失败。

内核版本和固件绑在一起。 内核及其模块需要与固件一起构建,不能像普通 Linux 发行版那样独立跟随较新的主线内核。新的内核功能以及新的安全补丁也只能等下次更新的时候才能用上。

设计上的选择 ​

因为刚好在学 Rust 和 eBPF , 所以也就没有选择 DPDK 或是 VPP. eBPF 程序可以动态加载并挂载到 XDP 和 TC,在内核中完成数据包处理,不必把所有流量送入用户态,也不需要再围绕 iptables 组织一整套转发流程。

这也决定了 Landscape 的边界。Landscape 不是一个新的路由发行版,而是直接运行在 Debian、Arch、openSUSE 等标准 Linux 系统上。配置集中保存在一个目录中,升级时替换二进制即可,数据迁移由程序在启动时完成。

策略则由 Flow 隔离。设备通过 IP 或 MAC 加入不同 Flow,每个 Flow 有各自的 DNS、出口。Landscape 默认采用比 NAT4 更严格的策略,再按端口、域名或 IP 为确实需要的流量放通 NAT1。 需要代理的流量可以导入容器,其他流量按照目的网卡直接发送;即使容器发生故障,直连流量还是能使用的.

这些问题已经困扰我许久,于是我决定编写一个自己的路由程序。Landscape 就是从这开始的。