2012/03/25

用 shell script 做一個假的 DNS

很有趣的問題,突然跟我同事在想要怎麼快速做一個假的DNS (Domain Name Server)? 不就follow 鳥哥的教學,用 bind 架一個就好了?
有想過寫在 /etc/hosts,但發現 nslookup 並不會去查詢 hosts file

Anyway, geek 就喜歡搞怪,喜歡繞道而行,喜歡自己造輪子...

=> 想到用 netcat 當 dns proxy,把 dns query redirect 給 8.8.8.8,但遇到 special 的 domain name 時,就自己 return。



Step1: 測試 dns proxy
$ sudo nc -v -u -l -s 127.0.0.1 -p 53 -e 'nc -u 8.8.8.8 53'
$ nslookup - 127.0.0.1
> yahoo.com
Server:         10.32.100.199
Address:        10.32.100.199#53
Non-authoritative answer:
Name:   yahoo.com
Address: 209.191.122.70
Name:   yahoo.com
Address: 72.30.38.140
Name:   yahoo.com
Address: 98.139.183.24
> 
It's work!

想看整個過程,開三個session
$ mkfifo fifo1 fifo2
$ sudo nc -u -l -s 127.0.0.1 -p 53 -c -x > fifo1 < fifo2
Received 27 bytes from the socket
00000000  E2 20 01 00  00 01 00 00  00 00 00 00  05 79 61 68  . ...........yah
00000010  6F 6F 03 63  6F 6D 00 00  01 00 01                  oo.com.....
Sent 75 bytes to the socket
00000000  E2 20 81 80  00 01 00 03  00 00 00 00  05 79 61 68  . ...........yah
00000010  6F 6F 03 63  6F 6D 00 00  01 00 01 C0  0C 00 01 00  oo.com..........
00000020  01 00 00 09  80 00 04 62  8B B7 18 C0  0C 00 01 00  .......b........
00000030  01 00 00 09  80 00 04 D1  BF 7A 46 C0  0C 00 01 00  .........zF.....
00000040  01 00 00 09  80 00 04 48  1E 26 8C                  .......H.&.

$ nc -u 8.8.8.8 53 -x < fifo1 > fifo2
Sent 27 bytes to the socket
00000000  E2 20 01 00  00 01 00 00  00 00 00 00  05 79 61 68  . ...........yah
00000010  6F 6F 03 63  6F 6D 00 00  01 00 01                  oo.com.....
Received 75 bytes from the socket
00000000  E2 20 81 80  00 01 00 03  00 00 00 00  05 79 61 68  . ...........yah
00000010  6F 6F 03 63  6F 6D 00 00  01 00 01 C0  0C 00 01 00  oo.com..........
00000020  01 00 00 09  80 00 04 62  8B B7 18 C0  0C 00 01 00  .......b........
00000030  01 00 00 09  80 00 04 D1  BF 7A 46 C0  0C 00 01 00  .........zF.....
00000040  01 00 00 09  80 00 04 48  1E 26 8C                  .......H.&.

$ nslookup - 127.0.0.1
> yahoo.com
Server:         10.32.100.199
Address:        10.32.100.199#53

Non-authoritative answer:
Name:   yahoo.com
Address: 98.139.183.24
Name:   yahoo.com
Address: 209.191.122.70
Name:   yahoo.com
Address: 72.30.38.140
>


Step 2: 截取 dns query
$ sudo nc -u -l -s 127.0.0.1 -p 53 > fake_query
$ nslookup - 127.0.0.1
> yahoo.com


Step 3: 用 fake_query 去 get response
$ cat fake_query | nc -u 8.8.8.8 53 > fake_response


Step 4: 把 fake_response 內的 ip 換成特定的 ip
(這一步還沒做)


Step 5: Start fake dns
$ mkfifo fifo1 fifo2
$ sudo nc -u -l -s 127.0.0.1 -p 53 -c > fifo1 < fifo2 &
$ sh filter.sh < fifo1 > fifo2

filter.sh 裡面會截取 current query id,然後 replace fake response 裡面的
#!/bin/sh
QID=
COUNT=0
cat - | while read -n 1 byte
do
    if [ $COUNT -lt 2 ]; then
        QID+=$byte
    fi

    if [ $COUNT -eq 2 ]; then
        echo -n $QID$(cut -b 3- fake_response)
    fi

    COUNT=`expr $COUNT + 1`
done


結果
$ nslookup - 127.0.0.1
> yahoo.com
;; Got bad packet: bad compression pointer
51 bytes
65 9c 81 80 01 03 05 79 61 68 6f 6f 03 63 6f 6d
01 01 c0 0c 01 01 01 ad 04 d1 bf 7a 46 c0 0c 01
01 01 ad 04 48 1e 26 8c c0 0c 01 01 01 ad 04 62
8b b7 18
>

Oh no~ 還是有問題,初估應該是 dns packet header 哪邊需要動態更改...
Alright! 是該停止這浪費時間的行為了...



參考資料
想利用 shell script 做到這些事情代價真大,以下是必需了解的:
  • 以 hex mode 顯示 binary file
hexdump -C file
while read -n 1 byte; do
    ord=$(printf "%b" "${byte:-\000}" |
          od -t x1 |
          { read offset hex; echo $hex; })
    echo "$ord"
done
#!/bin/sh
cat - | while read LINE
do
  echo ${LINE}
done

try ls -al | script.sh


沒有留言:

張貼留言