12.5. MATE’s configuration tutorial

We’ll show a MATE configuration that first creates GOPs for every DNS and HTTP request, then it ties the GOPs together in a GOG based on the host. Finally, we’ll separate into different GOGs request coming from different users.

With this MATE configuration loaded we can:

The complete config file is available on the Wireshark Wiki: https://gitlab.com/wireshark/wireshark/-/wikis/Mate/Tutorial

Note: This example uses dns.qry.name which is defined since Wireshark version 0.10.9. Supposing you have a MATE plugin already installed you can test it with the current Wireshark version.

12.5.1. A GOP for DNS requests

First we’ll tell MATE how to create a GOP for each DNS request/response.

MATE needs to know what makes a DNS PDU. We describe it using a Pdu declaration:

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;

Using Proto dns we tell MATE to create PDUs every time it finds dns. Using Transport ip we inform MATE that some of the fields we are interested are in the ip part of the frame. Finally, we tell MATE to import ip.addr as addr, dns.id as dns_id and dns.flags.response as dns_resp.

Once we’ve told MATE how to extract dns_pdus we’ll tell it how to match requests and responses and group them into a GOP. For this we’ll use a Gop declaration to define the GOP, and then, Start and Stop statements to tell it when the GOP starts and ends.

Gop dns_req On dns_pdu Match (addr,addr,dns_id) {
    Start (dns_resp="False");
    Stop (dns_resp="True");

Using the Gop declaration we tell MATE that the Name of the GOP is dns_req, that _dns_pdus_s can become members of the GOP, and what is the key used to match the PDUs to the GOP.

The key for this GOP is "addr, addr, dns_id". That means that in order to belong to the same GOP, dns_pdus have to have both addresses and the request id identical. We then instruct MATE that a dns_req starts whenever a dns_pdu matches "dns_resp="False"" and that it stops when another dns_pdu matches "dns_resp="True"".

At this point, if we open a capture file using this configuration, we are able to use a display filter mate.dns_req.Time > 1 to see only the packets of DNS requests that take more than one second to complete.

We can use a display filter mate.dns_req && ! mate.dns_req.Time to find requests for which no response was given. mate.xxx.Time is set only for GOPs that have being stopped.

12.5.2. A GOP for HTTP requests

This other example creates a GOP for every HTTP request.

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);

So, if we open a capture using this configuration

  • filtering with mate.http_req.Time > 1 will give all the requests where the response header takes more than one second to come
  • filtering with mate.http_req.Duration > 1.5 will show those request that take more than 1.5 seconds to complete.

You have to know that mate.xxx.Time gives the time in seconds between the PDU matching the GOP Start clause and the PDU matching the GOP Stop clause (yes, you can create timers using this!). On the other hand, mate.xxx.Duration gives you the time passed between the GOP Start and the last PDU assigned to that GOP regardless whether it is a Stop or not. After the GOP Stop, PDUs matching the GOP’s Key will still be assigned to the same GOP as far as they don’t match the GOP Start, in which case a new GOP with the same key will be created.

12.5.3. Getting DNS and HTTP together into a GOG

We’ll tie together to a single GOG all the HTTP packets belonging to requests and responses to a certain host and the DNS request and response used to resolve its domain name using the Pdu and Gop definitions of the previous examples

To be able to group DNS and HTTP requests together, we need to import into the PDUs and GOPs some part of information that both those protocols share. Once the PDUs and GOPs have been defined, we can use Extract (for PDUs) and Extract (for GOPs) statements to tell MATE what other protocol fields are to be added to PDU’s and GOP’s AVPLs. We add the following statements to the appropriate declarations:

    Extract host From http.host; // to Pdu http_pdu as the last Extract in the list
    Extra (host); // to Gop http_req after the Stop

    Extract host From dns.qry.name; // to Pdu dns_pdu as the last Extract in the list
    Extra (host); // to Gop dns_req after the Stop

Here we’ve told MATE to import http.host into http_pdu and dns.qry.name into dns_pdu as host. We also have to tell MATE to copy the host attribute from the PDUs to the GOPs - we do this using Extra.

Once we have all the data we need in PDUs and GOPs, we tell MATE what makes different GOPs belong to a certain GOG.

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

Using the Gog declaration, we tell MATE to define a GOG type named http_use whose expiration is 0.75 seconds after all the GOPs that belong to it had been stopped. After that time, an eventual new GOP with the same key match will create a new GOG instead of been added to the previous GOG.

Using the Member statements, we tell MATE that http_req*s with the same *host belong to the same GOG, same thing for *dns_req*s.

So far we have instructed MATE to group every packet related to sessions towards a certain host. At this point if we open a capture file and:

  • a display filter mate.http_use.Duration > 5 will show only those requests that have taken more than 5 seconds to complete starting from the DNS request and ending with the last packet of the HTTP responses.
  • a display filter mate.http_use.host == "www.w3c.org" will show all the packets (both DNS and HTTP) related to the requests directed to www.w3c.org

12.5.4. Separating requests from multiple users

"Houston: we’ve had a problem here."

This configuration works fine if used for captures taken at the client’s side but deeper in the network we’d got a real mess. Requests from many users get mixed together into http_uses. GOGs are created and stopped almost randomly (depending on the timing in which GOPs start and stop). How do we get requests from individual users separated from each other?

MATE has a tool that can be used to resolve this kind of grouping issues. This tool are the Transforms. Once defined, they can be applied against PDUs, GOPs and GOGs and they might replace or insert more attributes based on what’s there. We’ll use them to create an attribute named client, using which we’ll separate different requests.

For DNS we need the ip.src of the request moved into the GOP only from the DNS request.

So we first tell MATE to import ip.src as client:

    Extract client From ip.src;

Next, we tell MATE to replace ( dns_resp="True", client ) with just dns_resp="True" in the PDU. That way, we’ll keep the attribute client only in the DNS request PDUs (i.e., packets coming from the client).To do so, we have to add a Transform declaration (in this case, with just one clause) before the Pdu declaration which uses it:

Transform rm_client_from_dns_resp {
    Match (dns_resp="True", client) Replace (dns_resp="True");

Next, we invoke the transform by adding the following line after the Extract list of the dns_pdu PDU:

    Transform rm_client_from_dns_resp;

HTTP is a little trickier. We have to remove the attribute carrying ip.src from both the response and the "continuations" of the response, but as there is nothing to filter on for the continuations, we have to add a fake attribute first. And then we have to remove client when the fake attribute appears. This is possible due to the fact that the Match clauses in the Transform are executed one by one until one of them succeeds. First, we declare another two 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)

Next, we add another Extract statement to the http_pdu declaration, and apply both Transforms declared above in a proper order:

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

In MATE, all the Transform_s listed for an item will be evaluated, while inside a single _Transform, the evaluation will stop at the first successful Match clause. That’s why we first just match http_rq to get out of the first sequence before adding the not_rq attribute. Then we apply the second Transform which removes both not_rq and client if both are there. Yes, _Transform_s are cumbersome, but they are very useful.

Once we got all what we need in the PDUs, we have to tell MATE to copy the attribute client from the PDUs to the respective GOPs, by adding client to Extra lists of both Gop declarations:

    Extra (host, client);

On top of that, we need to modify the old declarations of GOP key to new ones that include both client and host. So we change the Gog Member declarations the following way:

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

Now we got it, every "usage" gets its own GOG.