Skip to content
Wireshark Wiki 中文翻译整理专题首页原始页面

MATE 的配置教程

如果你是 MATE 新用户,应先阅读 Getting Started 页面。

我们将展示一个 MATE 配置:它首先为每个 DNS 和 HTTP 请求创建 Gop,然后根据 host 将 Gop 关联到一起,形成一个 Gop。最后,我们会将来自不同用户的请求分离到不同的 Gog 中。

加载此 MATE 配置后,我们可以:

  • 使用 mate.http_use.Duration > 5.5 根据从 DNS 请求解析名称开始,到最后一张图片加载完成为止的完整页面加载耗时来过滤帧。

  • 使用 mate.http_use.client == "10.10.10.20" && mate.http_use.host == "www.example.com" 来隔离与某个用户访问相关的 DNS 和 HTTP 数据包。

  • 使用 mate.http_req.Duration > 1.5 来过滤所有完成时间超过 1.5 秒的 HTTP 请求数据包。

完整配置文件在这里:web.mate

注意:在此示例中,我使用了 dns.qry.name,它自 Wireshark version 0.10.9 起定义。假设你已经安装了 mate plugin,就可以用当前 Wireshark 版本进行测试。

用于 DNS 请求的 Gop

首先,我们会告诉 MATE 如何为每个 DNS 请求/响应创建一个 Gop。

MATE 需要知道什么构成一个 DNS PDU。我们使用 Pdu 声明来描述它:

Pdu dns_pdu Proto dns Transport ip { Extract addr From ip.addr; Extract dns_id From dns.id; Extract dns_resp From dns.flags.response;};

使用 Proto dns,我们告诉 MATE 每次发现 dns 时都创建 Pdu。使用 Transport ip,我们通知 MATE 我们感兴趣的一些字段位于帧的 ip 部分。最后,我们告诉 MATE 将 ip.addr 作为 addr、dns.id 作为 dns_id、dns.flags.response 作为 dns_resp 导入。

一旦告诉 MATE 如何提取 dns_pdus,我们就会告诉它如何匹配请求和响应,并将它们分组到一个 Gop 中。为此,我们将使用 Gop 声明来定义 Gop,然后使用 Start 和 Stop 语句告诉它 Gop 何时开始和结束。

Gop dns_req On dns_pdu Match (addr,addr,dns_id) { Start (dns_resp=0); Stop (dns_resp=1);};

使用 Gop 声明,我们告诉 MATE:该 Gop 的 Name 是 dns_req,dns_pdus 可以成为该 Gop 的成员,以及用于将 Pdu 匹配到 Gop 的 key 是什么。

此 Gop 的 key 是 "addr, addr, dns_id"。这意味着,为了属于同一个 Gop,dns_pdus 必须两个地址和 request id 都相同。然后我们指示 MATE:只要 dns_pdu 匹配 "dns_resp=0",dns_req 就开始;当另一个 dns_pdu 匹配 "dns_resp=1" 时,它就停止。

此时,如果我们使用此配置打开一个捕获文件,就能够使用显示过滤器 mate.dns_req.Time > 1 只查看完成时间超过一秒的 DNS 请求数据包。

我们可以使用显示过滤器 mate.dns_req && ! mate.dns_req.Time 来查找没有收到响应的请求。mate.xxx.Time 只会为已经停止的 Gop 设置。

用于 HTTP 请求的 Gop

另一个示例会为每个 HTTP 请求创建一个 Gop。

Pdu http_pdu Proto http Transport tcp/ip { Extract addr From ip.addr; Extract port From tcp.port; Extract http_rq From http.request.method; Extract http_rs From http.response; DiscardPduData true;};Gop http_req On http_pdu Match (addr, addr, port, port) { Start (http_rq); Stop (http_rs);};

因此,如果我们使用此配置打开一个捕获文件

  • 使用 mate.http_req.Time > 1 过滤会给出响应头耗时超过一秒才到达的所有请求

  • 使用 mate.http_req.Duration > 1.5 过滤会显示完成时间超过 1.5 秒的那些请求。

你必须知道,mate.xxx.Time 给出的是匹配 GopStart 的 pdu 与匹配 GopStop 的 Pdu 之间的秒数(是的,你可以用它创建计时器!)。另一方面,mate.xxx.Duration 给出的是从 GopStart 到分配给该 Gop 的最后一个 pdu 之间经过的时间,不管它是否是 stop。在 GopStop 之后,匹配该 Gop 的 Key 的 Pdu 仍会被分配给同一个 Gop,只要它们不匹配 GopStart;如果匹配 GopStart,则会创建一个具有相同 key 的新 Gop。

将 DNS 和 HTTP 组合到一个 Gog 中

我们将使用前面示例中的 Pdu 和 Gop 定义,把属于针对某个 host 的请求和响应的所有 http 数据包,以及用于解析其域名的 dns 请求和响应,关联到单个 Gog 中。

为了能够将 DNS 和 HTTP 请求分组到一起,我们需要向 Pdu 和 Gop 中导入这两种协议共享的一部分信息。一旦 Pdu 和 Gop 已经定义,我们可以使用 Extract(用于 Pdu)和 Extract(用于 Gop)语句来告诉 MATE 还要把哪些其他协议字段添加到 Pdu 和 Gop 的 AVPL 中。我们将以下语句添加到相应声明中:

Extract host From http.host; // to Pdu http_pdu as the last Extract in the listExtra (host); // to Gop http_req after the StopExtract host From dns.qry.name; // to Pdu dns_pdu as the last Extract in the listExtra (host); // to Gop dns_req after the Stop

这里我们告诉 MATE 将 http.host 导入 http_pdu,并将 dns.qry.name 作为 host 导入 dns_pdu。我们还必须告诉 MATE 将 host 属性从 Pdu 复制到 Gop;我们使用 Extra 来完成此操作。

一旦 Pdu 和 Gop 中有了所需的所有数据,我们就告诉 MATE 是什么使不同的 Gop 属于某个 Gog。

Gog http_use { Member http_req (host); Member dns_req (host); Expiration 0.75;};

使用 Gog 声明,我们告诉 MATE 定义一种 Gog 类型,Named 为 http_use,其过期时间是在属于它的所有 Gop 都停止后的 0.75 秒。在该时间之后,最终出现的具有相同 key match 的新 Gop 将创建一个新的 Gog,而不是被添加到之前的 Gog 中。

使用 Member 语句,我们告诉 MATE:具有相同 host 的 http_reqs 属于同一个 Gog;dns_reqs 也是如此。

到目前为止,我们已经指示 mate 将与到某个 host 的会话相关的每个数据包分组。此时,如果我们打开一个捕获文件并:

  • 显示过滤器 mate.http_use.Duration > 5 将只显示那些从 DNS 请求开始、到 http 响应的最后一个数据包结束,总耗时超过 5 秒的请求。

  • 显示过滤器 mate.http_use.host == "www.w3c.org" 将显示与发往 www.w3c.org 的请求相关的所有数据包(DNS 和 HTTP 两者)。

分离来自多个用户的请求

“Houston: we've had a problem here.”

如果用于在客户端侧获取的捕获,此配置工作良好;但在网络更深处,我们会得到一团乱麻。许多用户的请求会混合到 http_uses 中。Gog 几乎随机地创建和停止(取决于 Gop 开始和停止的时序)。我们如何将各个用户的请求彼此分离?

MATE 有一个可用于解决这类分组问题的工具。这个工具就是 Transforms。一旦定义,它们可以应用于 Pdu、Gop 和 Gog,并且可能会根据已有内容替换或插入更多属性。我们将使用它们创建一个名为 client 的属性,并使用该属性分离不同请求。

对于 DNS,我们需要只从 DNS 请求中把该请求的 ip.src 移入 Gop。

因此,我们首先告诉 MATE 将 ip.src 作为 client 导入:

Extract client From ip.src;

接下来,我们告诉 MATE 在 Pdu 中将 ( dns_resp=1, client ) 替换为仅 dns_resp=1。这样,我们就只会在 DNS 请求 Pdu(即来自客户端的数据包)中保留 client 属性。为此,我们必须在使用它的 Pdu 声明之前添加一个 Transform 声明(在本例中只有一个 clause):

Transform rm_client_from_dns_resp { Match (dns_resp=1, client) Replace (dns_resp=1);};

接下来,我们通过在 dns_pdu Pdu 的 Extract 列表之后添加以下行来调用该 transform:

 Transform rm_client_from_dns_resp;

HTTP 稍微棘手一些。我们必须从响应以及响应的“continuations”中移除携带 ip.src 的属性,但由于 continuations 没有可过滤的内容,我们必须先添加一个伪属性。然后在该伪属性出现时移除 client。之所以可以这样做,是因为 Transform 中的 Match clauses 会逐个执行,直到其中一个成功。首先,我们再声明另外两个 Transforms:

Transform rm_client_from_http_resp1 { Match (http_rq); //first match wins so the request won't get the not_rq attribute inserted Match Every (addr) Insert (not_rq); //this line won't be evaluated if the first one matched so not_rq won't be inserted to requests};Transform rm_client_from_http_resp2 { Match (not_rq, client) Replace (); //replace "client and not_rq" with nothing (will happen only in the response and eventual parts of it)};

接下来,我们向 http_pdu 声明添加另一个 Extract 语句,并按正确顺序应用上面声明的两个 Transforms:

 Extract client From ip.src; Transform rm_client_from_http_resp1, rm_client_from_http_resp2;

在 MATE 中,针对某个 item 列出的所有 Transforms 都会被求值;而在单个 Transform 内部,求值会在第一个成功的 Match clause 处停止。这就是为什么我们首先只匹配 http_rq,以便在添加 not_rq 属性之前跳出第一个序列。然后我们应用第二个 Transform,如果 not_rq 和 client 都存在,它会移除两者。是的,Transforms 很笨重,但它们非常有用。计划是改进它们,有什么想法吗?

一旦我们在 Pdu 中获得了所需的一切,就必须告诉 MATE 将 client 属性从 Pdu 复制到相应的 Gop,方法是把 client 添加到两个 Gop 声明的 Extra 列表中:

Extra (host, client);

除此之外,我们还需要将旧的 Gop key 声明修改为同时包含 client 和 host 的新声明。因此,我们按如下方式修改 Gog Member 声明:

 Member http_req (host, client); Member dns_req (host, client);

现在我们完成了,每个“usage”都会得到自己的 Gog。

Imported from https://wiki.wireshark.org/Mate/Tutorial on 2020-08-11 23:16:37 UTC

相关 Wireshark Wiki 页面

网络分析技术档案