跟风贴自家软路由实现

66 天前
 maybeonly

设计目标

设计总则

具体实现

为什么说玩得开心呢

4965 次点击
所在节点    宽带症候群
53 条回复
aptupdate
65 天前
怎么和我玩的软路由不太一样。。。
dodakt
65 天前
我看完了 也看懵了 没有一个字是我不认识的 没有一段是我能看懂的
MeteorVIP
65 天前
你这确实很高端喔,虽然我看不懂,
但是我就想问,掉线,网速慢会被老婆骂吗?
maybeonly
65 天前
@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 年之前的事情了。
maybeonly
65 天前
@MeteorVIP
网速慢会被老婆骂,广告过滤列表过滤不掉广告会被老婆骂,dns 解锁不灵会被老婆骂,老婆在外边连不上回家的 vpn 也会骂。
好在这些年了除了在有计划的调整之外,只有硬件故障和电力故障能搞坏它。
yyysuo
65 天前
@maybeonly #25 擦,军功章上有你的一半也有贵夫人的一半啊。
KazeW
65 天前
这 这才是软路由?
佬这不是跟风,是平地起狂风
MeteorVIP
65 天前
@maybeonly #25 挨骂我就舒心了,哈哈哈
zylll520
65 天前
大佬独领风骚👍
shunia
65 天前
不对,这不是我要上的车!
defunct9
65 天前
大佬买个 AS 域,折腾 BGP 吧
hi2hi
65 天前
大佬!太强了
povsister
65 天前
@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 下的域名分流机制可能会始终面临这个痛点。
maybeonly
65 天前
@povsister 这个问题思考过,并没有那么疼。
首先,基本上没可能解析到同一个 anycast ip 。大厂的 cdn ip 也是专用的。好吧,假设他真的解析到同一个 anycast ip 了。
其次,比较现实的情况是,使用了两个不同的 dns 解锁机,分别解析到商家的美国解锁机和日本解锁机上,那这俩 ip 显然也不一样。
第三,更现实的情况,真实场景下,同一个用户/客户端几乎不可能同时用 nf 和 dmm 。所以实现的时候有考虑源 ip*目的 ip 做匹配,假如电视上看 nf ,手机上玩 dmm ,那是一点都不会出问题的。就算在同一台机器上切换,只要别来回切,后续解析成功的规则会覆盖前一个,而之前建立的 tcp/udp 连接则不会断——这里 dns 解析的结果是缓存在递归里的,而 dnsroute 会把 ttl 改小让用户不要太久不请求。
整体上来讲,不可能完全避免这类问题,但是现在的实现,已经可以让这类问题发生的几率足够小了。

至于嗅探,还是算了吧,当时也考虑到 ech (当时还是 esni ),从开头就没有打算做。
Jirajine
65 天前
@maybeonly #24 你用一堆 netns 组了个虚拟集群,数据包发过来发过去,这开销一点不比用户态低啊。
复杂度这么高,能保证 correctness 吗,比如任何情况下任意客户端的任意 dns 请求和后续实际请求能够路由到相同的外部接口。
那些代理软件确实不适合在路由器上使用,它们提供的功能根本就不是路由器需要的。路由器只要做好两件事:把不同客户端的出战连接路由到不同外部接口;追踪入站连接,回程路由到来源的接口。其他的你想用什么隧道、起什么服务、vpn 入站、通过 ip/mac/vlan 等方式识别客户端等等都是全部解耦、互不影响的。其他更复杂需求客户端自己做更合适。
Jirajine
65 天前
@povsister #33 因为你在尝试在错误的 layer 解决问题。开两个 firefox container ,一个走美国代理打开 netflix 、一个走日本代理打开 dmm 不就完事了,什么规则、路由、dns 都不需要。
maybeonly
65 天前
@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 很大程度上也是为了干这个。
huangya
65 天前
这些配置,有些可不可以整理一下放 github ?
Jirajine
65 天前
@maybeonly #37
> 调试修改起来比单个用户态程序容易太多
好吧,你是写 Cpp 的,能够理解😂
不过用户态一个函数能实现的功能在系统网络栈配合路由和规则做,正常来说最大的优势就是性能了。模块之间如果需要交流,那说明是耦合到一起的。

如果你的 vpn 入站需要路由除访问内部资源以外的流量,那是不是因为你这一套做了太多该在客户端做的,从而不够 portable 。
maybeonly
65 天前
@Jirajine
> 不过用户态一个函数能实现的功能在系统网络栈配合路由和规则做,正常来说最大的优势就是性能了。模块之间如果需要交流,那说明是耦合到一起的。
后面的 “交流” 指的是数据流转,比如后面挂了 3 个不同的梯子,那么数据总是得从调度进程到梯子进程的……不管整合不整合梯子都是 clash 既视感。
另一方面,在现实中,运维水平也是不得不考虑的……
所以这里的取舍是,选择 netns 集群便于维护的特点而放弃极致性能(其实也没多差)。

> 如果你的 vpn 入站需要路由除访问内部资源以外的流量,那是不是因为你这一套做了太多该在客户端做的,从而不够 portable 。
不是很确定你要表述什么。客户端连上入站 vpn 什么都能访问,就和连上 wifi 几乎一样(除了 2 层)。vpn 入站模块只需要路由器给转发特定端口就行。
现在的客户端可不是以前了,电脑怎么都好说,手机、平板、电视,IoT……还是设计哲学问题,我不想在客户端放复杂的东西,能连个不同的 ssid 就是极限了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1034955

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX