如何建立dns隧道来突破连接WIFI后用户密码认证的上网方式

image-20240221134517708
  • 2024.3.5 优化了DNS的A记录(经测试优化t1ns的A记录成功)

有什么用

建立dns隧道来突破连接WIFI后用户密码认证的上网方式

学习和了解iodine的工作原理

实测环境:

  • J4125中的OpenWrt;作为服务端
  • Mac OS X 电脑;作为客户端

怎么用

详见下方的实现过程,含大框架的步骤

客户端iodine连接上服务端iodined后,继续嵌套SSH来上网(或使用其他的vpn/socks等代理方式)

当前的目标是:突破连接WIFI后,继续提示输入用户名和密码的认证方式(一般还设置了上网时间限制,比如采集手机号码当作用户名,密码用短信下发)

当前应用:可以建立dns隧道来突破连接WIFI后用户密码认证的上网方式,然后远程SSH来管理或给Linux主机下达指令

下一步:

  • 如何提速?减少连接使用时的等待时间(目前的应用,需要超级大的耐心)
  • 是否有其他的应用场景?或结合其他的应用?

相关知识/灵感来源

什么是DNS隧道?

DNS隧道(DNS Tunneling)是将其他协议的内容封装在DNS协议中,然后以DNS请求和响应包完成传输数据(通信)的技术。

DNS隧道的原理:

在进行DNS查询时,如果查询的域名不在DNS服务器本机的缓存中,就会访问互联网进行查询,然后返回结果。如果在互联网上有一台定制的服务器,那么依靠DNS协议即可进行数据包的交换。从DNS协议的角度看,这样的操作只是在一次次查询某个特定的域名并得到解析结果,但其本质问题是,预期的返回结果应该是一个IP地址,而事实上不是——返回的可以是任意字符串,包括加密的C&C指令。

DNS隧道分为两种:

直连模式:客户端直接向指定IP地址的DNS服务器发起DNS解析请求

中继模式:DNS经过互联网的迭代解析,指向指定的DNS服务器。

区别在于直连模式速度相对快,但安全性相对较差。非直连模式速度相对较慢,但安全性相对较高。大多数情况下都使用中继模式。

iodine

iodine可以通过一台DNS服务器制造一个IPv4数据通道,特别适合在目标主机只能发送DNS请求的网络环境中使用。iodine是基于C语言开发的,分为服务端程序iodined和客户端程序iodine。kali中内置了iodine。 下载:https://github.com/Al1ex/iodine
iodine工作原理是:通过 TAP虚拟网卡,在服务端建立一个局域网;在客户端,通过TAP 建立一个虚拟网卡;两者通过 DNS 隧道连接,处于同—个局域网(可以通过ping命令通信)。在客户端和服务端之间建立连接后,客户机上会多出一块名为“dns0”的虚拟网卡。更多使用方法和功能特性,请参考iodine的官方文档:http://code.kryo.se/iodine

https://github.com/yarrick/iodine
https://code.kryo.se/iodine/

另一个工具dns2tcp

详细见文章:WIFI无线上网短信认证

相关内容

实现方法

1. make 后获取iodined(Server端) 和 iodine(客户端)

OpenWrt平台(Linux):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> opkg install iodined
Installing iodined (0.7.0-4) to root...
Downloading https://op.supes.top/23.05/packages/x86_64/packages/iodined_0.7.0-4_x86_64.ipk
Configuring iodined.
iodined: Invalid topdomain: Too short (< 3)
Usage: iodined [-v] [-h] [-c] [-s] [-f] [-D] [-u user] [-t chrootdir] [-d device] [-m mtu] [-z context] [-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password] [-F pidfile] [-i max idle time] tunnel_ip[/netmask] topdomain


------------------------------------------------
以下部分是客户端的程序:iodine
------------------------------------------------
> opkg install iodine
Installing iodine (0.7.0-4) to root...
Downloading https://op.supes.top/23.05/packages/x86_64/packages/iodine_0.7.0-4_x86_64.ipk
Configuring iodine.

Mac平台(Mac OS X):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
iodine-0.8.0 % make
OS is DARWIN, arch is arm64
CC tun.c
CC dns.c
CC read.c
CC encoding.c
CC login.c
CC base32.c
CC base64.c
Making base64u.c
CC common.c
common.c:283:2: warning: 'daemon' is deprecated: first deprecated in macOS 10.5 - Use posix_spawn APIs instead. [-Wdeprecated-declarations]
daemon(0, 0);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdlib.h:294:6: note: 'daemon' has been explicitly marked deprecated here
int daemon(int, int) __DARWIN_1050(daemon) __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_0, __MAC_10_5, __IPHONE_2_0, __IPHONE_2_0, "Use posix_spawn APIs instead.") __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
^
1 warning generated.
CC iodine.c
CC client.c
CC util.c
LD ../bin/iodine
CC iodined.c
CC user.c
CC fw_query.c
LD ../bin/iodined

2. 设置DNS记录

以dash.cloudflare.com的配置为例,新增以下这两条DNS记录

DNS类型 名称 内容/值 备注
NS t1 t1ns.carlzeng.top 仅 DNS
A t1ns 125.34.235.88 仅 DNS, 可优化

20240305 经实践测试,这条A记录是可以有泛域名*A记录解析后优化掉(即删去)。

原理:这个APP只需要得到t1ns.carlzeng.top的IP地址,而不设置这条A记录,DNS系统会自动使用泛域名*所对应的IP地址,而这正是我想要达到的效果(减少了宽带DDNS需要更新的DNS记录数)

3. 运行服务端iodined

image-20240221174938467

这个范例在OpenWrt上无法成功:iodined -f -P 123 10.0.0.1 t1.carlzeng.top

1
2
# 请使用-c  和 -l 125.34.235.88 指定WAN口的监听IP, —D 为调试信息输出
iodined -D -f -c -l 125.34.235.88 -p 53 -P 123 192.168.99.1/24 t1.carlzeng.top

长期运行的话,放入后台运行:

1
2
3
4
5
6
7
# iodined -c -l 125.34.235.88 -p 53 -P 123 192.168.99.1/24 t1.carlzeng.top        
Opened dns0
Setting IP of dns0 to 192.168.99.1
Setting MTU of dns0 to 1130
Opened IPv4 UDP socket
Listening to dns for domain t1.carlzeng.top
Detaching from terminal...

4. 运行客户端iodine

image-20240221175104599

以Mac OS X运行客户端为例:

1
./iodine -f -P 123 t1.carlzeng.top

成功后的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
> ./iodine -f -P 123  t1.carlzeng.top
No tun devices found, trying utun
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
Opened utun6
Opened IPv4 UDP socket
Sending DNS queries for t1.carlzeng.top to 223.5.5.5
Autodetecting DNS query type (use -T to override).
Using DNS type NULL queries
Version ok, both using protocol v 0x00000502. You are user #0
Setting IP of utun6 to 10.0.0.2
Adding route 10.0.0.0/27 to 10.0.0.2
add net 10.0.0.0: gateway 10.0.0.2
Setting MTU of utun6 to 1130
Server tunnel IP is 10.0.0.1
Requesting server address to attempt raw UDP mode (skip with -r)
Server is at 125.34.235.88, trying raw login: (skip with -r) ....failed
Using EDNS0 extension
DNS queries get changed to lowercase, keeping upstream codec Base32
No alternative downstream codec available, using default (Raw)
Switching to lazy mode for low-latency
Server switched to lazy mode
Autoprobing max downstream fragment size... (skip with -m fragsize)
...768 not ok.. ...384 not ok.. 192 ok.. ...288 not ok.. ...240 not ok.. 216 ok.. 228 ok.. ...234 not ok.. ...231 not ok.. 230 ok.. will use 230-2=228
Setting downstream fragment size to max 228...
Connection setup complete, transmitting data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# sudo ./iodine -r -f -P 123 202.106.0.20 t1.carlzeng.top
No tun devices found, trying utun
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
Opened utun6
Opened IPv4 UDP socket
Sending DNS queries for t1.carlzeng.top to 202.106.0.20
Autodetecting DNS query type (use -T to override).
Using DNS type NULL queries
Version ok, both using protocol v 0x00000502. You are user #6
Setting IP of utun6 to 192.168.99.8
Adding route 192.168.99.0/24 to 192.168.99.8
add net 192.168.99.0: gateway 192.168.99.8
Setting MTU of utun6 to 1130
Server tunnel IP is 192.168.99.1
Skipping raw mode
Using EDNS0 extension
Switching upstream to codec Base128
Server switched upstream to codec Base128
No alternative downstream codec available, using default (Raw)
Switching to lazy mode for low-latency
Server switched to lazy mode
Autoprobing max downstream fragment size... (skip with -m fragsize)
...768 not ok.. ...384 not ok.. 192 ok.. ...288 not ok.. ...240 not ok.. 216 ok.. 228 ok.. ...234 not ok.. ...231 not ok.. 230 ok.. will use 230-2=228
Setting downstream fragment size to max 228...
Connection setup complete, transmitting data.

长期运行的话,放入后台运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# sudo ./iodine -r -P 123 202.106.0.20 t1.carlzeng.top
No tun devices found, trying utun
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
Opened utun6
Opened IPv4 UDP socket
Sending DNS queries for t1.carlzeng.top to 202.106.0.20
Autodetecting DNS query type (use -T to override).
Using DNS type NULL queries
Version ok, both using protocol v 0x00000502. You are user #1
Setting IP of utun6 to 192.168.99.3
Adding route 192.168.99.0/24 to 192.168.99.3
add net 192.168.99.0: gateway 192.168.99.3
Setting MTU of utun6 to 1130
Server tunnel IP is 192.168.99.1
Skipping raw mode
Using EDNS0 extension
DNS queries get changed to lowercase, keeping upstream codec Base32
No alternative downstream codec available, using default (Raw)
Switching to lazy mode for low-latency
Server switched to lazy mode
Autoprobing max downstream fragment size... (skip with -m fragsize)
...768 not ok.. ...384 not ok.. 192 ok.. ...288 not ok.. ...240 not ok.. 216 ok.. 228 ok.. ...234 not ok.. ...231 not ok.. 230 ok.. will use 230-2=228
Setting downstream fragment size to max 228...
Connection setup complete, transmitting data.
Detaching from terminal...

5. 使用dns隧道来代理上网

注意:这个方案需要开启iodined服务端(也就是OpenWrt)防火墙设置;开启SSH访问运行从Wan口访问,开启防火墙运行接收入站流量。

现实中的代理使用;

​ ssh隧道方案:
​ 客户端运行:
​ ssh -CfNg -D 7001 root@10.0.0.1

1
ssh -CfNg -D 7001 root@192.168.99.1

​ 客户端的浏览器设置socks代理
​ IP地址
​ 7001端口

感受

通过以上设置,可正常打开网页。但网速实在不敢恭维,并无多大现实日常使用的意思。

除非极其特别的情况:比如,通过此隧道连接来触发远程服务端执行特定的预编译的指令。

错误及解决方法

#1.客户端卡死:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
> ./iodine -f -P 123 t1.carlzeng.top                                                                  
No tun devices found, trying utun
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
Opened utun5
Opened IPv4 UDP socket
Sending DNS queries for t1.carlzeng.top to 192.168.6.1
Autodetecting DNS query type (use -T to override)..iodine: Got NOTIMP as reply: server does not support our request
.......iodine: Got NOTIMP as reply: server does not support our request
.......iodine: Got NOTIMP as reply: server does not support our request
.....
iodine: No suitable DNS query type found. Are you connected to a network?
iodine: If you expect very long roundtrip delays, use -T explicitly.
iodine: (Also, connecting to an "ancient" version of iodined won't work.)

------------------------------------------------------------------------

> sudo ./iodine -f -P 123 202.106.0.20 t1.carlzeng.top
No tun devices found, trying utun
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
iodine: open_utun: connect: Resource busy
Opened utun6
Opened IPv4 UDP socket
Sending DNS queries for t1.carlzeng.top to 202.106.0.20
Autodetecting DNS query type (use -T to override).....................
iodine: No suitable DNS query type found. Are you connected to a network?
iodine: If you expect very long roundtrip delays, use -T explicitly.
iodine: (Also, connecting to an "ancient" version of iodined won't work.)

#1解决办法:

换一个客户端来测试(从Mac换到OpenWrt,或者Debian)

使用官方的在线工具测试:https://code.kryo.se/iodine/check-it/

1
2
3
4
5
6
7
8
9
10
Troubleshoot your iodine setup

Analyzing DNS setup for tunnel domain 't1.carlzeng.top'... (might take some time)

Looking for nameserver for carlzeng.top.. got paityn.ns.cloudflare.com (at 108.162.194.18).
Resolving delegation of t1.carlzeng.top at 108.162.194.18... to t1ns.carlzeng.top (at 125.34.235.88).

Expecting iodined to be accessible at 125.34.235.88... no reply.

Error: Make sure iodined is running and the firewall accepts UDP port 53. Also check any port forwards in use.
1
iodined -f -DDD -l 125.34.235.88 -p 53 -P 123 10.0.0.1 t1.carlzeng.top
1
2
#最终改进后的服务端命令
iodined -f -c -l 125.34.235.88 -p 53 -P 123 10.0.0.1 t1.carlzeng.top

  1. 关闭了iodined以后,仍然还是53端口开启状态,这是相当不正常?(后来来看,这是正常的)
1
2
3

nc -vz op.carlzeng.top 53
Connection to op.carlzeng.top port 53 [tcp/domain] succeeded!

#2解决方法:

​ 登录到OpenWrt的SSH,关闭dnsmasq服务

1
2
3
4
5
6
7
#关闭OpenWrt的DHCP和DNS服务
/etc/init.d/dnsmasq stop


#关闭,重启,防火墙服务
/etc/init.d/firewall stop
/etc/init.d/firewall restart

登录到UI,修改DNS服务端口从53改为5353:

原来iodined使用的是udp的53端口,而运行完iodined这个是开启着的

1
2
3
#NC检查udp端口情况, -vz(检测TCP端口) 变成 -vuz(检测UDP端口)
> nc -vuz 192.168.6.1 53
Connection to 192.168.6.1 port 53 [udp/domain] succeeded!

最终的解决方法是:

让iodined指定监听OpenWrt的Wan口IP地址,举例:-l 125.34.235.88(这是你iodined的公网IP地址)

#3 检查进程是否在运行,以及端口的使用情况

1
2
3
4
5
6
7
# 搜索输出的内容包含特定字符的行
ps | grep iodine
# 在进程列表中搜索包含iodine


# 在开放端口的列表中模糊搜索53端口的所有信息
netstat -tulpn | grep 53

#4 客户端和服务端连接成功后(调试信息可见:Connection setup complete, transmitting data. ),

如果客户端依旧无法ping通192.168.99.1(iodined服务端虚拟接口被分配的IP地址)

成功后如果客户端依旧无法ping通192.168.99.1

#4 解决方法:

开启OpenWrt(iodine服务端)的防火墙,允许入站数据包(入站数据 = 接受)。

#5 客户端和服务端连接成功后(调试信息可见:Connection setup complete, transmitting data. ),

如果客户端依旧无法ssh通192.168.99.1(iodined服务端虚拟接口被分配的IP地址)的22端口。

#5 解决方法:

配置OpenWrt的系统 》 管理权

设置 “接口” 为 “未指定”; 含义: 仅监听指定的接口,未指定则监听全部

#6 修改了OpenWrt的防火墙设置或DHCP/DNS设置后,

iodine: Got reply without error, but also without question and/or answer

1
2
3
4
#客户端重启提示错误:
iodine: Got NOTIMP as reply: server does not support our request
.....
iodine: No suitable DNS query type found. Are you connected to a network?

#6 解决方法:

重启服务端+客户端,必须都要重启(因为服务的其他设置被修改了,需要重启;

而客户端因为服务端重启了,也需要被重启)

1
2
3
4
5
6
7
8
9
10
# 服务端查询旧的iodined所运行的进程ID,然后kill
ps | grep iodine
kill -9 {pid}

#直到输出变成:
# ps | grep iodine
9291 root 1200 S grep iodine

#然后重新启动
iodined -c -l 125.34.235.88 -p 53 -P 123 192.168.99.1/24 t1.carlzeng.top
1
2
3
4
#客户端,Mac OSX为例:
> sudo ./iodine -r -f -P 123 202.106.0.20 t1.carlzeng.top
....
Connection setup complete, transmitting data.

#7 由于连接速度慢,当并发多的时候(同时刷新多个网页)服务经常容易进入假死状态,这是远程如何重启整个链路呢?

#7解决办法:

7.1 ssh进iodined的服务器:ssh root@192.168.99.1

7.2 ps | grep iodined

7.3 kill -9 23611 && iodined -c -l 125.34.235.88 -p 53 -P 123 192.168.99.1/24 t1.carlzeng.top

这样就可以远程重启iodined服务端,然后在本地在重启一下iodine就可以获取到全新的链路

在线检测DNS以及iodined配置

https://code.kryo.se/iodine/check-it/

Troubleshoot your iodine setup

Analyzing DNS setup for tunnel domain ‘t1.carlzeng.top’… (might take some time)

Looking for nameserver for carlzeng.top.. got amir.ns.cloudflare.com (at 108.162.193.62).
Resolving delegation of t1.carlzeng.top at 108.162.193.62… to t1ns.carlzeng.top (at 125.34.235.**).

Expecting iodined to be accessible at 125.34.235.**… yes, using proto 00000502.
Testing iodine reply using default nameserver… ok.

Well done, your iodine setup seems fine!

感谢列表

iodineReadMeGithub

[HOWTO] DNS tunneling with iodined on TurrisOS HBK [5.2.3]

内网隐藏通信隧道技术——DNS隧道

Iodined - how to use free internet on airports