Mythologyli / zju-connect

ZJU RVPN 客户端的 Go 语言实现
GNU Affero General Public License v3.0
313 stars 21 forks source link

feat: add dns-hijack for tun mode #45

Closed cxz66666 closed 8 months ago

cxz66666 commented 8 months ago

此PR旨在为zju-connect提供基本可用的dns劫持,使用户可以在tun模式下更方便的访问*.zju.edu.cn

目前tun模式使用的是10.0.0.0/8的路由,无法劫持所有流量,所以不同os下实现的方法不同。

通用的实现细节:

os相关的细节:

ip route add default dev tun0 table 1987



- macos: 由于缺少ip rule和ip route,在10.0.0.0/8的tun模式下无法方便的做到dns劫持,后面有两个方向可行的解决方法
  - 实现**优雅停机**后,将用户的dns解析设置成一个无用的公网ip,然后路由这个ip到tun设备
  - 用户手动配置dns server
cxz66666 commented 8 months ago

mac上第一个可能的方案是不是类似于fake-ip,但据我所知clash的fake-ip只支持A, AAAA和CNAME记录,至少测了SRV不支持,我不知道是不是原理限制(完全不懂网络哈哈哈

我感觉和fake-ip还有一些区别,在tun只接管10.0.0.0/8的前提下没法做正常的dns劫持,所以只能将用户的/etc/resolve.conf 改成比如举个例子 1.2.3.4, 然后路由表里面加一条规则 1.2.3.4的ip去tun设备,这样用户对1.2.3.4的udp dns请求就会被发送到tun设备中,就可以进行劫持

mac由于是强主机模型 https://learn.microsoft.com/zh-cn/previous-versions/technet-magazine/cc137807(v=msdn.10)?redirectedfrom=MSDN

如果源接口上启用了强主机发送,IP 将在路由表中对数据包的目标地址执行受约束的查询。在受约束的查询中,仅考虑带有源接口的下一跃点接口的路由。根据所选目标路由,IP 确定下一跃点地址。IP 具有了源地址和目标地址、下一跃点接口和下一跃点地址。请注意,如果在源接口上启用强主机发送行为,下一跃点接口将始终与源接口相同。图 2 显示发送主机进程的普通 IP。

cxz66666 commented 8 months ago

@Mythologyli https://github.com/Mythologyli/zju-connect/blob/403c98d6aaf05360665d7c1dfacafed7842de2b9/main.go#L141C1-L143 这里是否应该启一个协程,更符合其代码语义,测试过使用协程对程序执行逻辑没有影响

Mythologyli commented 8 months ago

@Mythologyli https://github.com/Mythologyli/zju-connect/blob/403c98d6aaf05360665d7c1dfacafed7842de2b9/main.go#L141C1-L143 这里是否应该启一个协程,更符合其代码语义,测试过使用协程对程序执行逻辑没有影响

啊,这个是我写的时候疏忽了,确实应该启一个协程

cxz66666 commented 8 months ago

确实应该启一个协程

已在该分支修复,后续合入即可解决

Mythologyli commented 8 months ago

另外考不考虑不在 rvpn_conn.go 里 panic,把 panic 挪到 stack 里面

主要是 Android 需要以库的形式调用,因此整个函数里不能 panic,参考 030bddc30d97c9d371f6c94c3e8ae8d4f588f7e6

cxz66666 commented 8 months ago

另外考不考虑不在 rvpn_conn.go 里 panic,把 panic 挪到 stack 里面

Android有这种需求的话我觉得也完全OK 👍

cxz66666 commented 8 months ago

macos下发现了一种十分甚至9分优雅的方法,创建/etc/resolver/hostname 的文件,向其中写入 nameserver a.b.c.d 即可做到对hostname后缀的域名使用a.b.c.d进行解析,这种用法相当符合我们的场景,只需要创建zju.edu.cn和cc98.org等文件即可,a.b.c.d是tun网卡的ip。 cc

btw,macos这种区分domain和search domain的行为感觉其实更加合理,linux就没法(不使用其他软件的情况下)做到根据域名使用不同的dns。

至此windows/linux/macos都可以以一种比较优雅的方法实现dns-hijack

cxz66666 commented 8 months ago

现在dns-hijack已经基本可用,相比于最初的设计有如下的改动,clientIP代指拿到的10.a.b.c的ip

@Mythologyli 辛苦测试下windows的效果,俺不太懂windows 🙇🙇

Mythologyli commented 8 months ago

感觉差不多可以合并了~