tcpdump 抓包实战

2022年 4月 20日 129点热度 0人点赞

Debian 安装 tcpdump

sudo apt update && sudo apt install tcpdump

引言

排查网络问题之前, 先来了解一下网络拓扑架构以及每个节点的配置, url 超时时间等, 抓包是排除所有其他问题之后的压箱底技能, 应用部署架构都没搞清楚贸然抓包是不可取的.

正文

每次遇到网络问题需要抓包的时候我就比较慌, 为啥呢? 还不是因为对 tcp/ip 以及 tcpdump 工具不熟撒. 若是各位看官有关于网络, 抓包以及 tcpdump 使用的建议, 也恳请不吝赐教.

先来看看 tcpdump 这个命令给我们提供了多少可用的选项:

tcpdump --help

root@mydebian:~# tcpdump --help
tcpdump version 4.99.0
libpcap version 1.10.0 (with TPACKET_V3)
OpenSSL 1.1.1k  25 Mar 2021
Usage: tcpdump [-AbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]
                [ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
                [ -i interface ] [ --immediate-mode ] [ -j tstamptype ]
                [ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ]
                [ -r file ] [ -s snaplen ] [ -T type ] [ --version ]
                [ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]
                [ --time-stamp-precision precision ] [ --micro ] [ --nano ]
                [ -z postrotate-command ] [ -Z user ] [ expression ]
root@mydebian:~#

真尼玛多啊, 一条条学, 一个个实践呗.

file

图片来源: linux 下如何使用 tcpdump 进行抓包详细教程

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

tcpdump 不带任何参数

监听第一块网卡上经过的数据包. 主机上可能有不止一块网卡, 所以经常需要指定网卡.

tcpdump

监听特定网卡

tcpdump -i

-i: 指定要过滤的网卡接口, 如果要查看所有网卡, 可以 -i any

监听特定主机

tcpdump host 192.168.213.161

如果不指定 src 跟 dst, 那么来源或者目标是 hostname 的通信都会被监听.

-Q: 选择是入方向还是出方向的数据包, 可选项有: in, out, inout, 也可以使用 --direction=[direction] 这种写法

特定来源地址的通信

监听特定来源

# hostname 需要指定
tcpdump src host hostname

特定目标地址的通信

# hostname 需要指定
tcpdump dst host hostname

特定端口

# 3000 可以换成你想要指定的端口
tcpdump port 3000

监听 TCP/UDP

服务器上不同服务分别用了 TCP,UDP 作为传输层, 假如只想监听 TCP 的数据包

tcpdump tcp

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

tcpdump -i eth0 udp
tcpdump -i eth0 proto 17

同理, tcpprotocol 6 意思相同.

来源主机+端口+TCP

监听来自主机 123.207.116.169 在端口 22 上的 TCP 数据包:

tcpdump tcp port 22 and src host 123.207.116.169

我擦这里居然有个 and, 属实没有想到

监听特定主机之间的通信

tcpdump ip host 210.27.48.1 and 210.27.48.2

210.27.48.1 除了和 210.27.48.2 之外的主机之间的通信

tcpdump ip host 210.27.48.1 and ! 210.27.48.2

限制抓包的数量

如下, 抓到 1000 个包后, 自动退出

tcpdump -c 1000

c 应该指代的是 count 吧.

显示 ASCII 字符串

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

tcpdump -A -s0 port 80

tcpdump 的常用参数如下:

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

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

  • -p: 不让网络接口进入混杂模式. 默认情况下使用 tcpdump 抓包时, 会让网络接口进入混杂模式. 一般计算机网卡都工作在非混杂模式下, 此时网卡只接受来自网络端口的目的地址指向自己的数据. 当网卡工作在混杂模式下时, 网卡将来自接口的所有数据都捕获并交给相应的驱动程序. 如果设备接入的交换机开启了混杂模式, 使用 -p 选项可以有效地过滤噪声.
  • -e: 显示数据链路层信息. 默认情况下 tcpdump 不会显示数据链路层信息, 使用 -e 选项可以显示源和目的 MAC 地址, 以及 VLAN tag 信息.

行缓冲模式

如果想实时将抓取到的数据通过管道传递给其他工具来处理, 需要使用 -l 选项来开启行缓冲模式 (或使用 -c 选项来开启数

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

组合过滤器

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

and or &&
or or ||
not or !

综合例子

稍微详细点的例子

tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
  • tcp: ip icmp arp rarp 和 tcp,udp,icmp 这些选项等都要放到第一个参数的位置, 用来过滤数据报的类型
  • -i eth1: 只抓经过接口 eth1 的包
  • -t: 不显示时间戳
  • -s 0: 抓取数据包时默认抓取长度为 68 字节. 加上-S 0 后可以抓到完整的数据包
  • -c 100: 只抓取 100 个数据包
  • dst port ! 22: 不抓取目标端口是 22 的数据包
  • src net 192.168.1.0/24 : 数据包的源网络地址为 192.168.1.0/24
  • -w ./target.cap : 保存成 cap 文件, 方便用 ethereal(即 wireshark) 分析

http 协议抓包

保存到本地

备注:tcpdump 默认会将输出写到缓冲区, 只有缓冲区内容达到一定的大小, 或者 tcpdump 退出时, 才会将输出写到本地磁盘

tcpdump -n -vvv -c 1000 -w /tmp/tcpdump_save.cap

也可以加上-U 强制立即写到本地磁盘 (一般不建议, 性能相对较差)

从文件中读取包数据

使用 -w 是写入数据到文件, 而使用 -r 是从文件中读取数据.

读取后, 我们照样可以使用上述的过滤器语法进行过滤分析.

$ tcpdump icmp -r all.pcap

控制详细内容的输出

  • -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 码形式打印出每个包的数据 (包括连接层的头部), 这在分析一些新协议的数据包很方便.

其他常用的一些参数

  • -A: 以 ASCII 码方式显示每一个数据包 (不显示链路层头部信息). 在抓取包含网页数据的数据包时, 可方便查看数据
  • -l: 基于行的输出, 便于你保存查看, 或者交给其它工具分析
  • -q: 简洁地打印输出. 即打印很少的协议相关信息, 从而输出行都比较简短.
  • -c: 捕获 count 个包 tcpdump 就退出
  • -s: tcpdump 默认只会截取前 96 字节的内容, 要想截取所有的报文内容, 可以使用 -s number, number 就是你要截取的报文字节数, 如果是 0 的话, 表示截取报文全部内容.
  • -S: 使用绝对序列号, 而不是相对序列号
  • -C:file-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 文件作为过滤条件表达式的输入, 此时命令行上的输入将被忽略.

对输出内容进行控制的参数

  • -D: 显示所有可用网络接口的列表
  • -e: 每行的打印输出中将包括数据包的数据链路层头部信息
  • -E: 揭秘 IPSEC 数据
  • -L: 列出指定网络接口所支持的数据链路层的类型后退出
  • -Z: 后接用户名, 在抓包时会受到权限的限制. 如果以 root 用户启动 tcpdump,tcpdump 将会有超级用户权限.
  • -d: 打印出易读的包匹配码
  • -dd: 以 C 语言的形式打印出包匹配码.
  • -ddd: 以十进制数的形式打印出包匹配码

过滤规则组合

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

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

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

$ tcpdump src 10.5.2.3 and dst port 3389

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

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

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

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

当你使用这两个符号时, 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)"

实战例子

先看下面一个比较常见的部署方式, 在服务器上部署了 nodejs server, 监听 3000 端口.nginx 反向代理监听 80 端口, 并将请求转发给 nodejs server(127.0.0.1:3000).

浏览器 -> nginx 反向代理 -> nodejs server

问题: 假设用户 (183.14.132.117) 访问浏览器, 发现请求没有返回, 该怎么排查呢?

步骤一: 查看请求是否到达 nodejs server, 可通过日志查看.

步骤二: 查看 nginx 是否将请求转发给 nodejs server.

tcpdump port 8383

这时你会发现没有任何输出, 即使 nodejs server 已经收到了请求. 因为 nginx 转发到的地址是 127.0.0.1, 用的不是默认的 interface, 此时需要显示指定 interface

tcpdump port 8383 -i lo

备注: 配置 nginx, 让 nginx 带上请求侧的 host, 不然 nodejs server 无法获取 src host, 也就是说, 下面的监听是无效的, 因为此时对于 nodejs server 来说,src host 都是 127.0.0.1

tcpdump port 8383 -i lo and src host 183.14.132.117

步骤三: 查看请求是否达到服务器

tcpdump -n tcp port 8383 -i lo and src host 183.14.132.117

过滤器

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

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

Host 过滤器

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

$ tcpdump host 1.2.3.4

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

$ tcpdump src host 1.2.3.4

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 复制代码
抓取所有发往网段 10.x.x.x 或从网段 10.x.x.x 发出的流量:

$ tcpdump net 10

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

$ tcpdump src net 10

也可以使用 CIDR 格式:

$ tcpdump src net 172.16.0.0/12

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

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

$ tcpdump port 389

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

最基本也是最重要的信息就是数据报的源地址/端口和目的地址/端口, 上面的例子第一条数据报中, 源地址 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 报文的应答报文.

例子

下面给出一些具体的例子, 每个例子都可以使用多种方法来获得相同的输出, 你使用的方法取决于所需的输出和网络上的流量. 我们在排障时, 通常只想获取自己想要的内容, 可以通过过滤器和 ASCII 输出并结合管道与 grep,cut,awk 等工具来实现此目的.
例如, 在抓取 HTTP 请求和响应数据包时, 可以通过删除标志 SYN/ACK/FIN 来过滤噪声, 但还有更简单的方法, 那就是通过管道传递给 grep. 在达到目的的同时, 我们要选择最简单最高效的方法. 下面来看例子.

提取 HTTP 用户代理

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

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

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

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

只抓取 HTTP GET 和 POST 流量

抓取 HTTP GET 流量:

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

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

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

注意: 该方法不能保证抓取到 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

提取 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

提取 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

抓取 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

抓取非 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

抓取 SMTP/POP3 协议的邮件

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

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

抓取 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

抓取 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

可以通过 tcpdump 抓取 GetRequest 和 GetResponse:

$ 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"

切割 pcap 文件

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

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

这些文件的命名为 capture-{1-24}.pcap,24 小时之后, 之前的文件就会被覆盖.
抓取 IPv6 流量
可以通过过滤器 ip6 来抓取 IPv6 流量, 同时可以指定协议如 TCP:

$ tcpdump -nn ip6 proto 6

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

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

检测端口扫描

在下面的例子中, 你会发现抓取到的报文的源和目的一直不变, 且带有标志位 [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

过滤 Nmap NSE 脚本测试结果

本例中 Nmap NSE 测试脚本 http-enum.nse 用来检测 HTTP 服务的合法 URL.
在执行脚本测试的主机上:

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

在目标主机上:

$ 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

抓取 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)

抓取 HTTP 有效数据包

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

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

将输出内容重定向到 Wireshark

通常 Wireshark(或 tshark) 比 tcpdump 更容易分析应用层协议. 一般的做法是在远程服务器上先使用 tcpdump 抓取数据并写入文件, 然后再将文件拷贝到本地工作站上用 Wireshark 分析.
还有一种更高效的方法, 可以通过 ssh 连接将抓取到的数据实时发送给 Wireshark 进行分析. 以 MacOS 系统为例, 可以通过 brew cask install wireshark 来安装, 然后通过下面的命令来分析:

$ 'tcpdump -s0 -c 1000 -nn -w - not port 22' | \
                         /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -

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

$ 'tcpdump -s0 -c 1000 -nn -w - port 53' |      \
                         /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -

抓取到的数据:

-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
  • 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 '

抓取 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

参考

rainbow

这个人很懒,什么都没留下

文章评论