• tcpdump 详细使用指南(请尽情食用)


    参考

    0. 总览

    tcpdump 是一款强大的网络抓包工具,它使用 libpcap 库来抓取网络数据包,这个库在几乎在所有的 Linux/Unix 中都有。熟悉 tcpdump 的使用能够帮助你分析调试网络数据,本文将通过一个个具体的示例来介绍它在不同场景下的使用方法。不管你是系统管理员,程序员,云原生工程师还是 yaml 工程师,掌握 tcpdump 的使用都能让你如虎添翼,升职加薪。

    tcpdump 核心参数图解

    img

    1. option 可选参数:将在后边一一解释。
    2. proto 类过滤器:根据协议进行过滤,可识别的关键词有: tcp, udp, icmp, ip, ip6, arp, rarp,ether,wlan, fddi, tr, decnet
    3. type 类过滤器:可识别的关键词有:host, net, port, portrange,这些词后边需要再接参数。
    4. direction 类过滤器:根据数据流向进行过滤,可识别的关键字有:src, dst,同时你可以使用逻辑运算符进行组合,比如 src or dst

    参数列表

    设置不解析域名提升速度
    -n不把ip转化成域名,直接显示 ip,避免执行 DNS lookups 的过程,速度会快很多
    -nn不把协议和端口号转化成名字,速度也会快很多。
    -N不打印出host 的域名部分.。比如,,如果设置了此选现,tcpdump 将会打印’nic’ 而不是 ‘nic.ddn.mil’.
    过滤指定网卡的数据包
    -i指定要过滤的网卡接口,如果要查看所有网卡,可以 -i any
    过滤特定流向的数据包
    -Q选择是入方向还是出方向的数据包,可选项有:in, out, inout,也可以使用 --direction=[direction] 这种写法
    常用的一些参数
    -A以ASCII码方式显示每一个数据包(不显示链路层头部信息). 在抓取包含网页数据的数据包时, 可方便查看数据
    -l基于行的输出,便于你保存查看,或者交给其它工具分析
    tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host’
    通过 egrep 可以同时提取用户代理和主机名(或其他头文件):
    -q简洁地打印输出。即打印很少的协议相关信息, 从而输出行都比较简短.
    -c捕获 count 个包 tcpdump 就退出
    -stcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s numbernumber 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
    -S使用绝对序列号,而不是相对序列号
    -Cfile-size,tcpdump 在把原始数据包直接保存到文件中之前, 检查此文件大小是否超过file-size. 如果超过了, 将关闭此文件,另创建一个文件继续用于原始数据包的记录. 新创建的文件名与-w 选项指定的文件名一致, 但文件名后多了一个数字.该数字会从1开始随着新创建文件的增多而增加. file-size的单位是百万字节(nt: 这里指1,000,000个字节,并非1,048,576个字节, 后者是以1024字节为1k, 1024k字节为1M计算所得, 即1M=1024 * 1024 = 1,048,576)
    -F使用file 文件作为过滤条件表达式的输入, 此时命令行上的输入将被忽略.
    过滤结果输出到文件
    -w使用 -w 参数后接一个以 .pcap 后缀命令的文件名,就可以将 tcpdump 抓到的数据保存到文件中。使用 wireshark 打开此文件便可进行分析tcpdump icmp -w icmp.pcap
    -r从文件中读取数据,读取后,我们照样可以使用上述的过滤器语法进行过滤分析。tcpdump icmp -r all.pcap
    对输出内容进行控制的参数
    -D显示所有可用网络接口的列表
    -e每行的打印输出中将包括数据包的数据链路层头部信息
    -E揭秘IPSEC数据
    -L列出指定网络接口所支持的数据链路层的类型后退出
    -Z后接用户名,在抓包时会受到权限的限制。如果以root用户启动tcpdump,tcpdump将会有超级用户权限。
    -d打印出易读的包匹配码
    -dd以C语言的形式打印出包匹配码.
    -ddd以十进制数的形式打印出包匹配码
    控制详细内容的输出
    -v产生详细的输出. 比如包的TTL,id标识,数据包长度,以及IP包的一些选项。同时它还会打开一些附加的包完整性检测,比如对IP或ICMP包头部的校验和。
    -vv产生比-v更详细的输出. 比如NFS回应包中的附加域将会被打印, SMB数据包也会被完全解码。(摘自网络,目前我还未使用过)
    -vvv产生比-vv更详细的输出。比如 telent 时所使用的SB, SE 选项将会被打印, 如果telnet同时使用的是图形界面,其相应的图形选项将会以16进制的方式打印出来(摘自网络,目前我还未使用过)
    控制时间的显示
    -t在每行的输出中不输出时间
    -tt在每行的输出中会输出时间戳
    -ttt输出每两行打印的时间间隔(以毫秒为单位)
    -tttt在每行打印的时间戳之前添加日期的打印(此种选项,输出的时间最直观)
    显示数据包的头部
    -x以16进制的形式打印每个包的头部数据(但不包括数据链路层的头部)
    -xx以16进制的形式打印每个包的头部数据(包括数据链路层的头部)
    -X以16进制和 ASCII码形式打印出每个包的数据(但不包括连接层的头部),这在分析一些新协议的数据包很方便。
    -XX以16进制和 ASCII码形式打印出每个包的数据(包括连接层的头部),这在分析一些新协议的数据包很方便。

    过滤规则组合

    有编程基础的同学,对于下面三个逻辑运算符应该不陌生了吧

    • and:所有的条件都需要满足,也可以表示为 &&
    • or:只要有一个条件满足就可以,也可以表示为 ||
    • not:取反,也可以使用 !

    举个例子,我想需要抓一个来自10.5.2.3,发往任意主机的3389端口的包

    $ tcpdump src 10.5.2.3 and dst port 3389
    
    • 1

    当你在使用多个过滤器进行组合时,有可能需要用到括号,而括号在 shell 中是特殊符号,因为你需要使用引号将其包含。例子如下:

    $ tcpdump 'src 10.0.2.4 and (dst port 3389 or 22)'
    
    • 1

    而在单个过滤器里,常常会判断一条件是否成立,这时候,就要使用下面两个符号

    • =:判断二者相等
    • ==:判断二者相等
    • !=:判断二者不相等

    当你使用这两个符号时,tcpdump 还提供了一些关键字的接口来方便我们进行判断,比如

    • if:表示网卡接口名、
    • proc:表示进程名
    • pid:表示进程 id
    • svc:表示 service class
    • dir:表示方向,in 和 out
    • eproc:表示 effective process name
    • epid:表示 effective process ID

    比如我现在要过滤来自进程名为 nc 发出的流经 en0 网卡的数据包,或者不流经 en0 的入方向数据包,可以这样子写

    $ tcpdump "( if=en0 and proc =nc ) || (if != en0 and dir=in)"
    
    • 1

    内容输出结构

    21:26:49.013621 IP 172.20.20.1.15605 > 172.20.20.2.5920: Flags [P.], seq 49:97, ack 106048, win 4723, length 48
    
    • 1

    从上面的输出来看,可以总结出:

    1. 第一列:时分秒毫秒 21:26:49.013621
    2. 第二列:网络协议 IP
    3. 第三列:发送方的ip地址+端口号,其中172.20.20.1是 ip,而15605 是端口号
    4. 第四列:箭头 >, 表示数据流向
    5. 第五列:接收方的ip地址+端口号,其中 172.20.20.2 是 ip,而5920 是端口号
    6. 第六列:冒号
    7. 第七列:数据包内容,包括Flags 标识符,seq 号,ack 号,win 窗口,数据长度 length,其中 [P.] 表示 PUSH 标志位为 1,更多标识符见下面

    理解 Flag 标识符

    截取数据只是第一步,第二步就是理解这些数据,下面就解释一下 tcpdump 命令输出各部分的意义。

    21:27:06.995846 IP (tos 0x0, ttl 64, id 45646, offset 0, flags [DF], proto TCP (6), length 64)
        192.168.1.106.56166 > 124.192.132.54.80: Flags [S], cksum 0xa730 (correct), seq 992042666, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 663433143 ecr 0,sackOK,eol], length 0
    
    21:27:07.030487 IP (tos 0x0, ttl 51, id 0, offset 0, flags [DF], proto TCP (6), length 44)
        124.192.132.54.80 > 192.168.1.106.56166: Flags [S.], cksum 0xedc0 (correct), seq 2147006684, ack 992042667, win 14600, options [mss 1440], length 0
    
    21:27:07.030527 IP (tos 0x0, ttl 64, id 59119, offset 0, flags [DF], proto TCP (6), length 40)
        192.168.1.106.56166 > 124.192.132.54.80: Flags [.], cksum 0x3e72 (correct), ack 2147006685, win 65535, length 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    最基本也是最重要的信息就是数据报的源地址/端口和目的地址/端口,上面的例子第一条数据报中,源地址 ip 是 192.168.1.106,源端口是 56166,目的地址是 124.192.132.54,目的端口是 80> 符号代表数据的方向。

    此外,上面的三条数据还是 tcp 协议的三次握手过程,第一条就是 SYN 报文,这个可以通过 Flags [S] 看出。下面是常见的 TCP 报文的 Flags:

    • [S] : SYN(开始连接)
    • [.] : 没有 Flag
    • [P] : PSH(推送数据)
    • [F] : FIN (结束连接)
    • [R] : RST(重置连接)

    而第二条数据的 [S.] 表示 SYN-ACK,就是 SYN 报文的应答报文。

    示例

    基础过滤
    # 1. 基于IP地址过滤
    # 根据源ip进行过滤
    $ tcpdump -i eth2 src 192.168.10.100
    
    # 根据目标ip进行过滤
    $ tcpdump -i eth2 dst 192.168.10.200
    
    # 2. 基于网段进行过滤:net
    $ tcpdump net 192.168.10.0/24
    # 根据源网段进行过滤  可以理解为 ip 的前缀
    $ tcpdump src net 192.168
    
    # 根据目标网段进行过滤
    $ tcpdump dst net 192.168
    
    # 示例
    $ tcpdump -i ens160  src net 10.10
    17:11:59.473114 IP 10.10.2.238.55742 > master01.cluster.local.ssh: Flags [.], ack 14604, win 2028, options [nop,nop,TS val 1375892214 ecr 4001186014], length 0
    17:11:59.473188 IP master01.cluster.local.ssh > 10.10.2.238.55742: Flags [.], seq 20844:23340, ack 1, win 501, options [nop,nop,TS val 4001186225 ecr 1375892214], length 2496
    17:11:59.489447 IP 10.10.2.50.ideafarm-door > 10.10.1.21.41714: Flags [.], ack 149, win 128, length 0
    17:11:59.498194 IP 10.10.2.238.55742 > master01.cluster.local.ssh: Flags [.], ack 15852, win 2048, options [nop,nop,TS val 1375892216 ecr 4001186042], length 0
    17:11:59.498231 IP master01.cluster.local.ssh > 10.10.2.238.55742: Flags [.], seq 23340:24588, ack 1, win 501, options [nop,nop,TS val 4001186250 ecr 1375892216], length 1248
    17:11:59.539698 IP 10.10.2.33.etcd-client > 10.10.2.49.45720: Flags [.], ack 3363427380, win 1432, options [nop,nop,TS val 3296084139 ecr 1511276523], length 0
    17:11:59.539699 IP 10.10.2.33.etcd-client > 10.10.2.49.45130: Flags [.], ack 2489720301, win 801, options [nop,nop,TS val 3296084139 ecr 1511276523], length 0
    # 可看出筛选出 所有 1 段的源 ip 包,也可以理解为前缀符合 10.10.1
    $ tcpdump -i ens160  src net 10.10.1
    dropped privs to tcpdump
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on ens160, link-type EN10MB (Ethernet), capture size 262144 bytes
    17:13:23.179904 IP 10.10.1.21.41714 > 10.10.2.50.ideafarm-door: Flags [P.], seq 3089274228:3089274265, ack 2296379143, win 3507, length 37
    17:13:23.199903 IP 10.10.1.21.41714 > 10.10.2.50.ideafarm-door: Flags [P.], seq 37:74, ack 54, win 3507, length 37
    17:13:23.386367 IP 10.10.1.21.41714 > 10.10.2.50.ideafarm-door: Flags [P.], seq 74:111, ack 210, win 3507, length 37
    17:13:23.596409 IP 10.10.1.21.41714 > 10.10.2.50.ideafarm-door: Flags [P.], seq 111:148, ack 279, win 3507, length 37
    
    # 3. 基于端口进行过滤:port
    $ tcpdump port 8088
    # 根据源端口进行过滤
    $ tcpdump src port 8088
    
    # 根据目标端口进行过滤
    $ tcpdump dst port 8088
    
    # 想要同时指定两个端口你可以这样写
    $ tcpdump port 80 or port 8088
    
    # 想抓取的不再是一两个端口,而是一个范围,一个一个指定就非常麻烦了,此时你可以这样指定一个端口段
    $ tcpdump portrange 8000-8080
    $ tcpdump src portrange 8000-8080
    $ tcpdump dst portrange 8000-8080
    
    # 对于一些常见协议的默认端口,我们还可以直接使用协议名,而不用具体的端口号 比如 http == 80,https == 443 等
    $ tcpdump tcp port http
    
    # 4. 基本IP协议的版本进行过滤
    # 当你想查看 tcp 的包,你也许会这样子写
    $ tcpdump tcp
    
    # ip 根据版本的不同,可以再细分为 IPv4 和 IPv6 两种,如果你只指定了 tcp,这两种其实都会包含在内。
    # 那有什么办法,能够将 IPv4 和 IPv6 区分开来呢?
    # 如果是 IPv4 的 tcp 包 ,就这样写
    $ tcpdump 'ip proto tcp'
    
    # 而如果是 IPv6 的 tcp 包 ,就这样写
    $ tcpdump 'ip6 proto tcp'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    过滤组合
    # 1. 通常情况下,如果不指定网络接口, tcpdump 在运行时会选择编号最低的网络接口,一般情况下是 eth0,不过因系统不同可能会有所差异。
    $ tcpdump
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    16:15:05.051896 IP blog.ssh > 10.0.3.1.32855: Flags [P.], seq 2546456553:2546456749, ack 1824683693, win 355, options [nop,nop,TS val 620879437 ecr 620879348], length 196
    
    # 2. 可以用 -i 标记来指定网络接口。在大多数 Linux 系统上,any 这一特定的网络接口名用来让 tcpdump 监听所有的接口。我发现这在排查服务器(拥有多个网络接口)的问题特别有用,尤其是牵扯到路由的时候。
    $ tcpdump -i any
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
    16:45:59.312046 IP blog.ssh > 10.0.3.1.32855: Flags [P.], seq 2547763641:2547763837, ack 1824693949, win 355, options [nop,nop,TS val 621343002 ecr 621342962], length 196
    
    # 3. 通常情况下, tcpdump 会尝试查找和转换主机名和端口号。
    $ tcpdump
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    16:15:05.051896 IP blog.ssh > 10.0.3.1.32855: Flags [P.], seq 2546456553:2546456749, ack 1824683693, win 355, options [nop,nop,TS val 620879437 ecr 620879348], length 196
    
    # 4. 可以通过 -n 标记关闭这个功能。我个人总是使用这个标记,因为我喜欢使用 IP 地址而不是主机名,主机名和端口号的转换经常会带来困扰。但是,知道利用 tcpdump 转换或者不转换的功能还是相当有用的,特别是有些时候,知道源流量(source traffic)来自哪个服务器是相当重要的。
    # -n 参数  不会讲数据包中的 ip 转换为域名,可以看出,上面没指定 -n 显示为 blog.ssh,指定了 -n 参数 显示为 10.0.3.246.22(ip为 10.0.3.246,端口为22)
    # 同理 -nn 是 不进行域名和端口名的转换,显示 ip 和 端口
    $ tcpdump -n
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    16:23:47.934665 IP 10.0.3.246.22 > 10.0.3.1.32855: Flags [P.], seq 2546457621:2546457817, ack 1824684201, win 355, options [nop,nop,TS val 621010158 ecr 621010055], length 196
    
    # 5. tcpdump 的详细信息有三个等级,你可以通过在命令行增加 v 标记的个数来获取更多的信息。通常我在使用 tcpmdump 的时候,总是使用最高等级的详细信息,因为我希望看到所有信息,以免后面会用到。
    # -c 表示抓取一个完整的数据包就退出
    $ tcpdump -vvv -c 1
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    16:36:13.873456 IP (tos 0x10, ttl 64, id 121, offset 0, flags [DF], proto TCP (6), length 184)
        blog.ssh > 10.0.3.1.32855: Flags [P.], cksum 0x1ba1 (incorrect -> 0x0dfd), seq 2546458841:2546458973, ack 1824684869, win 355, options [nop,nop,TS val 621196643 ecr 621196379], length 132
    
    # 6. 指定抓包大小, 此处为只获取包的前 100 字节
    $ tcpdump  -s 100
    
    # 7. 指定抓包数量  抓10个包就退出
    $ tcpdump  -c 10
    
    # 8. 过滤指定端口
    # 这里使用 and 操作符告诉 tcpdump 只输出端口号是 22 和 60738 的数据包
    # and 或者 && 都可以。我个人倾向于两个都使用,特别要记住在使用 && 的时候,要用单引号或者双引号包住表达式。在 BASH 中,你可以使用 && 运行一个命令,该命令成功后再执行后面的命令。通常,最好将表达式用引号包起来,这样会避免不预期的结果,特别当过滤器中有一些特殊字符的时候
    $ tcpdump  -nvvv -i any -c 3 port 22 and port 60738
    或 $ tcpdump -nvvv -i any -c 3 port 22 and port 60738
    tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
    18:05:54.069403 IP (tos 0x10, ttl 64, id 64401, offset 0, flags [DF], proto TCP (6), length 104)
        10.0.3.1.60738 > 10.0.3.246.22: Flags [P.], cksum 0x1b51 (incorrect -> 0x5b3c), seq 917414532:917414584, ack 1550997318, win 353, options [nop,nop,TS val 622541691 ecr 622538903], length 52
    18:05:54.072963 IP (tos 0x10, ttl 64, id 13601, offset 0, flags [DF], proto TCP (6), length 184)
        10.0.3.246.22 > 10.0.3.1.60738: Flags [P.], cksum 0x1ba1 (incorrect -> 0xb0b1), seq 1:133, ack 52, win 355, options [nop,nop,TS val 622541692 ecr 622541691], length 132
    18:05:54.073080 IP (tos 0x10, ttl 64, id 64402, offset 0, flags [DF], proto TCP (6), length 52)
        10.0.3.1.60738 > 10.0.3.246.22: Flags [.], cksum 0x1b1d (incorrect -> 0x1e3b), seq 52, ack 133, win 353, options [nop,nop,TS val 622541692 ecr 622541692], length 0
    
    # 9. 查找两个端口号的流量
    # 可以用 or 或者 || 操作符来过滤结果。在这个例子中,我们使用 or 操作符去截获发送和接收端口为 80 或 443 的数据流。这在 Web 服务器上特别有用,因为服务器通常有两个开放的端口,端口号 80 表示 http 连接,443 表示 https。
    $ tcpdump -nvvv -i any -c 20 'port 80 or port 443'
    tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
    18:24:28.817940 IP (tos 0x0, ttl 64, id 39930, offset 0, flags [DF], proto TCP (6), length 60)
        10.0.3.1.50524 > 10.0.3.246.443: Flags [S], cksum 0x1b25 (incorrect -> 0x8611), seq 3836995553, win 29200, options [mss 1460,sackOK,TS val 622820379 ecr 0,nop,wscale 7], length 0
    18:24:28.818052 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
        10.0.3.246.443 > 10.0.3.1.50524: Flags [R.], cksum 0x012c (correct), seq 0, ack 3836995554, win 0, length 0
    18:24:32.721330 IP (tos 0x0, ttl 64, id 48510, offset 0, flags [DF], proto TCP (6), length 475)
        10.0.3.1.60374 > 10.0.3.246.80: Flags [P.], cksum 0x1cc4 (incorrect -> 0x3a4e), seq 580573019:580573442, ack 1982754038, win 237, options [nop,nop,TS val 622821354 ecr 622815632], length 423
    18:24:32.721465 IP (tos 0x0, ttl 64, id 1266, offset 0, flags [DF], proto TCP (6), length 52)
        10.0.3.246.80 > 10.0.3.1.60374: Flags [.], cksum 0x1b1d (incorrect -> 0x45d7), seq 1, ack 423, win 243, options [nop,nop,TS val 622821355 ecr 622821354], length 0
    18:24:32.722098 IP (tos 0x0, ttl 64, id 1267, offset 0, flags [DF], proto TCP (6), length 241)
        10.0.3.246.80 > 10.0.3.1.60374: Flags [P.], cksum 0x1bda (incorrect -> 0x855c), seq 1:190, ack 423, win 243, options [nop,nop,TS val 622821355 ecr 622821354], length 189
    18:24:32.722232 IP (tos 0x0, ttl 64, id 48511, offset 0, flags [DF], proto TCP (6), length 52)
        10.0.3.1.60374 > 10.0.3.246.80: Flags [.], cksum 0x1b1d (incorrect -> 0x4517), seq 423, ack 190, win 245, options [nop,nop,TS val 622821355 ecr 622821355], length 0
    
    # 10. 查找两个特定端口和来自特定主机的数据流
    # 前面的例子用来排查多端口的协议问题,是非常有效的。如果 Web 服务器的数据流量相当大, tcpdump 的输出可能有点混乱。我们可以通过增加 host 参数进一步限定输出。在这种情况下,我们通过把 or 表达式放在括号中来保持 or 描述。
    $ tcpdump -nvvv -i any -c 20 '(port 80 or port 443) and host 10.0.3.169'
    tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
    18:38:05.551194 IP (tos 0x0, ttl 64, id 63169, offset 0, flags [DF], proto TCP (6), length 60)
        10.0.3.169.33786 > 10.0.3.246.443: Flags [S], cksum 0x1bcd (incorrect -> 0x0d96), seq 4173164403, win 29200, options [mss 1460,sackOK,TS val 623024562 ecr 0,nop,wscale 7], length 0
    18:38:05.551310 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
        10.0.3.246.443 > 10.0.3.169.33786: Flags [R.], cksum 0xa64a (correct), seq 0, ack 4173164404, win 0, length 0
    18:38:05.717130 IP (tos 0x0, ttl 64, id 51574, offset 0, flags [DF], proto TCP (6), length 60)
        10.0.3.169.35629 > 10.0.3.246.80: Flags [S], cksum 0x1bcd (incorrect -> 0xdf7c), seq 1068257453, win 29200, options [mss 1460,sackOK,TS val 623024603 ecr 0,nop,wscale 7], length 0
    18:38:05.717255 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
        10.0.3.246.80 > 10.0.3.169.35629: Flags [S.], cksum 0x1bcd (incorrect -> 0xed80), seq 2992472447, ack 1068257454, win 28960, options [mss 1460,sackOK,TS val 623024603 ecr 623024603,nop,wscale 7], length 0
    18:38:05.717474 IP (tos 0x0, ttl 64, id 51575, offset 0, flags [DF], proto TCP (6), length 52)
        10.0.3.169.35629 > 10.0.3.246.80: Flags [.], cksum 0x1bc5 (incorrect -> 0x8c87), seq 1, ack 1, win 229, options [nop,nop,TS val 623024604 ecr 623024603], length 0
    
    
    
    # tcpdump 绝对不是只能抓 TCP 数据包。它还可以用来获取其他类型的数据包,例如 ICMP、 UDP 和 ARP 包。下面是一些简单的例子,说明 tcpdump 可以截获非 TCP 数据包
    # ICMP 数据包
    $ tcpdump -nvvv -i any -c 2 icmp
    tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
    20:11:24.627824 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
        10.0.3.169 > 10.0.3.246: ICMP echo request, id 15683, seq 1, length 64
    20:11:24.627926 IP (tos 0x0, ttl 64, id 31312, offset 0, flags [none], proto ICMP (1), length 84)
        10.0.3.246 > 10.0.3.169: ICMP echo reply, id 15683, seq 1, length 64
    # UDP 数据包
    $ tcpdump -nvvv -i any -c 2 udp
    tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
    20:12:41.726355 IP (tos 0xc0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 76)
        10.0.3.246.123 > 198.55.111.50.123: [bad udp cksum 0x43a9 -> 0x7043!] NTPv4, length 48
            Client, Leap indicator: clock unsynchronized (192), Stratum 2 (secondary reference), poll 6 (64s), precision -22
            Root Delay: 0.085678, Root dispersion: 57.141830, Reference-ID: 199.102.46.75
              Reference Timestamp:  3622133515.811991035 (2014/10/12 20:11:55)
              Originator Timestamp: 3622133553.828614115 (2014/10/12 20:12:33)
              Receive Timestamp:    3622133496.748308420 (2014/10/12 20:11:36)
              Transmit Timestamp:   3622133561.726278364 (2014/10/12 20:12:41)
                Originator - Receive Timestamp:  -57.080305658
                Originator - Transmit Timestamp: +7.897664248
    20:12:41.748948 IP (tos 0x0, ttl 54, id 9285, offset 0, flags [none], proto UDP (17), length 76)
        198.55.111.50.123 > 10.0.3.246.123: [udp sum ok] NTPv4, length 48
            Server, Leap indicator:  (0), Stratum 3 (secondary reference), poll 6 (64s), precision -20
            Root Delay: 0.054077, Root dispersion: 0.058944, Reference-ID: 216.229.0.50
              Reference Timestamp:  3622132887.136984840 (2014/10/12 20:01:27)
              Originator Timestamp: 3622133561.726278364 (2014/10/12 20:12:41)
              Receive Timestamp:    3622133618.830113530 (2014/10/12 20:13:38)
              Transmit Timestamp:   3622133618.830129086 (2014/10/12 20:13:38)
                Originator - Receive Timestamp:  +57.103835195
                Originator - Transmit Timestamp: +57.103850722
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117

    1. 基本语法和使用方法

    tcpdump 的常用参数如下:

    $ tcpdump -i eth0 -nn -s0 -v port 80
    
    • 1
    • -i : 选择要捕获的接口,通常是以太网卡或无线网卡,也可以是 vlan 或其他特殊接口。如果该系统上只有一个网络接口,则无需指定。
    • -nn : 单个 n 表示不解析域名,直接显示 IP;两个 n 表示不解析域名和端口。这样不仅方便查看 IP 和端口号,而且在抓取大量数据时非常高效,因为域名解析会降低抓取速度。
    • -s0 : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s numbernumber 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
    • -v : 使用 -v-vv-vvv 来显示更多的详细信息,通常会显示更多与特定协议相关的信息。
    • port 80 : 这是一个常见的端口过滤器,表示仅抓取 80 端口上的流量,通常是 HTTP。

    额外再介绍几个常用参数:

    • -p : 不让网络接口进入混杂模式。默认情况下使用 tcpdump 抓包时,会让网络接口进入混杂模式。一般计算机网卡都工作在非混杂模式下,此时网卡只接受来自网络端口的目的地址指向自己的数据。当网卡工作在混杂模式下时,网卡将来自接口的所有数据都捕获并交给相应的驱动程序。如果设备接入的交换机开启了混杂模式,使用 -p 选项可以有效地过滤噪声。
    • -e : 显示数据链路层信息。默认情况下 tcpdump 不会显示数据链路层信息,使用 -e 选项可以显示源和目的 MAC 地址,以及 VLAN tag 信息。例如:
    $ tcpdump -n -e -c 5 not ip6
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes
    18:27:53.619865 24:5e:be:0c:17:af > 00:e2:69:23:d3:3b, ethertype IPv4 (0x0800), length 1162: 192.168.100.20.51410 > 180.176.26.193.58695: Flags [.], seq 2045333376:2045334484, ack 3398690514, win 751, length 1108
    18:27:53.626490 00:e2:69:23:d3:3b > 24:5e:be:0c:17:af, ethertype IPv4 (0x0800), length 68: 220.173.179.66.36017 > 192.168.100.20.51410: UDP, length 26
    18:27:53.626893 24:5e:be:0c:17:af > 00:e2:69:23:d3:3b, ethertype IPv4 (0x0800), length 1444: 192.168.100.20.51410 > 220.173.179.66.36017: UDP, length 1402
    18:27:53.628837 00:e2:69:23:d3:3b > 24:5e:be:0c:17:af, ethertype IPv4 (0x0800), length 1324: 46.97.169.182.6881 > 192.168.100.20.59145: Flags [P.], seq 3058450381:3058451651, ack 14349180, win 502, length 1270
    18:27:53.629096 24:5e:be:0c:17:af > 00:e2:69:23:d3:3b, ethertype IPv4 (0x0800), length 54: 192.168.100.20.59145 > 192.168.100.1.12345: Flags [.], ack 3058451651, win 6350, length 0
    5 packets captured
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    显示 ASCII 字符串

    -A 表示使用 ASCII 字符串打印报文的全部数据,这样可以使读取更加简单,方便使用 grep 等工具解析输出内容。-X 表示同时使用十六进制和 ASCII 字符串打印报文的全部数据。这两个参数不能一起使用。例如:

    $ tcpdump -A -s0 port 80
    
    • 1

    抓取特定协议的数据

    后面可以跟上协议名称来过滤特定协议的流量,以 UDP 为例,可以加上参数 udp 或 protocol 17,这两个命令意思相同。

    $ tcpdump -i eth0 udp
    $ tcpdump -i eth0 proto 17
    
    • 1
    • 2

    同理,tcp 与 protocol 6 意思相同。

    抓取特定主机的数据

    使用过滤器 host 可以抓取特定目的地和源 IP 地址的流量。

    $ tcpdump -i eth0 host 10.10.1.1
    
    • 1

    也可以使用 srcdst 只抓取源或目的地:

    $ tcpdump -i eth0 dst 10.10.1.20
    
    • 1

    将抓取的数据写入文件

    使用 tcpdump 截取数据报文的时候,默认会打印到屏幕的默认输出,你会看到按照顺序和格式,很多的数据一行行快速闪过,根本来不及看清楚所有的内容。不过,tcpdump 提供了把截取的数据保存到文件的功能,以便后面使用其他图形工具(比如 wireshark,Snort)来分析。

    -w 选项用来把数据报文输出到文件:

    $ tcpdump -i eth0 -s0 -w test.pcap
    
    • 1

    行缓冲模式

    如果想实时将抓取到的数据通过管道传递给其他工具来处理,需要使用 -l 选项来开启行缓冲模式(或使用 -c 选项来开启数据包缓冲模式)。使用 -l 选项可以将输出通过立即发送给其他命令,其他命令会立即响应。

    $ tcpdump -i eth0 -s0 -l port 80 | grep 'Server:'
    
    • 1

    组合过滤器

    过滤的真正强大之处在于你可以随意组合它们,而连接它们的逻辑就是常用的 与/AND/&&或/OR/||非/not/!

    and or &&
    or or ||
    not or !
    
    • 1
    • 2
    • 3

    2. 过滤器

    关于 tcpdump 的过滤器,这里有必要单独介绍一下。

    机器上的网络报文数量异常的多,很多时候我们只关系和具体问题有关的数据报(比如访问某个网站的数据,或者 icmp 超时的报文等等),而这些数据只占到很小的一部分。把所有的数据截取下来,从里面找到想要的信息无疑是一件很费时费力的工作。而 tcpdump 提供了灵活的语法可以精确地截取关心的数据报,简化分析的工作量。这些选择数据包的语句就是过滤器(filter)!

    Host 过滤器

    Host 过滤器用来过滤某个主机的数据报文。例如:

    $ tcpdump host 1.2.3.4
    
    • 1

    该命令会抓取所有发往主机 1.2.3.4 或者从主机 1.2.3.4 发出的流量。如果想只抓取从该主机发出的流量,可以使用下面的命令:

    $ tcpdump src host 1.2.3.4
    
    • 1

    Network 过滤器

    Network 过滤器用来过滤某个网段的数据,使用的是 CIDR 模式。可以使用四元组(x.x.x.x)、三元组(x.x.x)、二元组(x.x)和一元组(x)。四元组就是指定某个主机,三元组表示子网掩码为 255.255.255.0,二元组表示子网掩码为 255.255.0.0,一元组表示子网掩码为 255.0.0.0。例如,

    抓取所有发往网段 192.168.1.x 或从网段 192.168.1.x 发出的流量:

    $ tcpdump net 192.168.1
    
    • 1

    抓取所有发往网段 10.x.x.x 或从网段 10.x.x.x 发出的流量:

    $ tcpdump net 10
    
    • 1

    和 Host 过滤器一样,这里也可以指定源和目的:

    $ tcpdump src net 10
    
    • 1

    也可以使用 CIDR 格式:

    $ tcpdump src net 172.16.0.0/12
    
    • 1

    Proto 过滤器

    Proto 过滤器用来过滤某个协议的数据,关键字为 proto,可省略。proto 后面可以跟上协议号或协议名称,支持 icmp, igmp, igrp, pim, ah, esp, carp, vrrp, udp tcp。因为通常的协议名称是保留字段,所以在于 proto 指令一起使用时,必须根据 shell 类型使用一个或两个反斜杠(/)来转义。Linux 中的 shell 需要使用两个反斜杠来转义,MacOS 只需要一个。

    例如,抓取 icmp 协议的报文:

    $ tcpdump -n proto \\icmp
    # 或者
    $ tcpdump -n icmp
    
    • 1
    • 2
    • 3

    Port 过滤器

    Port 过滤器用来过滤通过某个端口的数据报文,关键字为 port。例如:

    $ tcpdump port 389
    
    • 1

    3. 理解 tcpdump 的输出

    截取数据只是第一步,第二步就是理解这些数据,下面就解释一下 tcpdump 命令输出各部分的意义。

    21:27:06.995846 IP (tos 0x0, ttl 64, id 45646, offset 0, flags [DF], proto TCP (6), length 64)
        192.168.1.106.56166 > 124.192.132.54.80: Flags [S], cksum 0xa730 (correct), seq 992042666, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 663433143 ecr 0,sackOK,eol], length 0
    
    21:27:07.030487 IP (tos 0x0, ttl 51, id 0, offset 0, flags [DF], proto TCP (6), length 44)
        124.192.132.54.80 > 192.168.1.106.56166: Flags [S.], cksum 0xedc0 (correct), seq 2147006684, ack 992042667, win 14600, options [mss 1440], length 0
    
    21:27:07.030527 IP (tos 0x0, ttl 64, id 59119, offset 0, flags [DF], proto TCP (6), length 40)
        192.168.1.106.56166 > 124.192.132.54.80: Flags [.], cksum 0x3e72 (correct), ack 2147006685, win 65535, length 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    最基本也是最重要的信息就是数据报的源地址/端口和目的地址/端口,上面的例子第一条数据报中,源地址 ip 是 192.168.1.106,源端口是 56166,目的地址是 124.192.132.54,目的端口是 80> 符号代表数据的方向。

    此外,上面的三条数据还是 tcp 协议的三次握手过程,第一条就是 SYN 报文,这个可以通过 Flags [S] 看出。下面是常见的 TCP 报文的 Flags:

    • [S] : SYN(开始连接)
    • [.] : 没有 Flag
    • [P] : PSH(推送数据)
    • [F] : FIN (结束连接)
    • [R] : RST(重置连接)

    而第二条数据的 [S.] 表示 SYN-ACK,就是 SYN 报文的应答报文。

    4. 例子

    下面给出一些具体的例子,每个例子都可以使用多种方法来获得相同的输出,你使用的方法取决于所需的输出和网络上的流量。我们在排障时,通常只想获取自己想要的内容,可以通过过滤器和 ASCII 输出并结合管道与 grep、cut、awk 等工具来实现此目的。

    例如,在抓取 HTTP 请求和响应数据包时,可以通过删除标志 SYN/ACK/FIN 来过滤噪声,但还有更简单的方法,那就是通过管道传递给 grep。在达到目的的同时,我们要选择最简单最高效的方法。下面来看例子。

    提取 HTTP 用户代理

    从 HTTP 请求头中提取 HTTP 用户代理:

    $ tcpdump -nn -A -s1500 -l | grep "User-Agent:"
    
    • 1

    通过 egrep 可以同时提取用户代理和主机名(或其他头文件):

    $ tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host:'
    
    • 1

    只抓取 HTTP GET 和 POST 流量

    抓取 HTTP GET 流量:

    $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
    
    • 1

    也可以抓取 HTTP POST 请求流量:

    $ tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'
    
    • 1

    注意:该方法不能保证抓取到 HTTP POST 有效数据流量,因为一个 POST 请求会被分割为多个 TCP 数据包。

    上述两个表达式中的十六进制将会与 GET 和 POST 请求的 ASCII 字符串匹配。例如,tcp[((tcp[12:1] & 0xf0) >> 2):4] 首先会 确定我们感兴趣的字节的位置(在 TCP header 之后),然后选择我们希望匹配的 4 个字节。

    提取 HTTP 请求的 URL

    提取 HTTP 请求的主机名和路径:

    $ tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:"
    
    tcpdump: listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    	POST /wp-login.php HTTP/1.1
    	Host: dev.example.com
    	GET /wp-login.php HTTP/1.1
    	Host: dev.example.com
    	GET /favicon.ico HTTP/1.1
    	Host: dev.example.com
    	GET / HTTP/1.1
    	Host: dev.example.com
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    提取 HTTP POST 请求中的密码

    从 HTTP POST 请求中提取密码和主机名:

    $ tcpdump -s 0 -A -n -l | egrep -i "POST /|pwd=|passwd=|password=|Host:"
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    11:25:54.799014 IP 10.10.1.30.39224 > 10.10.1.125.80: Flags [P.], seq 1458768667:1458770008, ack 2440130792, win 704, options [nop,nop,TS val 461552632 ecr 208900561], length 1341: HTTP: POST /wp-login.php HTTP/1.1
    .....s..POST /wp-login.php HTTP/1.1
    Host: dev.example.com
    .....s..log=admin&pwd=notmypassword&wp-submit=Log+In&redirect_to=http%3A%2F%2Fdev.example.com%2Fwp-admin%2F&testcookie=1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    提取 Cookies

    提取 Set-Cookie(服务端的 Cookie)和 Cookie(客户端的 Cookie):

    $ tcpdump -nn -A -s0 -l | egrep -i 'Set-Cookie|Host:|Cookie:'
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on wlp58s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    Host: dev.example.com
    Cookie: wordpress_86be02xxxxxxxxxxxxxxxxxxxc43=admin%7C152xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxfb3e15c744fdd6; _ga=GA1.2.21343434343421934; _gid=GA1.2.927343434349426; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_86be654654645645645654645653fc43=admin%7C15275102testtesttesttestab7a61e; wp-settings-time-1=1527337439
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    抓取 ICMP 数据包

    查看网络上的所有 ICMP 数据包:

    $ tcpdump -n icmp
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    11:34:21.590380 IP 10.10.1.217 > 10.10.1.30: ICMP echo request, id 27948, seq 1, length 64
    11:34:21.590434 IP 10.10.1.30 > 10.10.1.217: ICMP echo reply, id 27948, seq 1, length 64
    11:34:27.680307 IP 10.10.1.159 > 10.10.1.1: ICMP 10.10.1.189 udp port 59619 unreachable, length 115
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    抓取非 ECHO/REPLY 类型的 ICMP 数据包

    通过排除 echo 和 reply 类型的数据包使抓取到的数据包不包括标准的 ping 包:

    $ tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    11:37:04.041037 IP 10.10.1.189 > 10.10.1.20: ICMP 10.10.1.189 udp port 36078 unreachable, length 156
    
    • 1
    • 2
    • 3
    • 4
    • 5

    抓取 SMTP/POP3 协议的邮件

    可以提取电子邮件的正文和其他数据。例如,只提取电子邮件的收件人:

    $ tcpdump -nn -l port 25 | grep -i 'MAIL FROM\|RCPT TO'
    
    • 1

    抓取 NTP 服务的查询和响应

    $ tcpdump dst port 123
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    21:02:19.112502 IP test33.ntp > 199.30.140.74.ntp: NTPv4, Client, length 48
    21:02:19.113888 IP 216.239.35.0.ntp > test33.ntp: NTPv4, Server, length 48
    21:02:20.150347 IP test33.ntp > 216.239.35.0.ntp: NTPv4, Client, length 48
    21:02:20.150991 IP 216.239.35.0.ntp > test33.ntp: NTPv4, Server, length 48
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    抓取 SNMP 服务的查询和响应

    通过 SNMP 服务,渗透测试人员可以获取大量的设备和系统信息。在这些信息中,系统信息最为关键,如操作系统版本、内核版本等。使用 SNMP 协议快速扫描程序 onesixtyone,可以看到目标系统的信息:

    $ onesixtyone 10.10.1.10 public
    
    Scanning 1 hosts, 1 communities
    10.10.1.10 [public] Linux test33 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64
    
    • 1
    • 2
    • 3
    • 4

    可以通过 tcpdump 抓取 GetRequestGetResponse

    $ tcpdump -n -s0  port 161 and udp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on wlp58s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    23:39:13.725522 IP 10.10.1.159.36826 > 10.10.1.20.161:  GetRequest(28)  .1.3.6.1.2.1.1.1.0
    23:39:13.728789 IP 10.10.1.20.161 > 10.10.1.159.36826:  GetResponse(109)  .1.3.6.1.2.1.1.1.0="Linux testmachine 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    切割 pcap 文件

    当抓取大量数据并写入文件时,可以自动切割为多个大小相同的文件。例如,下面的命令表示每 3600 秒创建一个新文件 capture-(hour).pcap,每个文件大小不超过 200*1000000 字节:

    $ tcpdump  -w /tmp/capture-%H.pcap -G 3600 -C 200
    
    • 1

    这些文件的命名为 capture-{1-24}.pcap,24 小时之后,之前的文件就会被覆盖。

    抓取 IPv6 流量

    可以通过过滤器 ip6 来抓取 IPv6 流量,同时可以指定协议如 TCP:

    $ tcpdump -nn ip6 proto 6
    
    • 1

    从之前保存的文件中读取 IPv6 UDP 数据报文:

    $ tcpdump -nr ipv6-test.pcap ip6 proto 17
    
    • 1

    检测端口扫描

    在下面的例子中,你会发现抓取到的报文的源和目的一直不变,且带有标志位 [S][R],它们与一系列看似随机的目标端口进行匹配。当发送 SYN 之后,如果目标主机的端口没有打开,就会返回一个 RESET。这是 Nmap 等端口扫描工具的标准做法。

    $ tcpdump -nn
    
    21:46:19.693601 IP 10.10.1.10.60460 > 10.10.1.199.5432: Flags [S], seq 116466344, win 29200, options [mss 1460,sackOK,TS val 3547090332 ecr 0,nop,wscale 7], length 0
    21:46:19.693626 IP 10.10.1.10.35470 > 10.10.1.199.513: Flags [S], seq 3400074709, win 29200, options [mss 1460,sackOK,TS val 3547090332 ecr 0,nop,wscale 7], length 0
    21:46:19.693762 IP 10.10.1.10.44244 > 10.10.1.199.389: Flags [S], seq 2214070267, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0
    21:46:19.693772 IP 10.10.1.199.389 > 10.10.1.10.44244: Flags [R.], seq 0, ack 2214070268, win 0, length 0
    21:46:19.693783 IP 10.10.1.10.35172 > 10.10.1.199.1433: Flags [S], seq 2358257571, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0
    21:46:19.693826 IP 10.10.1.10.33022 > 10.10.1.199.49153: Flags [S], seq 2406028551, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0
    21:46:19.695567 IP 10.10.1.10.55130 > 10.10.1.199.49154: Flags [S], seq 3230403372, win 29200, options [mss 1460,sackOK,TS val 3547090334 ecr 0,nop,wscale 7], length 0
    21:46:19.695590 IP 10.10.1.199.49154 > 10.10.1.10.55130: Flags [R.], seq 0, ack 3230403373, win 0, length 0
    21:46:19.695608 IP 10.10.1.10.33460 > 10.10.1.199.49152: Flags [S], seq 3289070068, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0
    21:46:19.695622 IP 10.10.1.199.49152 > 10.10.1.10.33460: Flags [R.], seq 0, ack 3289070069, win 0, length 0
    21:46:19.695637 IP 10.10.1.10.34940 > 10.10.1.199.1029: Flags [S], seq 140319147, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0
    21:46:19.695650 IP 10.10.1.199.1029 > 10.10.1.10.34940: Flags [R.], seq 0, ack 140319148, win 0, length 0
    21:46:19.695664 IP 10.10.1.10.45648 > 10.10.1.199.5060: Flags [S], seq 2203629201, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0
    21:46:19.695775 IP 10.10.1.10.49028 > 10.10.1.199.2000: Flags [S], seq 635990431, win 29200, options [mss 1460,sackOK,TS val 3547090335 ecr 0,nop,wscale 7], length 0
    21:46:19.695790 IP 10.10.1.199.2000 > 10.10.1.10.49028: Flags [R.], seq 0, ack 635990432, win 0, length 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    过滤 Nmap NSE 脚本测试结果

    本例中 Nmap NSE 测试脚本 http-enum.nse 用来检测 HTTP 服务的合法 URL。

    在执行脚本测试的主机上:

    $ nmap -p 80 --script=http-enum.nse targetip
    
    • 1

    在目标主机上:

    $ tcpdump -nn port 80 | grep "GET /"
    
    GET /w3perl/ HTTP/1.1
    GET /w-agora/ HTTP/1.1
    GET /way-board/ HTTP/1.1
    GET /web800fo/ HTTP/1.1
    GET /webaccess/ HTTP/1.1
    GET /webadmin/ HTTP/1.1
    GET /webAdmin/ HTTP/1.1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    抓取 DNS 请求和响应

    向 Google 公共 DNS 发起的出站 DNS 请求和 A 记录响应可以通过 tcpdump 抓取到:

    $ tcpdump -i wlp58s0 -s0 port 53
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on wlp58s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    14:19:06.879799 IP test.53852 > google-public-dns-a.google.com.domain: 26977+ [1au] A? play.google.com. (44)
    14:19:07.022618 IP google-public-dns-a.google.com.domain > test.53852: 26977 1/0/1 A 216.58.203.110 (60)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    抓取 HTTP 有效数据包

    抓取 80 端口的 HTTP 有效数据包,排除 TCP 连接建立过程的数据包(SYN / FIN / ACK):

    $ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
    
    • 1

    将输出内容重定向到 Wireshark

    通常 Wireshark(或 tshark)比 tcpdump 更容易分析应用层协议。一般的做法是在远程服务器上先使用 tcpdump 抓取数据并写入文件,然后再将文件拷贝到本地工作站上用 Wireshark 分析。

    还有一种更高效的方法,可以通过 ssh 连接将抓取到的数据实时发送给 Wireshark 进行分析。以 MacOS 系统为例,可以通过 brew cask install wireshark 来安装,然后通过下面的命令来分析:

    $ ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - not port 22' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -
    
    • 1

    例如,如果想分析 DNS 协议,可以使用下面的命令:

    $ ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - port 53' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -
    
    • 1

    抓取到的数据:

    img

    -c 选项用来限制抓取数据的大小。如果不限制大小,就只能通过 ctrl-c 来停止抓取,这样一来不仅关闭了 tcpdump,也关闭了 wireshark。

    找出发包最多的 IP

    找出一段时间内发包最多的 IP,或者从一堆报文中找出发包最多的 IP,可以使用下面的命令:

    $ tcpdump -nnn -t -c 200 | cut -f 1,2,3,4 -d '.' | sort | uniq -c | sort -nr | head -n 20
    
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    200 packets captured
    261 packets received by filter
    0 packets dropped by kernel
        108 IP 10.10.211.181
         91 IP 10.10.1.30
          1 IP 10.10.1.50
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • cut -f 1,2,3,4 -d ‘.’ : 以 . 为分隔符,打印出每行的前四列。即 IP 地址。
    • sort | uniq -c : 排序并计数
    • sort -nr : 按照数值大小逆向排序

    抓取用户名和密码

    本例将重点放在标准纯文本协议上,过滤出于用户名和密码相关的报文:

    $ tcpdump port http or port ftp or port smtp or port imap or port pop3 or port telnet -l -A | egrep -i -B5 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|passwd=|password=|pass:|user:|username:|password:|login:|pass |user '
    
    • 1

    抓取 DHCP 报文

    最后一个例子,抓取 DHCP 服务的请求和响应报文,67 为 DHCP 端口,68 为客户机端口。

    $ tcpdump -v -n port 67 or 68
    
    tcpdump: listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
    14:37:50.059662 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
        0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:0c:xx:xx:xx:d5, length 300, xid 0xc9779c2a, Flags [none]
    	  Client-Ethernet-Address 00:0c:xx:xx:xx:d5
    	  Vendor-rfc1048 Extensions
    	    Magic Cookie 0x63825363
    	    DHCP-Message Option 53, length 1: Request
    	    Requested-IP Option 50, length 4: 10.10.1.163
    	    Hostname Option 12, length 14: "test-ubuntu"
    	    Parameter-Request Option 55, length 16: 
    	      Subnet-Mask, BR, Time-Zone, Default-Gateway
    	      Domain-Name, Domain-Name-Server, Option 119, Hostname
    	      Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route
    	      NTP, Classless-Static-Route-Microsoft, Static-Route, Option 252
    14:37:50.059667 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
        0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:0c:xx:xx:xx:d5, length 300, xid 0xc9779c2a, Flags [none]
    	  Client-Ethernet-Address 00:0c:xx:xx:xx:d5
    	  Vendor-rfc1048 Extensions
    	    Magic Cookie 0x63825363
    	    DHCP-Message Option 53, length 1: Request
    	    Requested-IP Option 50, length 4: 10.10.1.163
    	    Hostname Option 12, length 14: "test-ubuntu"
    	    Parameter-Request Option 55, length 16: 
    	      Subnet-Mask, BR, Time-Zone, Default-Gateway
    	      Domain-Name, Domain-Name-Server, Option 119, Hostname
    	      Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route
    	      NTP, Classless-Static-Route-Microsoft, Static-Route, Option 252
    14:37:50.060780 IP (tos 0x0, ttl 64, id 53564, offset 0, flags [none], proto UDP (17), length 339)
        10.10.1.1.67 > 10.10.1.163.68: BOOTP/DHCP, Reply, length 311, xid 0xc9779c2a, Flags [none]
    	  Your-IP 10.10.1.163
    	  Server-IP 10.10.1.1
    	  Client-Ethernet-Address 00:0c:xx:xx:xx:d5
    	  Vendor-rfc1048 Extensions
    	    Magic Cookie 0x63825363
    	    DHCP-Message Option 53, length 1: ACK
    	    Server-ID Option 54, length 4: 10.10.1.1
    	    Lease-Time Option 51, length 4: 86400
    	    RN Option 58, length 4: 43200
    	    RB Option 59, length 4: 75600
    	    Subnet-Mask Option 1, length 4: 255.255.255.0
    	    BR Option 28, length 4: 10.10.1.255
    	    Domain-Name-Server Option 6, length 4: 10.10.1.1
    	    Hostname Option 12, length 14: "test-ubuntu"
    	    T252 Option 252, length 1: 10
    	    Default-Gateway Option 3, length 4: 10.10.1.1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    5. 总结

    本文主要介绍了 tcpdump 的基本语法和使用方法,并通过一些示例来展示它强大的过滤功能。将 tcpdump 与 wireshark 进行组合可以发挥更强大的功效,本文也展示了如何优雅顺滑地结合 tcpdump 和 wireshark。如果你想了解更多的细节,可以查看 tcpdump 的 man 手册。

  • 相关阅读:
    ssm冬奥会志愿者报名系统毕业设计源码241154
    在K8S中,静态、动态、自主式Pod有何区别?
    研发效能的逻辑:填补软工鸿沟
    计讯物联智慧合杆在智慧城市中的应用
    数据库基础
    (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
    PageRank实战---西游记人物节点重要度
    threejs全景图片展示
    Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog
    c语言开篇---跟着视频学C语言
  • 原文地址:https://blog.csdn.net/qq_24433609/article/details/126729595