前情提要 https://www.v2ex.com/t/1034955
因为已经一年半了,不确定是否合适继续用原帖,所以新发一个。
我家路由器的基础打好了,确实很方便进行滚动演进,或者说快速迭代? 不管怎么说,在过去这段时间,又调整了一些东西、上线了一些东西、考虑了一些东西,稍微分享一下吧。
自动实现墙内域名分流的 autodirectdomain
所谓墙内域名,自然是为了用来解析加速的,解析的时候直接丢给预先配置的运营商 dns 就好了。 那么,什么样的域名可以丢给运营商 dns ?当然是不会被污染的域名。这里只是解析的环节走运营商,如果解析结果是境外 ip ,那默认还是要过梯的。 有了定义,如何确定一个域名是墙内域名呢?也很简单,如果这个域名原本会被污染,那么他的权威 dns 一定在墙外。例如,向 a.ns.facebook.com ,甚至哪个.gtld-servers.net 发一个查询 www.facebook.com 的 A 请求,结果请求还没到权威,就被墙抢答了。 注意到这点,那就好办多了。那就是,不考虑墙内 anycast 镜像,只要有任何一级权威在墙内,那么域名就可以直接查询,不会被污染。 为什么?因为墙是双向的。对于墙外用户来讲,如果向墙内权威查询一个可能被污染的域名,也会得到一个被污染的结果,相当于这个域名不可用。
根据以上原理,可以记录下进行递归查询的列表,再逐层解析其权威 dns 的 ip ,如果任何一个 ip 在墙内,那么这个域名(域)就可以被安全地加入“可以丢给墙内运营商 dns”的列表中。当然,实践的时候稍微复杂一些,还需要过期检测、黑白名单等等,在此不再赘述。 ( bash+tcpdump+dig )
ipman6s 服务:管理路由器内的 ipv6 地址
从运营商处拿到/60 ,如何进一步分配呢?这里对此部分进行了完全重写,允许 vlan 也获取公网 ipv6 网段的同时,允许整个系统,包括 lan ,更灵活地配置 ipv6 。
原本遇到的实际问题是,我曾想要双宽带一起跑 bt ,提交多个 ipv6 地址。这样势必会需要在原有地特定 vlan 上分配 ipv6 ,而且要针对不同的 ipv6 做策略路由/snpt 。这样就需要管理运营商下发的/60 ,将其拆成多个/64 ,根据 vlan 的配置进行下发。这样一来,某个 vlan 或者 lan 可以选择 fd 开头的私网地址,或者来自某条宽带的公网地址;也可以选择从特定的若干条宽带出,策略全部由 ipman6s 生成和管理。 但是,但是。好孩子不要学我。因为跑 bt 的时候很容易因为连接数过多触发反向墙,这个宽带的出口( ipv4 )就没法连接海外 ip 了(也有只是不能连接 udp 的情况,但是我主力用 hy2 )。所以模块虽然好用,但是目前还是有需要的时候限定 bt 在一条宽带上。算了,我也不怎么跑,就这样吧。 ( bash+radvd+ip6tables )
部分标准化的 docker 管理器
之前版本的路由器上 docker ,其实都是手工配置的。手工配置 run 参数表,手工建立 netns ,手工配置防火墙和路由规则,手工启动和停止,手工配置域名,手工管理一切。虽然有脚本,但是吧,就是很不正规。但是慢慢地,随着 docker 数量增多,以及内建了 mariadb 这样的数据库来存放一些日志文件,继续手工下去好像不太行了。 于是乎,重写了一个“类似于 docker”的简单的管理器,照着 docker-compose 尽量实现吧!如果不需要前面说的那些特殊规则的话,从外边 copy 一个 compose 也能尽量用的那种。当然,network 区块被无视了,高级功能需要自定义区块。
目前,我家路由器上跑着 mariadb 、grafana 、ubnt-ac 、chrony 等几个 docker 服务。 ( bash+yq )
适应更多 vlan 策略模块 ingw.d
还记得之前设计的 XC 网段吗?原本计划着把所有需要的 vlan 都接进去 XC 放给 INGW 做 ingw.d ,但是实践的时候发现,不如给 ingw.d 做一个子集,适合在不同 vlan 上实现的子集。所以目前重写了 ingw.d ,使得部分模块可以在不同 vlan 上工作,这样我就能确保我的摄像头没法和公网通信了!顺便地,再给他安排个内网 ntp ,妥。 ( bash )
快速隧道下线
什么是快速隧道下线?当某个隧道“完全”中断时,不等待一分钟一次地健康检查,而进行快速关断的动作,以便后续连接可以正常进行。目前的方法是在 primary ( id 最小的活跃隧道)内 ping 1.1.1.1 ,如果连续 3 个数据包没返回,那就执行快速下线。但是,显然我用的隧道是可以通过 icmp 的(例如在 hy 上封装一层 openvpn ),如果没法通过 icmp 的就没办法了。 针对上述情况,目前还在考虑中。考虑的方案有,执行 http/2 ping 主动探活,或者 dns 主动探活,或者 tcp 内容被动探活(即是,记录双向 tcp payload 流量)。三个方案都在考虑中。
不得不说,这一点就暴露出了明显的分体设计的劣势。如果是合体的程序,例如 clash 或者 surge 的话,是可以有更多方法知道隧道状态的。但是即便如此也不打算修改为合体程序,毕竟分体也有优势,例如便于调试、不会全体崩溃等等。
感觉有点走上邪路的 dnsroute
dnsroute ( dns 分流模块)得到了巨大的升级。支持了 geosite ,甚至支持了简单的表达式匹配、自行设定优先级等等……所以有点感觉走上邪路了。 依托的还是之前设计的 OWGW->DNSROUTE 的 conntrack 基础框架,目前看这个框架再进一步支持按 ip/端口/协议分流也能继续支撑,反正只处理首包。只是继续这么处理的话,如果 dnsroute 失效,掉回传统分流,怕是就有点接不住了。所以本模块仍然是可选件,可能永远都是可选件。 ( c++)
增加了这些东西,cpu 日常 idle 掉到 88%左右的水平了。( 70 个左右的隧道)因为每个隧道都有若干个独立进程,所以继续增加功能模块,特别是类似快速隧道下线这种还是要掂量一下的。有必要的话会考虑 c++甚至 golang 替换掉一部分模块以提高性能,不过目前看还是没什么大问题的。
以上,只是希望交流一下各种问题和思路。可能具体要怎么实现,都不是那么重要的事情。有任何意见或者想法,也欢迎交流。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.