项目 GITHUB: https://github.com/ThisSeanZhang/landscape
为什么做 Landscape
想法出现是在一次 OpenWrt 崩溃。我明白崩溃并不是 OP 自身的问题.
应该是我选择的插件之间出现了兼容性的问题, 而每次修改 OP 的配置总是让我觉得战战兢兢, 要么是觉得配置好像没有生效, 要么太多的输入框和按钮展示在我面前.
学习 OpenWrt 的成本让我觉得很大, 所以我就在想是否能在通用发行版 Linux 的基础上, 实现一个自己的路由?
而那时正在学习 Rust (入门第 N 次) 和 eBPF, 手上正握着把锤子, 想找个东西敲打一番, 于是我的计划就开始了.
开始对于我自己也就这几个需求:
- 怎么彻底的抑制 PCDN 偷上行
- 怎么方便将内网设备更新 DDNS.
- 不同的网站针对不同的设备使用不同的出口进行访问(当时还不知道有那么多丰富的插件).
- 不要每次都刷整个系统, 程序可以直接升级. 并且最好是只导出一份文件就够了.
简单规划之后, 便开始进行实施了
NAT 的设计
NAT 能力演示: https://www.bilibili.com/video/BV1b8Tn6ZEaz
在使用组网软件的时候, 就看到了 tailscale 的一篇文章. 是关于 tailscale 是怎么进行 P2P 打洞的, 这给予了我灵感.
简要的流程是, 当两个设备要进行穿透时, 需要先向一台 STUN 服务器进行请求, 告知自己的地址.
服务器向双方告知对方的地址, 双方开始尝试互联, 所以可以利用这个机制, 如果要进行强力阻断的, 默认端口不可复用即可.
比如在连接存活期间:
客户端 A → STUN 服务器 B ✅ 允许
STUN 服务器 B → 路由 A' ✅ 允许, 然后路由转为 B → A
客户端 A → 另一个客户端 C ❌ 直接丢弃(不会按照 NAT4 那样创建新映射)
另一个客户端 C → 路由 A' ❌ 丢弃
所以将会被迫回退中继模式.
而允许进行 P2P 的只要放行即可, 行为与全锥一致, 这已经在一年多的使用中已被证实是可行的, 且对日常毫无影响.
而另外一个大头是 IPv6 的支持
在 op 上的 IPv6 我总觉得用起来很奇怪, 当我自己实现的时候我才明白具体的原因是什么.
首先是 IPv6 首选时长和上游给的时间一致的问题, 而 DHCPv6 虽然设计了 reconfigure 机制, 但是现在的大部分客户端都没支持.
所以当你重启路由后的一段时间, 虽然你重新获取了一个新的 IP 但是旧的 IPv6 一直有效, 导致你访问不了 v6 网站.
不过 landscape 中额外考虑了另一个场景, 也就是 IPv6 NPT, 不是将 IPv6 使用 nat66 的方式进行 IP 映射, 而是当有多网口时, 即使内网设备获得的是 A 网口的 IP, 流量实际也能从 B 网卡发出, 并自动能替换成 B 网卡获得的前缀信息.
还有 op 上不总是能固定后缀, 而 landscape 中不仅能固定后缀还能配合 DDNS 直接将 LAN 获得的 IP 直接写入运营商的 DNS 记录.
不同设备应用不同的规则
分流能力演示: https://www.bilibili.com/video/BV1Wy26BiEJW/
现有的科学上网分流, 都是对本地局域网内的所有设备应用, 但是我不想所有的设备都是走同一套规则.
比如, 开发主机是全局的. IoT 设备是全部走直连. 某些设备只有部分网站使用科学.
并且虽然只配置了一个 DNS 上游. 但是依据不同的 DNS 请求要与出口一致, 且这样天然就能拿到最终落地所在的 CDN 地址.
有看到部分人称为 DNS 跟踪, 我觉得称为 DNS 出口亲和可能更合适?
假设你想要使用某个新协议, 你需要等待某些作者进行合入现有的分流程序. 或者等待这个协议作者实现一套完整的分流.
landscape 将容器出口也作为与 WAN 网卡同级别的一等公民. 其中使用 tproxy 进行解耦. 只要容器内运行支持 tproxy 的程序即可进行流量处理.
多个容器间直接切换也是无缝的, 因为在 landscape 已经做好了分流, 容器内只需设置全局的配置就行.
且不同规则组的 DNS 缓存是隔离的. 不会因为融合了不同的策略, 导致 DNS 缓存相互覆盖.
比如:
A 网站在 X 策略组中是直连的 -> 得到 Ax IP. -> X 策略组缓存
A 网站在 Y 策略组中是由容器处理 -> DNS 请求通过容器 得到 Ay IP. -> Y 策略组缓存
但是对于 Anycast IP 是怎么处理呢? 目前你可以通过在容器中部署支持 Fake IP 的组件. 然后将部分网站的 DNS 上游指向这个容器即可
比如:
A 网站在 X 策略组中是直连的 -> 得到 Ax real IP.
B 网站在 X 策略组中是指向 容器 I 的 -> 得到 Bx fake IP.
C 网站在 X 策略组中是指向 容器 J 的 -> 得到 Cx real IP.
可以做到只有部分容易混淆的访问使用 FakeIP
只将必须的流量转到容器还能额外获得一个优点, 你的科学工具不必再处理直连流量. 更不容易炸, 且炸了也只影响你的海淘. 不影响你的直连. 而直连就和正常的上网一样, 所以延迟相比过科学会再低一点.
其余一些特点
安装: https://www.bilibili.com/video/BV1aZ8w6TEY9/
- 前后端完全分离, 所以你可以通过 API 控制所有 UI 上可以控制的所有行为, 也意味着你可以实现一套自己的 UI
- 可将所有的配置导出为一份文件, 并通过这一份文件恢复整个路由的配置
- 有 tui 工具能直接热备份+恢复, 不需要重启. 且有救援工具, 不小心配置错误还能连上