Updates to the DPD framework.

- Removed the ProtocolViolation notice.  I'd like to hear
  if someone actually used that notice for something.
- Folded the dyn-disable functionality into the dpd/base script.
- Other small cleanup.
This commit is contained in:
Seth Hall 2011-06-30 21:26:30 -04:00
parent e3f6909b93
commit b4b990cfb5
5 changed files with 55 additions and 57 deletions

View file

@ -1,3 +1,2 @@
@load dpd/base @load dpd/base
@load dpd/dyn-disable
@load dpd/packet-segment-logging @load dpd/packet-segment-logging

View file

@ -1,4 +1,5 @@
##! Activates port-independent protocol detection. ##! Activates port-independent protocol detection and selectively disables
##! analyzers if protocol violations occur.
@load functions @load functions
@load signatures @load signatures
@ -6,19 +7,34 @@
module DPD; module DPD;
## Add the DPD signatures to the signature framework. ## Add the DPD signatures to the signature framework.
redef signature_files += "dpd/dpd.sig"; redef signature_files += "frameworks/dpd/dpd.sig";
export { export {
redef enum Log::ID += { DPD }; redef enum Log::ID += { DPD };
type Info: record { type Info: record {
## Timestamp for when protocol analysis failed.
ts: time &log; ts: time &log;
## Connection unique ID.
uid: string &log; uid: string &log;
## Connection ID.
id: conn_id &log; id: conn_id &log;
## Transport protocol for the violation.
proto: transport_proto &log; proto: transport_proto &log;
## The analyzer that generated the violation.
analyzer: string &log; analyzer: string &log;
## The textual reason for the analysis failure.
failure_reason: string &log; failure_reason: string &log;
## Disabled analyzer IDs. This is only for internal tracking
## so as to not attempt to disable analyzers multiple times.
# TODO: This is waiting on ticket #460 to remove the '0'.
disabled_aids: set[count] &default=set(0);
}; };
## Ignore violations which go this many bytes into the connection.
## Set to 0 to never ignore protocol violations.
const ignore_violations_after = 10 * 1024 &redef;
} }
redef record connection += { redef record connection += {
@ -29,6 +45,7 @@ event bro_init()
{ {
Log::create_stream(DPD, [$columns=Info]); Log::create_stream(DPD, [$columns=Info]);
# Populate the internal DPD analysis variable.
for ( a in dpd_config ) for ( a in dpd_config )
{ {
for ( p in dpd_config[a]$ports ) for ( p in dpd_config[a]$ports )
@ -42,31 +59,53 @@ event bro_init()
event protocol_confirmation(c: connection, atype: count, aid: count) &priority=10 event protocol_confirmation(c: connection, atype: count, aid: count) &priority=10
{ {
if ( fmt("-%s",analyzer_name(atype)) in c$service ) local analyzer = analyzer_name(atype);
delete c$service[fmt("-%s", analyzer_name(atype))];
if ( fmt("-%s",analyzer) in c$service )
delete c$service[fmt("-%s", analyzer)];
add c$service[analyzer_name(atype)]; add c$service[analyzer];
} }
event protocol_violation(c: connection, atype: count, aid: count, event protocol_violation(c: connection, atype: count, aid: count,
reason: string) &priority=5 reason: string) &priority=10
{ {
if ( analyzer_name(atype) in c$service ) local analyzer = analyzer_name(atype);
delete c$service[analyzer_name(atype)]; # If the service hasn't been confirmed yet, don't generate a log message
add c$service[fmt("-%s", analyzer_name(atype))]; # for the protocol violation.
if ( analyzer !in c$service )
return;
delete c$service[analyzer];
add c$service[fmt("-%s", analyzer)];
local info: Info; local info: Info;
info$ts=network_time(); info$ts=network_time();
info$uid=c$uid; info$uid=c$uid;
info$id=c$id; info$id=c$id;
info$proto=get_conn_transport_proto(c$id); info$proto=get_conn_transport_proto(c$id);
info$analyzer=analyzer_name(atype); info$analyzer=analyzer;
info$failure_reason=reason; info$failure_reason=reason;
c$dpd = info; c$dpd = info;
} }
event protocol_violation(c: connection, atype: count, aid: count, reason: string) &priority=5
{
if ( !c?$dpd || aid in c$dpd$disabled_aids )
return;
local size = c$orig$size + c$resp$size;
if ( ignore_violations_after > 0 && size > ignore_violations_after )
return;
# Disable the analyzer that raised the last core-generated event.
disable_analyzer(c$id, aid);
add c$dpd$disabled_aids[aid];
}
event protocol_violation(c: connection, atype: count, aid: count, event protocol_violation(c: connection, atype: count, aid: count,
reason: string) &priority=-5 reason: string) &priority=-5
{ {
Log::write(DPD, c$dpd); if ( c?$dpd )
} Log::write(DPD, c$dpd);
}

View file

@ -1,42 +0,0 @@
##! When this script is loaded, analyzers that raise protocol_violation events
##! are disabled for the affected connection.
@load dpd/base
@load notice
module DPD;
export {
redef enum Notice::Type += {
ProtocolViolation
};
redef record DPD::Info += {
## Disabled analyzer IDs.
# TODO: This is waiting on ticket #460 to remove the '0'.
disabled_aids: set[count] &default=set(0);
};
## Ignore violations which go this many bytes into the connection.
const max_data_volume = 10 * 1024 &redef;
}
event protocol_violation(c: connection, atype: count, aid: count,
reason: string) &priority=5
{
if ( aid in c$dpd$disabled_aids )
return;
local size = c$orig$size + c$resp$size;
if ( max_data_volume > 0 && size > max_data_volume )
return;
# Disable the analyzer that raised the last core-generated event.
disable_analyzer(c$id, aid);
add c$dpd$disabled_aids[aid];
NOTICE([$note=ProtocolViolation, $conn=c,
$msg=fmt("%s disabled due to protocol violation", analyzer_name(atype)),
$sub=reason, $n=atype]);
}

View file

@ -10,6 +10,8 @@ module DPD;
export { export {
redef record Info += { redef record Info += {
## A chunk of the payload the most likely resulted in the protocol
## violation.
packet_segment: string &optional &log; packet_segment: string &optional &log;
}; };
@ -21,5 +23,7 @@ export {
event protocol_violation(c: connection, atype: count, aid: count, event protocol_violation(c: connection, atype: count, aid: count,
reason: string) &priority=4 reason: string) &priority=4
{ {
if ( ! c?$dpd ) return;
c$dpd$packet_segment=fmt("%s", sub_bytes(get_current_packet()$data, 0, packet_segment_size)); c$dpd$packet_segment=fmt("%s", sub_bytes(get_current_packet()$data, 0, packet_segment_size));
} }

View file

@ -5,7 +5,6 @@
# Load the policy scripts where the notices are defined. # Load the policy scripts where the notices are defined.
@load frameworks/notice/weird @load frameworks/notice/weird
@load dpd
# Remove these notices from logging since they can be too noisy. # Remove these notices from logging since they can be too noisy.
redef Notice::ignored_types += { redef Notice::ignored_types += {
@ -13,5 +12,4 @@ redef Notice::ignored_types += {
Weird::AckAboveHole, Weird::AckAboveHole,
Weird::RetransmissionInconsistency, Weird::RetransmissionInconsistency,
Weird::WeirdActivity, # Only allow these to go in the weird log. Weird::WeirdActivity, # Only allow these to go in the weird log.
DPD::ProtocolViolation,
}; };