tcpdump的工作原理:
telnet、ftp等应用程序,其网络通信收发数据,会通过完整的Linux网络协议栈,由Linux操作系统完成数据的封装和解封装,应用程序只需要对应用层数据进行读写即可。
tcpdump这一类程序则依赖libpcap。libpcap使用的是一种称为设备层的包接口技术。这种技术使得应用程序可以直接读写内核驱动层面的数据,而不经过Linux网络协议栈。
以上,可以看出tcpdump和iptables的关系:
tcpdump直接从网络驱动层面抓取数据。不经过任何Linux网络协议栈。iptables依赖的netfilter模块工作在Linux网络协议栈中。因此iptables的入栈策略不会影响到tcpdump抓取数据。
应用程序对外发送的数据包会先经过Linux网络协议栈,再到达网络驱动设备。因此,iptables的出栈策略会影响数据包发送到网络驱动设备层面,影响tcpdump抓取数据。
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