Tip of the Week: AI Triggers and Flow.setApplication()

triggers

#1

L4 metrics are handled a little differently, specifically because they use the Flow.setApplication() method to put them in an application bucket instead of the commit() method. You might remember the table below from the last week’s TotW, but we’ve now added a row for L4 with corresponding FLOW_CLASSIFY and TCP_OPEN events. The table represents all of the built-in metrics that can be added to an application as of the time of this writing.

  Application Component
Event
AAA AAA_REQUEST and AAA_RESPONSE
DB DB_RESPONSE
DNS DNS_REQUEST and DNS_RESPONSE
HTTP HTTP_RESPONSE
IBMMQ IBMMQ_REQUEST and IBMMQ_RESPONSE
ICA ICA_TICK and ICA_CLOSE
L4 TCP_OPEN or FLOW_CLASSIFY
LDAP LDAP_REQUEST and LDAP_RESPONSE
Memcache MEMCACHE_REQUEST and MEMCACHE_RESPONSE
NAS CIFS_RESPONSE or NFS_RESPONSE
SSL SSL_RECORD and SSL_CLOSE
FIX FIX_REQUEST and FIX_RESPONSE
FTP FTP_RESPONSE
SMTP SMTP_REQUEST and SMTP_RESPONSE

So how do we actually use Flow.setApplication()? There are three main points to remember with Flow.setApplication()

  • For TCP_OPEN and FLOW_CLASSIFY events, the setApplication() method is only valid way to make an application. The TCP_OPEN event fires on the ACK of the TCP threeway handshake and FLOW_CLASSIFY fires when ExtraHop identifies the L7 protocol, or labels the protocol as a unsupported protocol and marks the flow with the L4 protocol (TCP/UDP) and L4 port. Once the setApplication() method is called, all of the built-in L4 metrics for the flow will be added to the application.
  • The setApplication() method can be called during ANY event, not just TCP_OPEN and FLOW_CLASSIFY, in order to start capture L4 metrics for the flow.
  • The Highlander Rule: a flow can be assigned to only ONE application. The assignment goes to the last application the flow was set to. In practice, capturing L4 metrics for applications can take some thought and planning, but trigger logic and selective device grouping usually mitigates this issue.
  • The setApplication() method can take two arguments. The only mandatory argument is the application name, but the second argument enables turn timing (false by default). Turn timing metrics including turn counts, generic server processing time, and request/response transfer time. Turn timing falls under the Uncle Ben Warning (“With great power comes great responsibility”); turn timing can be compute intensive, and if inappropriately applied, can wreak some havok. Please, please please, don’t use “Apply To All”. Additionally, some transactions will not produce turn metrics:
    1. L7 data is unidirectional. We’ve seen this in some printing protocols, where the printer only acknowledges data with TCP ACKs
    2. The transaction flow is 3WH -> Request -> Response -> Close

To illustrate the above points, we’ve put together a little trigger.

// Event: FLOW_CLASSIFY

// When the following is set to true, this trigger will throw errors
// commit() is not valid on FLOW_CLASSIFY or TCP_OPEN
if (false) {
    Application('test1_appcommit').commit();
}

// Filter off port 80 traffic
if (Flow.server.port === 80) { 
    Flow.setApplication('test2_setapp');    // This application will never be created
    Flow.setApplication('test3_stealflow'); // because this call steals the data
}
else {
    // Capture turn timing metrics for traffic on all other ports
    Flow.setApplication('test4_turntiming',true);
}

From the first if statement we can see that we can’t use the commit() method to capture L4 metrics. It results in the following in the Runtime Log:

To evaluate the next test, we can look at the applications that have been created. The “test2_setapp” application is never created because the flow always set to “test3_stealflow” by the next line of the trigger (there can be only one!).

Drilling into the “test3_stealflow” application, we can see the expected L4 metrics.

Finally, we can look at the “test4_turntiming” application. Several new charts are visible, including generic processing time, and turn counting.

This wraps up Flow.setApplication(). Combined with Application.commit(), you should be able to bucketize your applications without turning to complex trigger writing.

As always, questions and comments welcome!