Critical Devices - EXA Connector Trigger

Hello,

I am a newcomer to the ExtraHop platform and triggers. I have no prior Javascript knowledge, so I am learning on how these triggers work slowly and through more exposure. I wanted to consult the forums to ask for assistance on the format and use of a trigger that was created with ExtraHop Support. The Critical Device EXA Connector Trigger sends records of interest to the EXA for all ENABLED event types for all critical business servers. This is a pretty large trigger that lives on the ECA. The trigger was originally created to showcase all records and transactions that can be processed for all device groups and events of interest.

The Javascript code is as follows.

/Note: Change (@) to @/
/* CONFIG:
(@)Name: EXA Connector (v3)
(@)Description: Sends default records to EXA for all ENABLED event types
(@)Assignments: EXA Connector
(@)Events: All Event Types w/Built-in Records
(@)L7BytesToBuffer: 0
/
const config = cache (‘exaConnectorConfig’, () => (
{
/
======================================================================== >>
The following events represent the default dataset recommended by ExtraHop
to ensure appropriate records are available for investigating Detections.
=========================================================================== */
‘CIFS_RESPONSE’: true,
‘DB_RESPONSE’: {
enabled: true,
verbosity: ‘LOW’, // ‘LOW’ or ‘HIGH’
procThreshold: 0 // Server Processing Time Threshold
},
‘DHCP_REQUEST’: true,
‘DHCP_RESPONSE’: true,
‘DNS_REQUEST’: true,
‘DNS_RESPONSE’: true,
‘FLOW_RECORD’: {
enabled: false,
includeEastWest: false
},
‘FTP_RESPONSE’: true,
‘HTTP_RESPONSE’: true,
‘KERBEROS_REQUEST’: true,
‘KERBEROS_RESPONSE’: true,
‘LDAP_REQUEST’: true,
‘LDAP_RESPONSE’: true,
‘LLMNR_REQUEST’: true,
‘LLMNR_RESPONSE’: true,
‘MONGODB_REQUEST’: true,
‘MONGODB_RESPONSE’: true,
‘NFS_RESPONSE’: true,
‘NTLM_MESSAGE’: true,
‘RDP_OPEN’: true,
‘RDP_CLOSE’: true,
‘RFB_OPEN’: true,
‘RFB_CLOSE’: true,
‘RPC_REQUEST’: true,
‘RPC_RESPONSE’: true,
‘SSH_OPEN’: true,
‘SSH_CLOSE’: true,
‘SSL_OPEN’: true,
‘SSL_CLOSE’: true,
‘TELNET_MESSAGE’: true,

/* ======================================================================== >>
The following events represent opt-in record types. Only enable these record
types when specifically required and/or after evaluating the impact by
reviewing the “EXA Connector” dashboard included with this bundle.
=========================================================================== */
‘AAA_REQUEST’: false,
‘AAA_RESPONSE’: false,
‘ACTIVEMQ_MESSAGE’: false,
‘AJP_RESPONSE’: false,
‘DICOM_REQUEST’: false,
‘DICOM_RESPONSE’: false,
‘FIX_REQUEST’: false,
‘FIX_RESPONSE’: false,
‘HL7_RESPONSE’: false,
‘IBMMQ_REQUEST’: false,
‘IBMMQ_RESPONSE’: false,
‘ICA_OPEN’: false,
‘ICA_TICK’: false,
‘ICA_CLOSE’: false,
‘ICA_AUTH’ : false,
‘ICMP_MESSAGE’: false,
‘MEMCACHE_REQUEST’: false,
‘MEMCACHE_RESPONSE’: false,
‘MODBUS_RESPONSE’: false,
‘MSMQ_MESSAGE’: false,
‘NETFLOW_RECORD’: false,
‘POP3_RESPONSE’: false,
‘RDP_TICK’: false,
‘RFB_TICK’: false,
‘REDIS_REQUEST’: false,
‘REDIS_RESPONSE’: false,
‘RTCP_MESSAGE’: false,
‘RTP_TICK’: false,
‘SCCP_MESSAGE’: false,
‘SFLOW_RECORD’: false,
‘SIP_REQUEST’: false,
‘SIP_RESPONSE’: false,
‘SMPP_RESPONSE’: false,
‘SMTP_RESPONSE’: false,
‘SSH_TICK’: false,
‘SSL_ALERT’: false,
‘SSL_HEARTBEAT’: false,
‘SSL_RENEGOTIATE’: false,

/* ======================================================================== >>
CAUTION: The following flag will enable ALL record types, regardless of the
settings above. USE WITH CAUTION and only after having evaluated the impact
by reviewing the “EXA Connector” dashboard included with this bundle.
=========================================================================== */
‘ALL_EVENTS’: false
}))

let eventClass = null;

// Records DISABLED for this [event], just RETURN
if (! config[‘ALL_EVENTS’] && (config[event] === false || config[event][‘enabled’] === false)) {return recordTelemetry(‘disabled’)}

let commit = false;
switch (event)
{
case ‘CIFS_RESPONSE’:

let cifsError = (CIFS.error !== null)
let cifsTarget = (CIFS.resource || CIFS.share)
let cifsCommand = (CIFS.isCommandRead || CIFS.isCommandWrite || CIFS.isCommandRename || CIFS.isCommandDelete)
let cifsMethods = [
  'TRANSACTION2_SECONDARY'
]

// If no ERROR and no RESOURCE and METHOD is not in the WHITELIST then break
if (! cifsError && (! cifsCommand || ! cifsTarget) && cifsMethods.indexOf(CIFS.method) === -1) {break}

commit = true;
CIFS.commitRecord();
break;

case ‘DB_RESPONSE’:

let dbProcTime = (DB.processingTime || 0);

switch (true)
{
  case (DB.error !== null): commit = true; break;
  case (/login/i.test(DB.method)): commit = true; break;
  case (config['DB_RESPONSE'].verbosity === 'HIGH'):
    if (config['DB_RESPONSE'].procThreshold && dbProcTime < config['DB_RESPONSE'].procThreshold) {break}
    commit = true;
    break;
  case (config['DB_RESPONSE'].verbosity === 'LOW'):
    if (config['DB_RESPONSE'].procThreshold && dbProcTime < config['DB_RESPONSE'].procThreshold) {break}
    if (! DB.statement && ! DB.procedure) {break}
    commit = true;
    break;
}

if (commit === true) {DB.commitRecord()}
break;

// case ‘FLOW_RECORD’:

// // Ignore East/West Flows
// if (! config[‘FLOW_RECORD’].includeEastWest && ! Flow.client.ipaddr.isExternal && ! Flow.server.ipaddr.isExternal) {break}

// commit = true;
// Flow.commitRecord1();
// Flow.commitRecord2();
// break;

case ‘LDAP_REQUEST’:
case ‘LDAP_RESPONSE’:

// METHOD Blacklist
let ldapMethods = [
  'searchresultentry',
  'searchresultdone'
];

// Check the BLACKLIST
if (ldapMethods.indexOf((LDAP.method || '').toLowerCase()) !== -1) {break}

commit = true;
LDAP.commitRecord();
break;

case ‘LLMNR_REQUEST’:
case ‘LLMNR_RESPONSE’:

// Ignore LLMNR traffic where the server/receiver is broadcast
if (Flow.server.ipaddr.mask(24).toString() === '224.0.0.0') {break}

commit = true;
LLMNR.commitRecord();
break;

case ‘NFS_RESPONSE’:

let nfsError = (NFS.error !== null)
let nfsTarget = (NFS.resource !== null)
let nfsCommand = (NFS.isCommandRead || NFS.isCommandWrite)

// If no ERROR and (no COMMAND or no TARGET)
if (! nfsError && (! nfsCommand || ! nfsTarget)) {break}

commit = true;
NFS.commitRecord();
break;

// TODO: Avoid using [getEventClass] on potentially high volume events to save
// trigger cycles if further optimizations are needed…

default:
eventClass = getEventClass();
if (! eventClass) {return}

commit = true;
eventClass.commitRecord();

}

// Records OMITTED for this [event]
if (commit !== true) {return recordTelemetry(‘omitted’)}

// Records SENT for this [event]
recordTelemetry(‘sent’)

// Saves Telemetry METRICS for [DISABLED, OMITTED, SENT] Records
function recordTelemetry (type)
{
// Only record METRICS if DEBUG is enabled
if (! Trigger.isDebugEnabled) {return}

let app = Application(’_default’)
let ipAddr = (Flow.device1.hasTrigger ? Flow.ipaddr1 : Flow.ipaddr2)

switch (type)
{
case ‘disabled’:
app.metricAddCount(‘exaConnect.disabled’, 1, {highPrecision:true})
app.metricAddDetailCount(‘exaConnect.disabled.event’, event, 1, {highPrecision:true})
app.metricAddDetailCount(‘exaConnect.disabled.device’, ipAddr, 1, {highPrecision:true})
return

case 'omitted':
  app.metricAddCount('exaConnect.omitted', 1, {highPrecision:true})
  app.metricAddDetailCount('exaConnect.omitted.event', event, 1, {highPrecision:true})
  app.metricAddDetailCount('exaConnect.omitted.device', ipAddr, 1, {highPrecision:true})
  return

case 'sent':
  app.metricAddCount('exaConnect.sent', 1, {highPrecision:true})
  app.metricAddDetailCount('exaConnect.sent.event', event, 1, {highPrecision:true})
  app.metricAddDetailCount('exaConnect.sent.device', ipAddr, 1, {highPrecision:true})
  return

default: return

}
}

function getEventClass ()
{
switch (event)
{
case ‘AAA_REQUEST’:
case ‘AAA_RESPONSE’: return AAA;

case 'ACTIVEMQ_MESSAGE': return ActiveMQ;

case 'AJP_RESPONSE': return AJP;

case 'CIFS_RESPONSE': return CIFS;

case 'DB_RESPONSE': return DB;

case 'DHCP_REQUEST':
case 'DHCP_RESPONSE': return DHCP;

case 'DICOM_REQUEST':
case 'DICOM_RESPONSE': return DICOM;

case 'DNS_REQUEST':
case 'DNS_RESPONSE': return DNS;

case 'FIX_REQUEST':
case 'FIX_RESPONSE': return FIX;

// case 'FLOW_RECORD': return Flow;

case 'FTP_RESPONSE': return FTP;

case 'HL7_RESPONSE': return HL7;

case 'HTTP_RESPONSE': return HTTP;

case 'IBMMQ_REQUEST':
case 'IBMMQ_RESPONSE': return IBMMQ;

case 'ICA_OPEN':
case 'ICA_TICK':
case 'ICA_CLOSE':
case 'ICA_AUTH': return ICA;

case 'ICMP_MESSAGE': return ICMP;

case 'KERBEROS_REQUEST':
case 'KERBEROS_RESPONSE': return Kerberos;

case 'LDAP_REQUEST':
case 'LDAP_RESPONSE': return LDAP;

case 'LLMNR_REQUEST':
case 'LLMNR_RESPONSE': return LLMNR;

case 'MEMCACHE_REQUEST':
case 'MEMCACHE_RESPONSE': return Memcache;

case 'MODBUS_RESPONSE': return Modbus;

case 'MONGODB_REQUEST':
case 'MONGODB_RESPONSE': return MongoDB;

case 'MSMQ_MESSAGE': return MSMQ;

case 'NETFLOW_RECORD': return NetFlow;

case 'NFS_RESPONSE': return NFS;

case 'NTLM_MESSAGE': return NTLM;

case 'POP3_RESPONSE': return POP3;

case 'RDP_OPEN':
case 'RDP_TICK':
case 'RDP_CLOSE': return RDP;

case 'RFB_OPEN':
case 'RFB_TICK':
case 'RFB_CLOSE': return RFB;

case 'REDIS_REQUEST':
case 'REDIS_RESPONSE': return Redis;

case 'RPC_REQUEST':
case 'RPC_RESPONSE': return RPC;

case 'RTCP_MESSAGE': return RTCP;

case 'RTP_TICK': return RTP;

case 'SCCP_MESSAGE': return SCCP;

case 'SFLOW_RECORD': return SFlow;

case 'SIP_REQUEST':
case 'SIP_RESPONSE': return SIP;

case 'SMPP_RESPONSE': return SMPP;

case 'SMTP_RESPONSE': return SMTP;

case 'SSH_OPEN':
case 'SSH_TICK':
case 'SSH_CLOSE': return SSH;

case 'SSL_OPEN':
case 'SSL_CLOSE':
case 'SSL_ALERT':
case 'SSL_HEARTBEAT':
case 'SSL_RENEGOTIATE': return SSL;

case 'TELNET_MESSAGE': return Telnet;

default: return false

}
}
Other triggers were individually created alongside other bundles in order to minimize the overall trigger load and exceptions occurring on the EXA. E.g. Trigger for VOIP - SIP Servers, Trigger for HTTP Servers/Clients - HTTP Servers/Clients, and so forth.

The Critical Device EXA Connector trigger is applied to a device group that contains 172 devices (more to be added, up to 1000 after initial testing and troubleshooting has been completed) that are primarily file and database servers. Previously, this trigger was assigned to various device groups such as HTTP servers, LDAP servers, DB Servers, DNS Clients, and more. No exceptions were occurring previously; however, now that I have that one static critical server device group assigned to the trigger, I see the following trigger load and exception values below.

How would I reduce or eliminate the number of exceptions that are occurring in relation to this trigger?

What is a trigger exception and how can it be prevented?

This is the only trigger running with trigger exceptions, and I am working to reduce the performance impact on the EXA by reducing these trigger exceptions.

Thank you for your time and assistance.

Last 30 minutes
image

Summary

This text will be hidden

If this Trigger was created with the help of ExtraHop Support, I would reach out to them first.

In the mean time, if you go to the Trigger Editor and view the Debug Log for this particular Trigger, it should tell you what is causing the exceptions.

1 Like