Skip to content

Configurable DNS server #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
zonyitoo opened this issue Jul 18, 2018 · 23 comments
Closed

Configurable DNS server #119

zonyitoo opened this issue Jul 18, 2018 · 23 comments

Comments

@zonyitoo
Copy link
Collaborator

Currently server uses system DNS configuration (e.g. /etc/resolv.conf in *NIX). But maybe we could use DNS over TLS (quad9 for example).

Split from #118 .

@e2ge
Copy link

e2ge commented Jul 19, 2018

因为ssdns是将本地的dns转发到remote ssserver,如果remote server位于国外,那么设置上游dns为dns over tls也许意义不大,我的建议是是否ssdns可以在local直接将dns转发到dns over tls,不转发到remote,这样会减少延迟,不过这个就和dnscyrpt-proxy功能就很像了。

@zonyitoo
Copy link
Collaborator Author

这样就成了一个纯粹的DNS服务器,就没有必要叫ssdns了。

@zonyitoo
Copy link
Collaborator Author

ssdns要解决的问题应该是本地访问那个DNS服务器的时候是会被干扰,比如8.8.8.8我这里就访问不了。

@e2ge
Copy link

e2ge commented Jul 19, 2018

是的,ssdns的确是解决本地无法访问特定dns服务器的一个方案,但是因为需要借助remote,延迟就不乐观,我在本地更愿意选用dnscrypt-proxy这样的方案,上游用支持dns-over-http2的dns server,不过ip被block的话只能借助ssdns。我还是支持ssserver可以设置dns-over-tls的,这样隐蔽性会更好一些。

zonyitoo added a commit that referenced this issue Sep 23, 2018
@LuoZijun
Copy link
Contributor

注: /etc/resolv.conf 在 macOS 上面并不管用(Read Only),在 macOS 上面需要使用 SystemConfiguration.framework 来进行配置。

SOCKS5 代理服务是一个被动代理,被动 是指需要应用程序去主动配合 代理服务,这样整个代理行为才会发生。

为了使很多程序的数据包能自动经过 SOCKS5 转发,我们不得不去写 类似于 ssdns ssautoconfig 之类的辅助工具,既然如此,我们为什么不一开始就直接从 TUN/TAP 设备里面读取数据,并直接加密发送呢?

借助 ExodusVPN/net2TUN/TAP 设备读取原始链接层数据(ETHER_FRAM/ARP/ICMP/IGMP/IP),使用 m-labs/smoltcp 为这些原始 IP Packet 构建 TCP/ICMP 协议栈,并管理状态,从协议栈提取出 通信数据,将该通信数据直接发送给 SOCKS5 ,当然如果是 IP 层代理,则就不需要协议栈,直接转发链接层包。

如果需要做 IP 地区查询,并依据查询结果来左右 流量出口策略,可以借助 ExodusVPN/ip-db 来完成这一操作,目前那些通过脚本实现的,性能,可靠性,可维护性其实都是很糟糕的。

@gfreezy
Copy link

gfreezy commented Jul 21, 2019

@LuoZijun 我目前在写一个类似的。目前已经实现捕获全部的tun数据,并且重新拼接出 tcp 和 udp 协议的数据。现在遇到的问题是,ss-rust 的代码并不方便外部使用,需要全部代码直接拷贝到我的代码库里面去改。但是这样后面 ss-rust 的更新就获取不到了。

大概流程:

  1. 写一个 DNS Server。根据 PAC 规则,对国内域名返回正常 IP;对需要翻墙的域名返回 192.168.9.0/24 这个网段的IP,并且记录域名与IP的对应关系。然后将系统 DNS 设置为自定义 DNS Server。
  2. 新建 tun,IP 设置为 192.168.9.1/24。这样所有的 IP 包都会被发送到 tun 设备。
  3. 从 tun 设备读取到 IP 包后,根据 dest ip 反查对应的域名与目标的 IP。将 IP 包组装成 TCP/UDP 协议数据(难点)。
  4. 与远程 ss 服务器建立连接,并发送目标 IP 与 TCP/UDP 数据 。
  5. 从 ss 服务器获取数据后,将数据封装成 IP 包,写入 tun 设备。
  6. client 就可以正常翻墙了。

@zonyitoo
Copy link
Collaborator Author

现在遇到的问题是,ss-rust 的代码并不方便外部使用,需要全部代码直接拷贝到我的代码库里面去改。但是这样后面 ss-rust 的更新就获取不到了。

那部分?

@gfreezy
Copy link

gfreezy commented Jul 21, 2019

写一个 DNS Server。根据 PAC 规则,对国内域名返回正常 IP;对需要翻墙的域名返回 192.168.9.0/24 这个网段的IP,并且记录域名与IP的对应关系。然后将系统 DNS 设置为自定义 DNS Server。

我本意想尽量少改代码把上面的逻辑注入到 udpreplay/dns.rs 里面。仔细看逻辑实际已经差别挺大的了,直接 fork 改代码可能反而比较合适。

@zonyitoo 顺便问下,这种情况,除了 fork 后改代码或者拷贝代码外有别的好方法吗?

@LuoZijun
Copy link
Contributor

@gfreezy

我大概写过一个 macOS 系统 里面 DNS 设置相关的代码。
如果你们有兴趣的话,可以查看这个部分,也许能有所帮助。
https://github.com/ExodusVPN/exodus/blob/rewrite/crates/sysconfig/src/dns/macos.rs

从 tun 设备读取到 IP 包后,根据 dest ip 反查对应的域名与目标的 IP。将 IP 包组装成 TCP/UDP 协议数据(难点)。

这个设计看起来是一个 Tun2Socks 的设计,这个当然是可行的,你可能需要一个 TCP 协议栈的库,推荐看下 https://docs.rs/smoltcp/0.5.0/smoltcp/

@gfreezy
Copy link

gfreezy commented Jul 23, 2019

目前改了改 smoltcp 可以在 tun 上实现 socket 的数据收发。怎么结合 tokio 使用还没想明白。

@gfreezy
Copy link

gfreezy commented Jul 23, 2019

@zonyitoo 能给些建议吗?目前代码 https://github.com/gfreezy/seeker/blob/master/src/main.rs ,很难结合 tokio

@zonyitoo
Copy link
Collaborator Author

地址并不能打开

@zonyitoo
Copy link
Collaborator Author

结合tunnel的方法的话,建议可以搞一个sstunnel? shadowsocks-libev 也有一个类似实现.

我这边电脑都是MAC所以一直没有做这块,可以考虑把你的做成一个单独的bin?

@zonyitoo
Copy link
Collaborator Author

目前改了改 smoltcp 可以在 tun 上实现 socket 的数据收发。怎么结合 tokio 使用还没想明白。

只要是可以注册到epoll的,肯定是可以结合tokio用的。如果没有已有的Rust库的话,建议可以先写一下封装库出来。写法上应该和普通的FD注册到Mio上是一样的。

@gfreezy
Copy link

gfreezy commented Jul 23, 2019

抱歉,忘记改成公开的了,已经可以访问了。

我这边电脑都是MAC所以一直没有做这块,可以考虑把你的做成一个单独的bin?

我是用的 mac 的 tun,mac 系统提供了 API 创建 tun。

目前改了改 smoltcp 可以在 tun 上实现 socket 的数据收发。怎么结合 tokio 使用还没想明白。

只要是可以注册到epoll的,肯定是可以结合tokio用的。如果没有已有的Rust库的话,建议可以先写一下封装库出来。写法上应该和普通的FD注册到Mio上是一样的。

有点不太一样。tun 的接口是提供一个 fd,从这个 fd 读到的是 IP 包,需要在 userspace 自己组装成 tcp/udp。mio 注册的话只能注册这一个 fd,但是不知道怎么把 tun 的读写事件转换成上层 n 多 socket 的事件。

@zonyitoo
Copy link
Collaborator Author

smoltcp这个库貌似就实现了这些代码吧,基于它改造一下?

@LuoZijun
Copy link
Contributor

结合tunnel的方法的话,建议可以搞一个sstunnel? shadowsocks-libev 也有一个类似实现.

我这边电脑都是MAC所以一直没有做这块,可以考虑把你的做成一个单独的bin?

macOS 也可以的嘛。

@zonyitoo
Copy link
Collaborator Author

macOS 也可以的嘛。

查了一下资料貌似还真可以,看@gfreezy 是否有空可以搞一个?我最近忙完了先

@gfreezy
Copy link

gfreezy commented Aug 24, 2019

已经实现了基本的功能,代码在 https://github.com/gfreezy/seeker

@zonyitoo 我看 ss-rust 里面的代码,ss server 的连接是每次都建立的,并没有复用。如果我希望 ss 服务器连接可以复用,甚至在请求来之前提前完成 handshake,节省几次网络来回的时间,有什么建议吗?

@zonyitoo
Copy link
Collaborator Author

zonyitoo commented Aug 24, 2019

这样sslocalssserver端都要做一个改造,做成连接池的形式。同一个目标地址的请求,可以直接从池里进行复用。

或者ssserver不做改造,只改sslocal端,sslocal端的连接池跟远端保持着长连接即可。

不过我觉得这一块可能优化不会特别大,在应用上大多都用于浏览器访问资源,大多的协议都是HTTP/1.1以上的,本身保持着的就是长连接。

@LuoZijun
Copy link
Contributor

@gfreezy

系统配置方面有进展咯:

macOS (通过 PF_ROUTE 操控)
https://github.com/ExodusVPN/exodus/blob/rewrite/crates/sysconfig/examples/route.rs
已经有 接近于 ip route list/get/add/del 的功能。

Linux (通过 Netlink 操控)
https://github.com/ExodusVPN/exodus/blob/rewrite/crates/netlink/examples/route.rs
已经有 接近于 ip route/neigh/addr/link list/get/add/del 的功能。

设置IP转发(通过 sysctl 操控,macOS 、Linux 和 BSD 都支持)
https://github.com/ExodusVPN/exodus/blob/rewrite/crates/sysconfig/src/ip_forwarding.rs
已经有等价于 sudo sysctl net.inet.ip.forwarding = 1 的功能。

DNS 设定方面还是只支持 macOS:
https://github.com/ExodusVPN/exodus/blob/rewrite/crates/sysconfig/src/dns/macos.rs

下一步应该就是防火墙规则的操控了,等价于 iptables/nftables .

🎉🎉🎉🎉🎉

@zonyitoo
Copy link
Collaborator Author

已经实现了基本的功能,代码在 https://github.com/gfreezy/seeker

@zonyitoo 我看 ss-rust 里面的代码,ss server 的连接是每次都建立的,并没有复用。如果我希望 ss 服务器连接可以复用,甚至在请求来之前提前完成 handshake,节省几次网络来回的时间,有什么建议吗?

对于SS协议,TCP连接肯定得每次都单独建立。不过目前最新的版本实现了HTTP协议的sslocal,因为HTTP 1.1协议本身要求支持Keep-Alive,因此实现了连接复用。可考虑试试。

这个协议讨论的是Configurable DNS Server,均已经实现。关于tun方面的讨论,最近我也在调研,可考虑加到sslocal去。

@zonyitoo
Copy link
Collaborator Author

忘了讲,sstunnel已经在本项目中实现并支持。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants