使用 Netcat 或 /dev/udp/ 创建 DNS 查询

use*_*280 6 linux command-line bash dns debian

nc我正在尝试使用orbash和发送有效的 DNS 请求/dev/udp/

我创建了一个有效的 DNS 数据包作为模板:

tcpdump -XX port 53
Run Code Online (Sandbox Code Playgroud)

然后,在新终端中使用curl发出请求:

curl https://duckduckgo.com/
Run Code Online (Sandbox Code Playgroud)

这会在 tcpdump 终端中生成以下数据。

    0x0000:  4500 003c b0b4 4000 4011 73c3 0a00 020f  E..<..@.@.s.....
    0x0010:  0a2a 0001 bdd4 0035 0028 4f24 cfc9 0100  .*.....5.(O$....
    0x0020:  0001 0000 0000 0000 0a64 7563 6b64 7563  .........duckduc
    0x0030:  6b67 6f03 636f 6d00 0001 0001            kgo.com.....
Run Code Online (Sandbox Code Playgroud)

由此,我稍微修改了请求以匹配此参考并将其保存到文件中/tmp/ddg.txt

0000:  4500 003c b0b4 4000 4011 73c3 0a00 020f  E..<..@.@.s.....
0010:  0a2a 0001 bdd4 0035 0028 4f24 cfc9 0100  .*.....5.(O$....
0020:  0001 0000 0000 0000 0a64 7563 6b64 7563  .........duckduc
0030:  6b67 6f03 636f 6d00 0001 0001            kgo.com.....
Run Code Online (Sandbox Code Playgroud)

然后,尝试生成请求,但收到以下错误消息:

xxd -r /tmp/ddg.txt | nc -q 1 -nu 10.42.0.1 53
xxd: sorry, cannot seek backwards.
Run Code Online (Sandbox Code Playgroud)

在 Wireshark 中,请求的格式不正确。我在这里犯了什么错?是否可以使用此方法发送正确的 DNS 查询?

在此输入图像描述

A.B*_*A.B 4

您已经使用了tcpdump。但是您应该像后来那样使用wireshark :您会发现您犯了与您提供的链接中相同的错误:您包含了额外的IPv4 + UDP标头:您必须只向netcat提供UDP有效负载命令,因为它已经发送了 IPv4 UDP 数据包。

这是没有任何多余地址的十六进制数据:

IPv4 标头

4500 003c b0b4 4000 4011 73c3 0a00 020f 0a2a 0001
Run Code Online (Sandbox Code Playgroud)

UDP 标头(0028 是整个 UDP 部分的长度:8+20 => 长度为 0x20 = 32 字节的有效负载):

bdd4 0035 0028 4f24
Run Code Online (Sandbox Code Playgroud)

UDP 负载:

cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001
Run Code Online (Sandbox Code Playgroud)

xxd可以使用-p参数而不是写入,但更重要的是不需要任何地址-r(这避免了必须重写并现在重新编号这些地址):

-p | -ps | -postscript | -plain
以 postscript 连续十六进制转储样式输出。也称为纯十六进制转储样式。

当反转 ( -r) 时,它也会忽略任何空格,无论它们在哪里。

这是完成的测试(我只是放回你自己的 DNS 服务器 IP,而不是运行良好的测试 IP):

$ echo cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001 |
    xxd -p -r | nc -q1 -w2 -n -u 10.42.0.1 53 | xxd
00000000: cfc9 8180 0001 0001 0004 0000 0a64 7563  .............duc
00000010: 6b64 7563 6b67 6f03 636f 6d00 0001 0001  kduckgo.com.....
00000020: c00c 0001 0001 0000 005e 0004 2872 b19c  .........^..(r..
00000030: c00c 0002 0001 0002 91bb 0014 0464 6e73  .............dns
00000040: 3303 7030 3505 6e73 6f6e 6503 6e65 7400  3.p05.nsone.net.
00000050: c00c 0002 0001 0002 91bb 0007 0464 6e73  .............dns
00000060: 31c0 41c0 0c00 0200 0100 0291 bb00 0704  1.A.............
00000070: 646e 7332 c041 c00c 0002 0001 0002 91bb  dns2.A..........
00000080: 0007 0464 6e73 34c0 41                   ...dns4.A
Run Code Online (Sandbox Code Playgroud)

将netcat替换为socat:替换nc -q1 -w2 -n -u 10.42.0.1 53socat udp4:10.42.0.1:53 -. 它可以更好地处理 EOF 条件(因此无需等待两秒钟)。


如果您想使用 bash 的内置函数/dev/udp而不是netcatsocat,那么使用两个半双工命令(一个仅写入,另一个仅读取)处理全双工套接字会变得更加复杂。对于这种非交互式情况,不需要分叉第一个输出命令(否则,对于更复杂的情况,可以将;beforedd替换&为让输出和输入并行工作)。它仍然需要dd只抓取一个数据包并完成,从而避免xxd阻塞:

( echo cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001 | xxd -p -r >&3; dd bs=9000 count=1 <&3 2>/dev/null | xxd ) 3>/dev/udp/10.42.0.1/53
Run Code Online (Sandbox Code Playgroud)