tcpdump

什么是tcpdump?

A powerful command-line packet analyzer; and libpcap, a portable C/C++ library for network traffic capture.

一个强大的抓包命令行工具,还有libpcap,一个跨平台的C/C++网络抓包库。

老高为了学习研究路由器上的流量包,所以本文的tcpdump的运行环境都是基于Linux的openwrt。

老高的建议:把流量比作水源,工具tcpdump就是一个过滤器,能够过滤出我们需要的纯净水,而水源有很多技术特征能够为我所用。

帮助命令

[root@PandoraBox:/root]#tcpdump -h
tcpdump version 4.5.1
libpcap version 1.5.3
Usage: tcpdump [-aAbdDefhHIJKlLnNOpqRStuUvxX] [ -B size ] [ -c count ]
		[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
		[ -i interface ] [ -j tstamptype ] [ -M secret ]
		[ -P in|out|inout ]
		[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]
		[ -W filecount ] [ -y datalinktype ] [ -z command ]
		[ -Z user ] [ expression ]

由此命令我们能够得到,tcpdump的版本为4.5.1,依赖库libpcap的版本为1.5.3。不同版本所支持的选项可能不一样。

基础命令

小tip,-nn可以不解析协议和端口号 -X 可以列出十六进制 (hex) 以及 ASCII 的数据包內容,后面还可以接关键字过滤。

列出可用接口

既然是抓包,那自然需要知道我们当前要抓取的是哪一个网络接口的数据包。

tcpdump -D

1.eth0
2.br-lan
3.eth0.1
4.eth0.2
5.pppoe-wan  
6.rai0
7.ra0
8.6to4-wan6
9.any (Pseudo-device that captures on all interfaces)
10.lo

监听指定接口

tcpdump -i eth0
tcpdump: WARNING: eth0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

# 如果没有指定接口,默认取第一个设备
tcpdump
tcpdump: WARNING: eth0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

监听指定主机名

假如老高的主机名为Laogao.lan,那么就可以指定host来滤出我的主机与路由器的通信。

# 指定主机名或IP
tcpdump -i rai0 host Laogao
tcpdump -i rai0 host 192.168.1.111
# 指定非192.168.1.111的流量
tcpdump -i rai0 host !192.168.1.111

# 抓取Laogao 之间 Laogao2的流量
tcpdump -i rai0 host Laogao or Laogao2

# 抓取Laogao 或 Laogao2的流量
tcpdump -i rai0 host Laogao or Laogao2

# 抓取从老高的主机发送的流量
tcpdump -i rai0 src host Laogao

# 抓取发送到老高的主机的流量
tcpdump -i rai0 dst host Laogao

以上命令还可以看出老高在使用 5G的频段

如何获取局域网中的设备主机名呢?老高提供几个关键字arp -a 192.168.1.110、host 192.168.1.110、nbtscan 192.168.1.0/24

关键字

体会了几个简答的命令后我们总结一下,tcpdump的几个关键字

  1. type qualifiers 类型关键字 host port nat
  2. dir qualifiers 方向关键字 src dst 、 src or dst 、 src and dst
  3. proto qualifiers 协议关键字 ether/fddi/ip/arp/rarp/decent/lat/sca/moprc/mopdl/tcp/udp

特殊的primitive关键字 gateway,broadcast,less,greater 逻辑运算符 : 与运算符 ‘and’、'&&'、 非运算符 ‘not’、'!' 或运算符 ‘or’、'||'

更复杂的例子

我们使用tcpdump观察TCP建立连接时的三次握手:

tcpdump -Stnn -i br-lan host 192.168.1.110 and 45.62.107.90 -c 30

# 当客户端想要对服务器端联机时,就必须要送出一个要求联机的封包,此时客户端必须随机取用一个大于 1024 以上的端口来做为程序沟通的接口。然后在 TCP 的表头当中,必须要带有 SYN 的主动联机(SYN=1),并且记下发送出联机封包给服务器端的序号 (Sequence number = 3818646240) 。

IP 192.168.1.110.57339 > 45.62.107.90.80: Flags [S], seq 3818646240, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 806255609 ecr 0,sackOK,eol], length 0

# 当服务器接到这个封包,并且确定要接收这个封包后,就会开始制作一个同时带有 SYN=1, ACK=1 的封包, 其中那个 acknowledge 的号码是要给 client 端确认用的,所以该数字会比(A 步骤)里面的 Sequence 号码多一号 (ack = 3818646240+1 = 3818646241), 那我们服务器也必须要确认客户端确实可以接收我们的封包才行,所以也会发送出一个 Sequence (seq=425027616) 给客户端,并且开始等待客户端给我们服务器端的回应喔!

IP 45.62.107.90.80 > 192.168.1.110.57339: Flags [S.], seq 425027616, ack 3818646241, win 14480, options [mss 1460,sackOK,TS val 2209935609 ecr 806255609,nop,wscale 7], length 0

# 当客户端收到来自服务器端的 ACK 数字后 (3818646241) 就能够确认之前那个要求封包被正确的收受了, 接下来如果客户端也同意与服务器端建立联机时,就会再次的发送一个确认封包 (ACK=1) 给服务器,亦即是 acknowledge = 425027616+1 = 425027617 啰。可以看到此时Flags中只有一个小数点,表示这个包只是用来做确认的。

IP 192.168.1.110.57339 > 45.62.107.90.80: Flags [.], ack 425027617, win 4117, options [nop,nop,TS val 806255911 ecr 2209935609], length 0

至此三次握手完成!

tcp状态FLAG可能的值:

F : FIN - 结束; 结束会话
S : SYN - 同步; 表示开始会话请求
R : RST - 复位;中断一个连接
P : PUSH - 推送; 数据包立即发送
A : ACK - 应答
U : URG - 紧急
E : ECE - 显式拥塞提醒回应
W : CWR - 拥塞窗口减少
. : 没有状态