1
yuanfa 246 天前
大佬!
|
2
tediorelee 246 天前
挖趣这也太复杂了
|
3
cJ8SxGOWRH0LSelC 246 天前
太长了, 没看完
|
4
Mrealy 246 天前
大佬,这么多字我也看完了。
|
5
yyysuo 246 天前
这就有点高端了。
|
6
x86 246 天前
今天刷小红书看一个评论的帖子分体水冷都上了,e5 做的软路由
|
7
YGBlvcAK 246 天前 via Android
大佬牛逼,我只是用 debian 玩旁路由,你这是整了个主路由!
|
8
AEnjoyable 246 天前
我以为的软路由:op ( ROS,ikuai )+ap+交换机
佬的软路由:自己实现?+ap |
9
JensenQian 246 天前 via Android
快进到家里上机柜
|
10
rrfeng 246 天前 1
这不得天天玩路由器,原来路由器=PS 是有道理的
|
11
Jeremial 246 天前 1
每个字都认识, 但是加一起不认识了
|
12
hahaha121 246 天前
好家伙好家伙
|
13
NeoChen 246 天前 via iPhone 3
你这跟谁的风,没人跟得上你的风
|
14
Jirajine 246 天前
感觉你这些 netns 之间高度耦合,那分这些“模块”意义在哪里。大部分需求单机策略路由+netfilter+广泛使用的用户态程序都能解决,再不行起个 tun/tap 全发到用户态自己想怎么搓就怎么搓。
自己跑 recursive 解析器意义也不大。 |
15
jsq2627 246 天前
自建 recursive ,对于没有缓存的域名那岂不是慢上天了?
|
16
apiman 246 天前
都没勇气全部看完,每一个字都认识,组合在一起不知道大佬在说啥
|
17
zhuantouer 246 天前 via Android
高端玩家,好奇 op 啥工作背景,怎么这么专业,纯爱好那就 orz 了
|
18
povsister 246 天前 via iPhone
分流思路和现在各种代理 core 差不多,而且在 dns route 上也摒弃了 FakeDNS 的路子好评。
但是,什么?你用 C++写的?还搓了这么多轮子?这是真大佬惹不起惹不起。 |
19
kkk9 246 天前
op 配置好可以打包镜像封装 OS 开卖,就叫 ChinaRouteOS
|
20
s4nd 246 天前
你有勇气写这么多,我却没有勇气看完
|
21
aptupdate 246 天前 via iPhone
怎么和我玩的软路由不太一样。。。
|
22
dodakt 246 天前
|
23
MeteorVIP 246 天前
你这确实很高端喔,虽然我看不懂,
但是我就想问,掉线,网速慢会被老婆骂吗? |
24
maybeonly OP @Jirajine
耦合并没有那么深,重要性也是分层的。 比如在外边,开着公网 ssh 的话(实际上就是),只要三个核心的模块( INGW ,OWGW ,RTGW )活着就能连回去。当然对应的 WAN 得正常。 然后一些是重要模块,比如 DNSIW ,DNSOW ,RECURSIVE ,DNSROUTE ,这些正常工作的话里边可以正常上网。 不仅仅各种隧道是模块化的,连入 VPN 、ADBLOCK 这些也都是模块化的。 再有就是,分 netns 是为了能有更强的扩展能力,也是为了每个 netns 里规则相对清晰,更是可以实现路由和 nat 分离,这一点在 dnsroute 里有集中的体现。 核心模块搭起来的是一个框架,然后就可以往上附着各种模块。 还有一些模块不是以 netns 的形式出现的,比如存在一个 ingw.d 模块,可以设置某些客户端( ip/ip6/mac )是不是使用去广告 dns ,是只有常规端口过梯还是所有端口过梯,etc.。更别说还有隧道管理器、流量监控之类的东西,纯属外围模块。又比如如果有需求,可以很轻松地给一个或多个 WAN 添加 nat1 模块而不影响整体,之类的。 @jsq2627 自建递归是一种权衡的选择。 主要目的是为了给没有在名单里的域名兜底,也从根本上杜绝 dns 泄漏之类的问题。 很久很久以前是用黑名单解析境外个别网站的,后来经常因为名单维护不及时而有时候连不上很恼火,逐渐改成了现在这个样子。 实际上没有想象的那么慢,例如解析 www.google.com ,实际上.com 是几乎肯定被缓存的,只需要 2rtt 就能解到。 复杂一点的,比如 www.163.com ,要 cname 两次,需要 7rtt 才能解析出来(当然 163 显然是在墙内白名单里的) 如果觉得有必要可以用名单手工指向墙内或墙外。 @povsister dns 分流这一点还是相信自己的创造力的。 现代专业梯子分流都是基于全用户态实现,dae 将无需代理的部分绕过了梯子用户态。 实际上这些软件,特别是 dae 之前的软件,设计场景都是单机使用,如果用在软路由上,就不可避免地会经常出现“为什么不过墙的网络也受影响”“啊,我改个梯子把整个网络搞坏了”“所以还是旁路由好”之类的情况。dae 一定程度上解决了第一个问题。 这边的实现,将调度模块与隧道模块分离,很大程度上解决了第二个问题。 通过自动维护的映射表( LAN 通过 ip nei ,openvpn 通过 status.log ,wg 通过 allowedips ),解决 v4/v6 映射的问题。同时,考虑隧道可用性,匹配最佳隧道,对首包用用户态通过 mac 地址选择下一跳,然后根据回包 mac 地址匹配 conntrack ,并且在后续甩掉用户态程序全依赖 conntrack ,极大程度保证了首包以外的性能,而且 dnsroute 本身负载很低,也解决了第一个问题——这一段肯定够写个专利了。 c 艹虽然确实比较艹,但是真的是很好用的。应该说最早还在用 dd-wrt 的时候,就有 c++写的一些其他模块在用了,所以说形成路径依赖了吧,那时候肯定是 2012 年之前的事情了。 |
25
maybeonly OP @MeteorVIP
网速慢会被老婆骂,广告过滤列表过滤不掉广告会被老婆骂,dns 解锁不灵会被老婆骂,老婆在外边连不上回家的 vpn 也会骂。 好在这些年了除了在有计划的调整之外,只有硬件故障和电力故障能搞坏它。 |
27
KazeW 246 天前
这 这才是软路由?
佬这不是跟风,是平地起狂风 |
29
zylll520 246 天前
大佬独领风骚👍
|
30
shunia 246 天前
不对,这不是我要上的车!
|
31
defunct9 246 天前
大佬买个 AS 域,折腾 BGP 吧
|
32
hi2hi 246 天前
大佬!太强了
|
33
povsister 246 天前
@maybeonly #24
DNS 分流实现思路和我一样,都是“不过墙的网络完全不走梯子”,但是我选了继续完善旁路由方案,对于 conntrack 部分我还是依赖主路由的路由表和防火墙的。给你这个全手搓的 DNS 分流跪了 Orz 不过我的帖子里,@mohumohu 提出了一个很有意思的问题: 有些网站会有区域限制,全真 IP 的情况下,如果两个网站解析到同一个 anycast IP ,而且域名嗅探失败的情况下,基于 conntrack 这一套 L3 的分流,如何正确选择代理隧道? 举个例子:假设 Netflix 套了 Cloudflare 的 CDN ,解锁 NF 需要美国 IP 。假设 DMM 也套了 CF 的 CDN ,解锁 DMM 需要日本 IP 。但因为 CF 的全球 CDN 网络,这两个站解析出的 IP 地址都是同一个 anycast 地址。 代理实现越靠下层,则会损失越多偏上层的信息。 我思来想去感觉很无解,随着 http3 和加密 SNI 普及,IP 数据包中的域名嗅探会变得越来越难,那么全真 IP 下的域名分流机制可能会始终面临这个痛点。 |
34
maybeonly OP @povsister 这个问题思考过,并没有那么疼。
首先,基本上没可能解析到同一个 anycast ip 。大厂的 cdn ip 也是专用的。好吧,假设他真的解析到同一个 anycast ip 了。 其次,比较现实的情况是,使用了两个不同的 dns 解锁机,分别解析到商家的美国解锁机和日本解锁机上,那这俩 ip 显然也不一样。 第三,更现实的情况,真实场景下,同一个用户/客户端几乎不可能同时用 nf 和 dmm 。所以实现的时候有考虑源 ip*目的 ip 做匹配,假如电视上看 nf ,手机上玩 dmm ,那是一点都不会出问题的。就算在同一台机器上切换,只要别来回切,后续解析成功的规则会覆盖前一个,而之前建立的 tcp/udp 连接则不会断——这里 dns 解析的结果是缓存在递归里的,而 dnsroute 会把 ttl 改小让用户不要太久不请求。 整体上来讲,不可能完全避免这类问题,但是现在的实现,已经可以让这类问题发生的几率足够小了。 至于嗅探,还是算了吧,当时也考虑到 ech (当时还是 esni ),从开头就没有打算做。 |
35
Jirajine 246 天前
@maybeonly #24 你用一堆 netns 组了个虚拟集群,数据包发过来发过去,这开销一点不比用户态低啊。
复杂度这么高,能保证 correctness 吗,比如任何情况下任意客户端的任意 dns 请求和后续实际请求能够路由到相同的外部接口。 那些代理软件确实不适合在路由器上使用,它们提供的功能根本就不是路由器需要的。路由器只要做好两件事:把不同客户端的出战连接路由到不同外部接口;追踪入站连接,回程路由到来源的接口。其他的你想用什么隧道、起什么服务、vpn 入站、通过 ip/mac/vlan 等方式识别客户端等等都是全部解耦、互不影响的。其他更复杂需求客户端自己做更合适。 |
36
Jirajine 246 天前
@povsister #33 因为你在尝试在错误的 layer 解决问题。开两个 firefox container ,一个走美国代理打开 netflix 、一个走日本代理打开 dmm 不就完事了,什么规则、路由、dns 都不需要。
|
37
maybeonly OP @Jirajine
> 你用一堆 netns 组了个虚拟集群,数据包发过来发过去,这开销一点不比用户态低啊。 没错,参见设计目标第二条:并不是追求极致性能。 p.s. 即使是这样的耦合,即使效率可能比不上用户态,调试和修改起来也会比单个用户态程序容易太多了。以及用户态同样要面对和其他模块(比如 vpn )交流的问题。 > 比如任何情况下任意客户端的任意 dns 请求和后续实际请求能够路由到相同的外部接口。 对于 dnsroute 列表内的域名来说,强保证同一个出口。 对于其他的,经过权衡利弊,故障切换比较重要,不保证同一个出口。否则对于 TTL 比较长的普通域名,靠前的隧道 up/down 会很难受。 > 路由器只要做好两件事:把不同客户端的出战连接路由到不同外部接口;追踪入站连接,回程路由到来源的接口。 这正是三个核心 GW+重要模块 DNSROUTE 的功能。如果需要依赖 DNS 做路由分流,那么这里混进一点 DNS 不可避免。 而且这里设计 DNSROUTE 只是“重要”,也就是说,必要的时候可以从核心模块上拆下来(当然功能也就没了)。 > 其他的你想用什么隧道、起什么服务、vpn 入站、通过 ip/mac/vlan 等方式识别客户端等等都是全部解耦、互不影响的。 这个确实全部解耦了。识别客户端在 INGW 中的 ingw.d 模块(还特别出现了 NET-XC ,就是为了把 VPN 入站的也拉过来),服务是单独的可拆卸模块(除了几个 DNS 是耦合度较高的),VPN 入站也是单独的模块(现在实现了 openvpn 和 wg 两个完全独立的模块),VPN 出站每个 VPN 抽象为一个隧道和其他 VPN 互不影响(串接除外)。 > 其他更复杂需求客户端自己做更合适。 算了,各种策略还是从路由器上下发吧,这是设计哲学的问题。ingw.d 很大程度上也是为了干这个。 |
38
huangya 246 天前
这些配置,有些可不可以整理一下放 github ?
|
39
Jirajine 246 天前
@maybeonly #37
> 调试修改起来比单个用户态程序容易太多 好吧,你是写 Cpp 的,能够理解😂 不过用户态一个函数能实现的功能在系统网络栈配合路由和规则做,正常来说最大的优势就是性能了。模块之间如果需要交流,那说明是耦合到一起的。 如果你的 vpn 入站需要路由除访问内部资源以外的流量,那是不是因为你这一套做了太多该在客户端做的,从而不够 portable 。 |
40
maybeonly OP @Jirajine
> 不过用户态一个函数能实现的功能在系统网络栈配合路由和规则做,正常来说最大的优势就是性能了。模块之间如果需要交流,那说明是耦合到一起的。 后面的 “交流” 指的是数据流转,比如后面挂了 3 个不同的梯子,那么数据总是得从调度进程到梯子进程的……不管整合不整合梯子都是 clash 既视感。 另一方面,在现实中,运维水平也是不得不考虑的…… 所以这里的取舍是,选择 netns 集群便于维护的特点而放弃极致性能(其实也没多差)。 > 如果你的 vpn 入站需要路由除访问内部资源以外的流量,那是不是因为你这一套做了太多该在客户端做的,从而不够 portable 。 不是很确定你要表述什么。客户端连上入站 vpn 什么都能访问,就和连上 wifi 几乎一样(除了 2 层)。vpn 入站模块只需要路由器给转发特定端口就行。 现在的客户端可不是以前了,电脑怎么都好说,手机、平板、电视,IoT……还是设计哲学问题,我不想在客户端放复杂的东西,能连个不同的 ssid 就是极限了。 |
41
povsister 245 天前
@Jirajine #36
不能算在错误的 layer 解决问题吧,只能说是:把解决的问题的阶段下沉,对内网终端设备隐形。 然而把方案下沉,其实哲学意义上,就意味着解决问题时能获取的有效信息会减少。 这和运营商选择把反诈插件放在用户侧光猫里是一样的道理,只有足够贴近用户,才能提高反诈预警的准确性(只是举个例子哈,不对反诈这个东西做任何评价。 说到底,我和 OP 的哲学是一样的,能在网关解决的问题绝不在客户端上解决。 |
42
Jirajine 245 天前
@maybeonly #40 很多事情在客户端做更适合也更简单,比如把不同的 app 路由到不同的接口,你在网关就没有足够的信息来做;再比如 dnsroute ,不如浏览器自己分配不同的 tab 走不同的代理。
至于电视、iot 设备,这些直接在网关全局路由到某个接口就行。 在外面上网还要走 vpn 连回家的话,开销就不是一般的了。 |
43
kylix 245 天前
好详细,先收藏,再慢慢看~~~
|
44
povsister 245 天前
@maybeonly #34 感谢分享思路!
这个问题我个人猜测应该是不会那么痛,但是明显还是大佬思考更细致。 我赞同你对现实情况的考量,只要路由选择上添加 srcIP - dstIP 做匹配,把不同终端的路由选择分割开,就能极大缓解这一问题。 目前我自己的实现是:只做了 dstIP 的路由规则,后续会抽空加上大佬的 srcIP 路由匹配策略。 另外咨询一个问题,大佬的 DNS route 的有效期是怎么计算的?什么时候废止这条路由表? 是靠客户端的 DNS 请求刷新吗? |
46
maybeonly OP @povsister
简要流程: DNS on query -> 匹配隧道? -> YES: 丢给对应的隧道 / NO: 丢回系统递归 DNS on reply -> 匹配隧道? -> NO: 直接返回 ... -> YES: 必要时查 ipv4/v6 映射表 -> 记录 DNS 结果地址、DNS 请求的源地址( edns 或者源 IP ),设置 TTL (比如不超过 5min ) -> 设置路由规则(源,目的,超时时间,隧道 ID 。其中超时=DNS 超时+允许的宽限时间) -> 返回记录 on PACKET -> 匹配路由规则(超时的这里就匹不到了)? -> YES: 修改目的 MAC 为隧道对应的 MAC / NO: 修改目的 MAC 为 OWGW 的 MAC -> rawsocket 发出 系统的路由表实现源*目的匹配各种不方便,更别说超时了。这也是自己搓二进制的主要原因。 |
47
povsister 245 天前
@maybeonly #46
完全理解了! 也就是只通过 DNS query 去刷新 DNS route 规则,已建立的连接依赖 conntrack 保持,不受 DNS route 限制。 我昨天给自己的实现添加了 onConnectionActivity 时,重置对应 DNS Route 的有效期,只要现有连接上有数据活动,则对应路由条目会一直刷新有效期。直到所有连接断开,且没有对应 DNS 请求时,对应 DNS route 才会被清理掉。 用于应对客户端 DNS 记录的缓存时间超过 DNS TTL 的情况。不过感觉似乎有点矫枉过正了。。 |
48
povsister 245 天前
@Jirajine #45
同意的,各种方案都有其优缺点。我描述的多网站共享 anycast ip 问题,确实适合在客户端侧自行解决。网关上只能有限的进行优化,无法彻底根治。属于透明代理的 tradeoff 了。 |
49
Donahue 245 天前
好复杂,我选择旁路由+openclash+机场下发代理文件
|
50
innoxa 245 天前
高端玩家
|
51
dvbs2000 245 天前
我用普通人理解翻译一下
这是一个自己动手实现的软路由系统。设计目标是为了玩得开心,而不是追求极致性能。它采用模块化设计,面向数据包和连接,使用真实 IP 地址。虽然结构复杂,但条理清晰,拓展性好,能够轻松适配各种形式的 VPN 。 基础操作系统使用 Rocky Linux 9 。主要使用 bash 脚本语言编写,部分模块使用 C++。没有图形界面,但有一些命令行工具。使用了多个内网 IPv4 和 IPv6 网段,尽管并非所有 IP 段都是必须的。 核心是 NET-IX 模块,提供虚拟交换功能。它使用一段内网 IPv4 和 IPv6 地址,提供调度、故障自动处理、分流及 DNS 、访问控制等服务。其中的主要功能模块包括: 1. INGW:内网接入网关,可针对不同设备应用不同策略,如 DNS 等。 2. DNSIW:普通 DNS 服务,转发到运营商 DNS 。 3. DNSOW:过墙 DNS 服务,对白名单域名转发 DNSIW,其他使用自己的递归 DNS 。 4. OWGW:隧道入口,对白名单 IP 转发至 RTGW 。 5. RTGW:IX 网段的出口网关,连接到 WAN 。 6. DNSROUTE:DNS 分流/策略分流模块,自行开发。 NET-LAN 模块对应普通内网接入,可直接分配公网 IPv6 地址并使用 SNPT 做转换。 NET-WAN 模块对应宽带接入,支持 PPPoE 、DHCP 等方式,还能转发 IPTV 流量。RTGW 连接 IX 和 WAN,对多宽带使用 connmark 解决连入连接问题。每条宽带使用两个 netns,分别连 ISP 和 TUN 。 NET-TUN 是模块化连出 VPN,每条隧道有两个 netns:TN 和 FW 。TN 接受 OWGW 或 DNSROUTE 的流量,经隧道协议发出;FW 提供防火墙和出口路由。VPN 出口在 OWGW 进行调度并自动检查隧道健康状态。 DNSROUTE 使用 C++ 实现,可匹配 DNS 请求并转发,并对返回的 IP 记录,后续可据此对数据包转发。 NET-XC 模块将连入 VPN 导入 INGW 并应用三层策略。NET-IoT 模块隔离物联网流量。 这个设计很灵活,在外部可方便地增删隧道、调整健康检查、改 WAN 设置等,且不影响整体。还能较容易增加新功能,如指定源 IP 经特定隧道、隧道串接、针对特定 WiFi 的 DNS 解锁等。 总之,这是一个为了玩得开心而设计的软路由系统,结构复杂但条理清晰,模块化程度高,可玩性强。作者在设计时着重考虑了灵活性和可扩展性。 @maybeonly 宠妻狂魔啊 小心惯坏 话说太复杂了 其实软路由稍微需要处理的主要是 dns 部分 dns 主要防被解析到沟里去 自己造轮子 说明技术水平确实高 |
52
GotKiCry 244 天前
太复杂了哥,我对软路由的理解还是停留在即插即用稳定上个网
|
53
kenywei001 243 天前
这就有点高端了。
|