tcpdump的工作原理:

    telnet、ftp等应用程序,其网络通信收发数据,会通过完整的Linux网络协议栈,由Linux操作系统完成数据的封装和解封装,应用程序只需要对应用层数据进行读写即可。

    tcpdump这一类程序则依赖libpcap。libpcap使用的是一种称为设备层的包接口技术。这种技术使得应用程序可以直接读写内核驱动层面的数据,而不经过Linux网络协议栈。

    以上,可以看出tcpdump和iptables的关系:

        tcpdump直接从网络驱动层面抓取数据。不经过任何Linux网络协议栈。iptables依赖的netfilter模块工作在Linux网络协议栈中。因此iptables的入栈策略不会影响到tcpdump抓取数据。

        应用程序对外发送的数据包会先经过Linux网络协议栈,再到达网络驱动设备。因此,iptables的出栈策略会影响数据包发送到网络驱动设备层面,影响tcpdump抓取数据。

Image.png


tcpdump常用参数和过滤器:

    5个参数:

    -i参数: 指定需要抓包的网卡。如果未指定,tcpdump会根据搜索到的系统中状态为UP的最小数字的网卡,一般情况下是eth0。
    -nnn参数: 禁止tcpdump展示时,将IP和端口转换为域名、端口对应的指明服务名称。
    -s参数: 指定抓取的数据包的大小。使用-s 0指定数据包大小为262144字节,可以使得抓到的数据包不被截断,完整反映数据包的内容。
    -c参数: 指定抓取的数据包的数量。
    -w参数: 指定抓取的数据包保存到相应的文件。

    过滤器:

    host x.x.x.x: 指定抓取本机和主机x.x.x.x的通信数据。
    tcp port x: 指定抓取TCP协议源端口或目的端口为x的通信数据。
    icmp: 仅抓取icmp协议的通信数据。
    !: 反向匹配。例如port !22,抓取非22端口的通信数据。
    可以使用and或or进行组合:
    host x.x.x.x and tcp port x:只抓取本机和主机x.x.x.x之间基于TCP的源端口或者目的端口是x的通信。
    tcp port x or icmp:抓取TCP协议目的端口或者源端口为x的数据通信或者ICMP协议的数据通信。

    例子,通过wget请求www.example.com,使用tcpdump抓取通信过程中的数据包,如下:

# tcpdump host www.example.com -i eth0 -nnn -s 0 -w example.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
^C14 packets captured
18 packets received by filter
0 packets dropped by kernel

    保存的example.pcap文件可以使用wireshark打开进行分析。

   

更多实例:

直接运行tcpdump,将抓取所有经过第一块网卡的数据包:

# tcpdump
11:30:46.125973 IP testmachine.ssh > 192.168.1.38.52513: Flags [P.], seq 142248509:142248705, ack 2170915706, win 143, length 196
11:30:46.126185 IP testmachine.60920 > public1.114dns.com.domain: 19252+ PTR? 38.1.168.192.in-addr.arpa. (43)



抓取所有经过第一块网卡的数据包:

# tcpdump -n -i eth0
11:35:40.080066 IP 192.168.1.186.ssh > 192.168.1.38.52513: Flags [P.], seq 142339561:142339757, ack 2170921190, win 143, length 196
11:35:40.080466 IP 192.168.1.38.52513 > 192.168.1.186.ssh: Flags [.], ack 196, win 16425, length 0


抓取所有经过网卡eth0,源地址或目的地址是192.168.1.186的数据包:

# tcpdump -n -i eth0 host 192.168.1.186
11:39:15.309068 IP 192.168.1.186.ssh > 192.168.1.38.52513: Flags [P.], seq 142386981:142387177, ack 2170925926, win 143, length 196
11:39:15.309482 IP 192.168.1.38.52513 > 192.168.1.186.ssh: Flags [.], ack 196, win 16194, length 0



抓取主机192.168.1.186与主机192.168.1.38或192.168.1.185通信的数据包:

# tcpdump -n host 192.168.1.186 and \(192.168.1.38 or 192.168.1.185\)
11:49:34.684823 IP 192.168.1.186.ssh > 192.168.1.38.52513: Flags [P.], seq 142404321:142404517, ack 2170931158, win 143, length 196
11:49:34.685348 IP 192.168.1.38.52513 > 192.168.1.186.ssh: Flags [.], ack 196, win 16350, length 0



抓取主机192.168.1.186与除了192.168.1.38之外的所有主机通信的数据包:

# tcpdump -n host 192.168.1.186 and ! 192.168.1.38
11:53:49.252813 IP 206.189.71.172.59736 > 192.168.1.186.ssh: Flags [S], seq 1757279264, win 65535, options [mss 1220], length 0
11:53:49.252847 IP 192.168.1.186.ssh > 206.189.71.172.59736: Flags [S.], seq 1494230099, ack 1757279265, win 14600, options [mss 1460], length 0



抓取主机192.168.1.186经由网卡eth0发送的所有数据包:

# tcpdump -i eth0 src host 192.168.1.186
3:44:44.523972 IP testmachine.ssh > 192.168.1.38.52513: Flags [P.], seq 142491065:142491261, ack 2170944970, win 143, length 196
13:44:44.524182 IP testmachine.51694 > public1.114dns.com.domain: 59005+ PTR? 38.1.168.192.in-addr.arpa. (43)



抓取主机192.168.1.186的网卡eth0接收到的所有数据包:

# tcpdump -i eth0 dst host 192.168.1.186
13:48:18.475454 IP 192.168.1.38.52513 > testmachine.ssh: Flags [.], ack 142529981, win 16350, length 0
13:48:18.477576 IP public1.114dns.com.domain > testmachine.40932: 8308 NXDomain* 0/1/0 (98)



抓取主机192.168.1.186的TCP 22端口接收到的数据包:

# tcpdump -i eth0 host 192.168.1.186 and tcp dst port 22
13:51:42.561420 IP 192.168.1.38.52513 > testmachine.ssh: Flags [.], ack 142596805, win 16337, length 0
13:51:42.771164 IP 192.168.1.38.52513 > testmachine.ssh: Flags [.], ack 149, win 16300, length 0



抓取所有经过eth0,TCP 端口是22,目的地址是192.168.1.38或192.168.1.185的数据包:

# tcpdump -i eth0 tcp port 22 and \(dst host 192.168.1.38 or dst host 192.168.1.185\)
# tcpdump -i eth0 '((tcp) and (prot 22) and ((dst host 192.168.1.38) or (dst host 192.168.1.185)))'
14:06:17.744857 IP testmachine.ssh > 192.168.1.38.52513: Flags [P.], seq 9480:9644, ack 1, win 143, length 164
14:06:17.745849 IP testmachine.ssh > 192.168.1.38.52513: Flags [P.], seq 9644:9808, ack 1, win 143, length 164



抓取SYN或ACK数据包:

# tcpdump -i eth0 'tcp[tcpflags] = tcp-syn' or 'tcp[tcpflags] = tcp-ack'
14:19:46.335429 IP 192.168.1.38.52513 > testmachine.ssh: Flags [.], ack 142950437, win 16350, length 0
14:19:46.545319 IP 192.168.1.38.52513 > testmachine.ssh: Flags [.], ack 149, win 16313, length 0