Thursday, 2 April 2015

[Sysad] một trận chiến giữa netcat và tcpdump

bình yên quá, dậy sóng thôi.

Cài đặt hai bên chiến tuyến:
# apt-get install -y tcpdump  netcat-openbsd
Sau đây hai đấu thủ cùng ra chào khán giả:
# for pkg in nc tcpdump; do whatis $pkg; whereis $pkg; done
nc (1)               - arbitrary TCP and UDP connections and listens
nc: /bin/nc /bin/nc.openbsd /usr/share/man/man1/nc.1.gz
tcpdump (8)          - dump traffic on a network
tcpdump: /usr/sbin/tcpdump /usr/share/man/man8/tcpdump.8.gz
Bây giờ là phần quảng cáo bỉm sữa và bình luận trước trận đấu:
- Bên công rõ ràng là nc, với khả năng tạo kết nối TCP/UDP tuỳ ý (ngoài ra có cả khả năng listen).
- Bên thủ chính là tcpdump danh tiếng, với khả năng "dump" mọi traffic trên 1 network, tcpdump có thể xử lý rất nhiều protocol khác nhau: ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp and udp, rõ ràng là hơn nc vài bậc về dạng rộng. ($ man pcap-filter | sed -n "/  proto  /,/If/ p" | sed 's/If.*//g')

Trận đấu bắt đầu trên sân vận động TCP:

đấu thủ nc bắt đầu ra đòn:
$ echo QUIT | nc -vtq2 localhost 1235
để gửi message QUIT đến port tcp số 1235 (-t hoặc không cần cũng được) trên host localhost
-v để cho nó dài ra một tí, ai cũng thích dài mà
-q2 khiến nc đợi 2 giây rồi kết thúc sau khi nhận được message QUIT từ lệnh echo (từ stdin).
vậy gộp lại ta có -vtq2 hay -vq2 đều ổn.

Bên tcpdump sẽ đỡ như nào:
$ tcpdump -i lo -nc1 src host 127.0.0.1 and tcp port 1235 2>/dev/null 
-i lo là interface loopback (cho 127.0.0.1/localhost), bình thường có thể dùng eth0 / eth1 ... hoặc thậm chí không cần chỉ định nếu muốn bắt packet trên tất cả các interface)
-n để hiện toàn là số, không đổi các địa chỉ ra chữ (host/port)
-c1 khiến câu lệnh dừng lại sau khi bắt được 1 packet.
theo sau các option trên là phần expression:
src host: địa chỉ nguồn của packet
tcp: bắt packet TCP (bỏ qua các loại packet khác, vd UDP)
port: port cần bắt packet.

Tổng hợp các option lại ta có: -i lo -nc1
để kết nối các expression, dùng "and": src host 127.0.0.1 and tcp port 1235
Kết quả là:
# tcpdump -i lo -nc1 src host 127.0.0.1 and tcp port 1235 2>/dev/null &
[2] 4306 # dùng & ở đây bởi ta muốn 2 lệnh này chạy ~ cùng lúc
# echo QUIT | nc -vtq2 localhost 123519:28:08.539020 IP 127.0.0.1.43215 > 127.0.0.1.1235: Flags [S], seq 1791095298, win 43690, options [mss 65495,sackOK,TS val 732658 ecr 0,nop,wscale 6], length 0
nc: connect to localhost port 1235 (tcp) failed: Connection refused
nc báo Connection refused bởi port 1235 đang không có dịch vụ nào listen cả, TCP là loại giao thức hướng kết nối, nên nếu tình cảm không đến từ hai phía, một bên sẽ nhận được "Connection refuse".

UDP thì sao? bản chất của giao thức sẽ thể hiện ở đây:
Thay -t ở nc bằng -u, thay tcp ở tcpdump bằng udp:
# tcpdump -i lo -nc1 src host 127.0.0.1 and udp port 1369 2>/dev/null &
[2] 4315
# echo QUIT | nc -vuq2 localhost 1369
19:30:32.073852 IP 127.0.0.1.43896 > 127.0.0.1.1369: UDP, length 5
nc không báo lỗi, bởi UDP là loại giao thức không hướng kết nối, một bên cứ gửi, ai nhận thì nhận, chẳng nhận thì thôi, giống như kiểu tình đơn phương vậy, không cần đáp lại, chỉ vậy hoy.

Script thực hiện bài viết:

Bài viết thực hiện với:
# dpkg -l tcpdump  netcat-openbsd | grep ii
ii  netcat-openbsd                   1.89-4ubuntu1                     TCP/IP swiss army knife
ii  tcpdump                          4.2.1-1ubuntu2.1                  command-line network traffic analyzer
# lsb_release -d
Description:    Ubuntu 12.04.5 LTS
Tham khảo:
http://manpages.ubuntu.com/manpages/oneiric/man1/nc_openbsd.1.html
http://manpages.ubuntu.com/manpages/precise/en/man7/pcap-filter.7.html
http://manpages.ubuntu.com/manpages/precise/en/man8/tcpdump.8.html