eycorsican / go-tun2socks

A tun2socks implementation written in Go.
MIT License
1.3k stars 432 forks source link

解决开启fakedns容易卡死的问题 #70

Closed xjasonlyu closed 5 years ago

xjasonlyu commented 5 years ago

原来的tun2socksfakedns的实现是基于对53端口udp包进行直接回复来做处理的,但是在实行运行中很容易直接卡死,可能是线程阻塞了。

然后就考虑直接建立一个fakedns server监听就可以,直接把系统设置成这个dns地址就可以解决了(虽然也考虑过用修改udp目的ip的方法省去设置系统dns的麻烦,但是因为有可能有把这个fakedns server作为上游dns,包着一层dnsmasq之类的,所以就没有强制实现。)

因为clashfakedns实现的挺好用的,就直接拿clashfakedns模块改了,测试一下效果不错,没有因为开启fakedns而直接卡死的问题了。

(因为ss和v2 handler 都被移除掉了,所以没有改这两个,只改了socks的支持)

eycorsican commented 5 years ago

只要能够稳定复现,线程阻塞(goroutine leak)算是 Go 中相对容易调试的一类问题,打开 pprof 就一目了然(1, 2),如果你觉得目前的代码或者方法有问题,请先把具体问题指出来,或者先提交相关的 issue。

xjasonlyu commented 5 years ago

因为目前的fakedns的实现算是强制修改走53的udp包的,其实这样不太好,还是监听53做一个fakedns server负责做respond比较好(目前fakedns有时候卡到算是个bug吧,我遇到过但没仔细研究,觉得可以换个实现。)

eycorsican commented 5 years ago

你认为做成一个 server 监听 53 端口对比原来的实现好在哪里呢?我认为目前的方法不需要在启动前和关闭后对系统 DNS 进行修改就是一个优势。

xjasonlyu commented 5 years ago

比如如果本地有一台dns server,自定义了nas.local->192.168.1.2的回复,如果这个强制变成fakeip的话,就要交给远程的socks server解决了,而不是直接本地请求到internal IP然后直连。(如果对面的socks server不在一个内网,那就直接连不上了)

xjasonlyu commented 5 years ago

其实启动关闭的时候肯定是要用脚本的,要对 route tun 一些做修改,所以改系统dns的事情可以直接在脚本里做好,方便性上没有区别,我觉得在用tun2socks应该没有人会每次都一串args启动,然后手动设置路由的吧。

eycorsican commented 5 years ago

这个 PR 中似乎有不少处理不当的地方,比如没有把 A/AAAA 类型过虑出来,DNS 可不只有这两种请求类型,对于非 A/AAAA 类型请求也没有后续处理。

上面提到 nas.local->192.168.1.2 的问题,也不见得在处理上有什么不一样,而且把 nas.local 这个域名交给远端代理服务器来处理正是 fake dns 所要实现的,考虑一下你设置了 chrome 的 socks5 代理后,在地址栏输入 nas.local

另外 go-tun2socks 不仅用在桌面系统,也用在移动系统,不过我也还没仔细考虑这块的影响。

xjasonlyu commented 5 years ago

DNS记录那一块我是直接拿clash的fakedns模块改的,没有具体看实现逻辑。。这一块是可以加以完善的,考虑到A/AAAA记录是可以用fakeip的,其他请求最好还是要给直接转发的(但这里还有个问题就是如果远程的socks不支持udp,那其实也白搭,然后用dns fallback感觉又要dns支持,处理起来并不是很好)

nas.local->192.168.1.2这个我想说的是可以把类似这样的地址直接本地处理了,不用交给远程服务器。(因为tun2socks没有类似于chrome代理时的cfw-pass的地址过滤机制,是所有请求都走socks之类的handler)

我的tun2socks主要是用来做旁路网关的,所以把dns server也一并实现了,目前效果是不错的,虽然也有一些地方还得改改。

eycorsican commented 5 years ago

所以你不能够提一个不完整的实现上来,不会合并的,有问题建议还是先提 issue。

而且要合并的话,你还得说服我这个实现究竟比原来实现好在哪里,对于你上面说的 .local 地址本地处理的情况,你这个 PR 的实现看起来也并非是本地处理的(如果我看错的可以纠正我

xjasonlyu commented 5 years ago

我是用了dnsmasq做系统dns,然后把这个fakedns做成了上游的dns,这样本地请求直接通过dnsmasq的host映射就可以了,其他的请求dnsmasq是可以再交给fakedns server解决的。

这个实现是不够完整,所以我还是自用修改的dev版本,但因为目前你的fakedns实现在实际用的时候经常dig baidu.com之类的会没有响应,所以先试图用这个pr临时解决一下。

其实我也觉得合并意义不大,因为实现还太残缺了😂