建立DNS隧道绕过校园网认证
因为之前在本科的时候破解过校园网三次,主要就是利用其业务逻辑上的漏洞、53
端口未过滤包、重放攻击的手段,然后就是一个博弈的过程,这三次加起来用了大概有一年的时间就被完全堵死了,最近又比较需要网络,然后有开始想折腾了,不过这次建立dns
隧道虽然是成功建立了,使用正常网络是能够走服务器的dns
隧道的,但是并没有成功绕过校园网的认证,至于原因还是有待探查。最后想着还是记录一下隧道建立流程,之后做CTF
题可能用得到。
描述
dns
隧道相关的描述直接引用参考中文章的一段描述:既然UDP53
端口的数据包可以通过网关,那么我们可以在本地运行一个程序将其它端口的数据包伪装组成UDP53
端口的数据包,然后发送到本地域名服务器,那么网关就不会进行拦截了,数据包就顺利的通过了网关,可是发送出去的数据报如何返回呢?这就需要我们做进一步的设置。接下来我们需要一个VPS
(云服务器)和一个域名,我了便于叙述,我给这个云服务器起名为V
,域名起名为Y
。我们伪装的DNS
数据包要查询的域名就是Y
,本地域名服务器接收到这个伪装后的数据包后,由于它无法解析这个域名Y
,便将数据包进行转发,让能够解析Y
的域名服务器进行解析,接下来我们将Y
设置一个NS
记录,用来指定Y
由哪个域名服务器来进行解析,我们指定的域名服务器就是前面提到的V
,所以接下来数据包会被发送到V
中。此时我们在V
中运行一个程序,对伪装的数据包进行还原,还原后的数据包再发送出去,这样当V
接收到响应数据包后,V
上运行的程序会再次对其进行伪装,伪装成一个DNS
响应数据包,这个DNS
响应数据包会沿着上述相反的路径发送回我们的计算机,我们的计算机再次对这个DNS
响应数据包进行还原,到现在,我们真正想要得到的数据包已经到手了。
服务端
假设此时有一个example.com
的域名,服务器的ip
地址为111.111.111.111
。接下来要对域名进行解析,增加一个NS
记录以及一个A
记录,新增NS
记录的名称为dns.example.com
,值为dnsserver.example.com
,新增A
记录的名称为dnsserver.example.com
,值为ip
地址即111.111.111.111
。
类型 名称 值
NS dns.example.com dnsserver.example.com
A dnsserver.example.com 111.111.111.111
之后在服务器执行以下命令。
代码语言:javascript复制$ tcpdump -n -i eth0 udp dst port 53
然后随便找一台机器进行dns
查询,然后在服务器的终端就能够看到查询的信息了。
$ nslookup dns.example.com
代码语言:javascript复制...
19:09:01.810846 IP 222.222.222.222.54346 > 111.111.111.111.53: 6858 [1au] A? dns.example.com. (57)
...
我的服务端使用ubuntu
的linux
发行版,直接使用包管理器安装dns2tcp
。
$ apt install dns2tcp
接下来需要配置一下dns2tcp
。
$ vim /etc/dns2tcpd.conf
代码语言:javascript复制listen = 0.0.0.0
port = 53
# If you change this value, also change the USER variable in /etc/default/dns2tcpd
user = nobody
chroot = /tmp
domain = dns.example.com
resources = ssh:127.0.0.1:22
执行如下命令即可启动dns2tcp
,其中参数-f /etc/dns2tcpd.conf
指定了配置文件,-F
要求程序在前台运行,-d 2
指明了输出调试信息,级别为2
,为首次运行,我们加上参数-F
和-d 2
,另外如果需要保持前台运行且输出日志信息的话,nohub
、screen
、systemctl
都是可行的,维持终端进程后台运行就不再赘述。
dns2tcpd -f /etc/dns2tcpd.conf -F -d 2
代码语言:javascript复制19:31:49 : Debug socket.c:55 Listening on 0.0.0.0:53 for domain dns.example.com
Starting Server v0.5.2...
19:31:49 : Debug main.c:132 Chroot to /tmp
11:31:49 : Debug main.c:142 Change to user nobody
客户端
在服务端只需要开启一个终端,客户端需要保持两个终端,首先我们建立一个链接通道,在客户端也需要下载dns2tcp
,在这里我直接使用brew
安装。
$ brew install dns2tcp
紧接着需要启动通道,至此第一个终端连接已经完成。
代码语言:javascript复制$ dns2tcpc -l 8888 -r ssh -z dns.example.com 111.111.111.111
代码语言:javascript复制Listening on port : 8888
紧接着我们需要借助ssh
开启一个socks4/5
通用代理,这也就是第二个终端需要完成的任务,相当于完成了一个ssh
连接,同样也是需要账号密码或者私钥的,执行下面的命令即可在127.0.0.1
开启一个端口为1080
的socks
代理。
$ ssh -D 127.0.0.1:1080 root@127.0.0.1 -p 8888
之后就是使用代理了,可以为全局进行代理也可以近为一些软件启用socks
代理连接,在此本地进行了简单的测试。
$ curl https://www.baidu.com --proxy socks5://127.0.0.1
可以看到服务端有大量的输出。
代码语言:javascript复制...
Debug queue.c:240 Flush Write 72 bytes, crc = 0x40c5
Debug queue.c:300 Flushing outgoing data
Debug queue.c:642 Packet [646] decoded, data_len 0
Debug queue.c:653 diff = 21
Debug queue.c:300 Flushing outgoing data
Debug queue.c:642 Packet [647] decoded, data_len 24
Debug queue.c:653 diff = 21
Debug queue.c:240 Flush Write 24 bytes, crc = 0xd739
Debug queue.c:300 Flushing outgoing data
Debug queue.c:642 Packet [648] decoded, data_len 0
Debug queue.c:653 diff = 21
Debug queue.c:300 Flushing outgoing data
...
要注意的是无论是本地的终端还是服务器的终端都需要保持其运行才能继续正常使用,毕竟如果终端掉了进程结束了也就不存在封包解包的操作了,另外实际使用速度还是比较感人的,毕竟其有大量的封包拆包操作。
最后
最终还是没能成功实现想要的功能,最后使用dnslog
探查了一下实际上是有dns
查询的,还是需要研究一下究竟是什么阻拦策略导致没有完成隧道的建立。想来三级域名的A
记录其实是可以携带一点信息的,即abc.example.com
可以携带abc
这个信息过去。此外还有一个终极大招,直接物理方案解决,毕竟AP
可是在宿舍里边的。
参考
代码语言:javascript复制http://0sec.com.cn/2018-08-05/
http://blog.dengxj.com/archives/14/
https://www.cnblogs.com/nkqlhqc/p/7805837.html
https://blog.csdn.net/wn314/article/details/81430554
https://blog.csdn.net/m0_53129012/article/details/111173610
https://blog.csdn.net/miaomiaodmiaomiao/article/details/50883764