zeek/scripts/base/frameworks/analyzer/dpd.zeek
2025-08-12 10:19:03 -07:00

109 lines
3.3 KiB
Text

##! Disables analyzers if protocol violations occur, and adds service information
##! to connection log.
@load ./main
module DPD;
export {
## Analyzers which you don't want to remove on violations.
option ignore_violations: set[Analyzer::Tag] = set();
## Ignore violations which go this many bytes into the connection.
## Set to 0 to never ignore protocol violations.
option ignore_violations_after = 10 * 1024;
## Change behavior of service field in conn.log:
## Failed services are no longer removed. Instead, for a failed
## service, a second entry with a "-" in front of it is added.
## E.g. a http connection with a violation would be logged as
## "http,-http".
option track_removed_services_in_connection = F;
}
redef record connection += {
## The set of prototol analyzers that were removed due to a protocol
## violation after the same analyzer had previously been confirmed.
failed_analyzers: set[string] &default=set() &ordered;
};
# Add confirmed protocol analyzers to conn.log service field
event analyzer_confirmation_info(atype: AllAnalyzers::Tag, info: AnalyzerConfirmationInfo) &priority=10
{
if ( ! is_protocol_analyzer(atype) && ! is_packet_analyzer(atype) )
return;
if ( ! info?$c )
return;
local c = info$c;
local analyzer = Analyzer::name(atype);
add c$service[analyzer];
}
# Remove failed analyzers from service field and add them to c$failed_analyzers
# Low priority to allow other handlers to check if the analyzer was confirmed
event analyzer_failed(ts: time, atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo) &priority=-5
{
if ( ! is_protocol_analyzer(atype) )
return;
if ( ! info?$c )
return;
local c = info$c;
local analyzer = Analyzer::name(atype);
# If the service hasn't been confirmed yet, or already failed,
# don't generate a log message for the protocol violation.
if ( analyzer !in c$service )
return;
# If removed service tracking is active, don't delete the service here.
if ( ! track_removed_services_in_connection )
delete c$service[analyzer];
# if statement is separate, to allow repeated removal of service, in case there are several
# confirmation and violation events
if ( analyzer !in c$failed_analyzers )
add c$failed_analyzers[analyzer];
# add "-service" to the list of services on removal due to violation, if analyzer was confirmed before
if ( track_removed_services_in_connection && Analyzer::name(atype) in c$service )
{
local rname = cat("-", Analyzer::name(atype));
if ( rname !in c$service )
add c$service[rname];
}
}
event analyzer_violation_info(atype: AllAnalyzers::Tag, info: AnalyzerViolationInfo ) &priority=5
{
if ( ! is_protocol_analyzer(atype) )
return;
if ( ! info?$c || ! info?$aid )
return;
if ( atype in ignore_violations )
return;
local c = info$c;
local aid = info$aid;
local size = c$orig$size + c$resp$size;
if ( ignore_violations_after > 0 && size > ignore_violations_after )
return;
# analyzer already was removed or connection finished
# let's still log this.
if ( lookup_connection_analyzer_id(c$id, atype) == 0 )
{
event analyzer_failed(network_time(), atype, info);
return;
}
local disabled = disable_analyzer(c$id, aid, F);
# If analyzer was disabled, send failed event
if ( disabled )
event analyzer_failed(network_time(), atype, info);
}