zeek/scripts/policy/files/x509/disable-certificate-events-known-certs.zeek
Johanna Amann e58b03a43f Add policy script suppressing certificate events
The added disable-certificate-events-known-certs.zeek disables repeated
X509 events in SSL connections, given that the connection terminates at
the same server and used the samt SNI as a previously seen connection
with the same certificate.

For people that see significant amounts of TLS 1.2 traffic, this could
reduce the amount of raised events significantly - especially when a
lot of connections are repeat connections to the same servers.

The practical impact of not raising these events is actually very little
- unless a script directly interacts with the x509 events, everything
works as before - the x509 variables in the connection records are still
being set (from the cache).
2021-06-29 11:39:18 +01:00

84 lines
3 KiB
Text

##! This script disables repeat certificate events for hosts for hosts for which the same
##! certificate was seen in the recent past;
##!
##! This script specifically plugs into the event caching mechanism that is set up by the
##! base X509 script certificate-event-cache.zeek. It adds another layer of tracking that
##! checks if the same certificate was seen for the server IP address before, when the same
##! SNI was used to connect. If the certificate is in the event cache and all of these conditions
##! apply, then no certificate related events will be raised.
##!
##! Please note that while this optimization can lead to a considerable reduction of load in some
##! settings, it also means that certain detection scripts that rely on the certificate events being
##! raised do no longer work - since the events will not be raised for all connections.
##!
##! Currently this script only works for X509 certificates that are sent via SSL/TLS connections.
##!
##! If you use any script that requires certificate events for each single connection,
##! you should not load this script.
@load base/protocols/ssl
@load base/files/x509
module DisableX509Events;
## Let's be a bit more generous with the number of certificates that we allow to be put into
## the cache.
redef X509::certificate_cache_max_entries = 100000;
type CacheIndex: record {
## IP address of the server the certificate was seen on.
ip: addr;
## SNI the client sent in the connection
sni: string &optional;
## sha256 of the certificate
sha256: string;
};
redef record SSL::Info += {
## Set to true to force certificate events to always be raised for this connection.
always_raise_x509_events: bool &default=F;
};
redef record X509::Info += {
## Set to true to force certificate events to always be raised for this certificate.
always_raise_x509_events: bool &default=F;
};
global certificate_replay_tracking: set[CacheIndex] &read_expire=X509::certificate_cache_minimum_eviction_interval;
hook X509::x509_certificate_cache_replay(f: fa_file, e: X509::Info, sha256: string) &priority=5
{
# Bail out if x509 is already set - or if the file tells us that we should always raise events.
if ( f$info?$x509 || e$always_raise_x509_events )
return;
local raise_events = F;
# not sure how that could happen - but let's be safe...
if ( |f$conns| == 0 )
return;
for ( c in f$conns )
{
if ( ! f$conns[c]?$ssl )
return;
local test = CacheIndex($ip=f$conns[c]$id$resp_h, $sha256=sha256);
if ( f$conns[c]$ssl?$server_name )
test$sni = f$conns[c]$ssl$server_name;
if ( test !in certificate_replay_tracking || f$conns[c]$ssl$always_raise_x509_events )
{
raise_events = T;
add certificate_replay_tracking[test];
}
}
if ( ! raise_events )
{
# We don't have to raise the events. :).
# Instead we just already set f$x509. That makes the data available to scripts that might need them - and the x509_certificate_cache_replayh
# hook in certificate-event-cache will just abort.
f$info$x509 = e;
}
}