mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 09:08:20 +00:00
Acld implementation for Pacf - Bro side.
Still needs a few small fixes to deal with the fact that acld does not always accept subnets.
This commit is contained in:
parent
f88a1337c0
commit
ee645dfce9
5 changed files with 341 additions and 0 deletions
|
@ -2,3 +2,4 @@
|
|||
@load ./openflow
|
||||
@load ./packetfilter
|
||||
@load ./broker
|
||||
@load ./acld
|
||||
|
|
215
scripts/base/frameworks/pacf/plugins/acld.bro
Normal file
215
scripts/base/frameworks/pacf/plugins/acld.bro
Normal file
|
@ -0,0 +1,215 @@
|
|||
# Acld plugin for the pacf framework.
|
||||
|
||||
module Pacf;
|
||||
|
||||
@load ../plugin
|
||||
@load base/frameworks/broker
|
||||
|
||||
export {
|
||||
type AclRule : record {
|
||||
command: string;
|
||||
cookie: count;
|
||||
arg: string;
|
||||
comment: string &optional;
|
||||
};
|
||||
|
||||
type AcldConfig: record {
|
||||
## The acld topic used to send events to
|
||||
acld_topic: string;
|
||||
## Broker host to connect to
|
||||
acld_host: addr;
|
||||
## Broker port to connect to
|
||||
acld_port: port;
|
||||
## Function that can decide weather to accept add request
|
||||
add_pred: function(p: PluginState, r: Rule, ar: AclRule): bool &optional &weaken;
|
||||
};
|
||||
|
||||
## Instantiates the acld plugin.
|
||||
global create_acld: function(config: AcldConfig) : PluginState;
|
||||
|
||||
redef record PluginState += {
|
||||
acld_config: AcldConfig &optional;
|
||||
## The ID of this acld instance - for the mapping to PluginStates
|
||||
acld_id: count &optional;
|
||||
};
|
||||
|
||||
global acld_add_rule: event(id: count, r: Rule, ar: AclRule);
|
||||
global acld_remove_rule: event(id: count, r: Rule, ar: AclRule);
|
||||
|
||||
global acld_rule_added: event(id: count, r: Rule, msg: string);
|
||||
global acld_rule_removed: event(id: count, r: Rule, msg: string);
|
||||
global acld_rule_error: event(id: count, r: Rule, msg: string);
|
||||
}
|
||||
|
||||
global pacf_acld_topics: set[string] = set();
|
||||
global pacf_acld_id: table[count] of PluginState = table();
|
||||
global pacf_acld_current_id: count = 0;
|
||||
|
||||
const acld_add_to_remove: table[string] of string = {
|
||||
["drop"] = "restore",
|
||||
["whitelist"] = "remwhitelist",
|
||||
["blockhosthost"] = "restorehosthost",
|
||||
["droptcpport"] = "restoretcpport",
|
||||
["dropudpport"] = "restoreudpport",
|
||||
["droptcpdsthostport"] ="restoretcpdsthostport",
|
||||
["dropudpdsthostport"] ="restoreudpdsthostport",
|
||||
["permittcpdsthostport"] ="unpermittcpdsthostport",
|
||||
["permitudpdsthostport"] ="unpermitudpdsthostport",
|
||||
["nullzero "] ="nonullzero"
|
||||
};
|
||||
|
||||
event Pacf::acld_rule_added(id: count, r: Rule, msg: string)
|
||||
{
|
||||
if ( id !in pacf_acld_id )
|
||||
{
|
||||
Reporter::error(fmt("Pacf acld plugin with id %d not found, aborting", id));
|
||||
return;
|
||||
}
|
||||
|
||||
local p = pacf_acld_id[id];
|
||||
|
||||
event Pacf::rule_added(r, p, msg);
|
||||
}
|
||||
|
||||
event Pacf::acld_rule_removed(id: count, r: Rule, msg: string)
|
||||
{
|
||||
if ( id !in pacf_acld_id )
|
||||
{
|
||||
Reporter::error(fmt("Pacf acld plugin with id %d not found, aborting", id));
|
||||
return;
|
||||
}
|
||||
|
||||
local p = pacf_acld_id[id];
|
||||
|
||||
event Pacf::rule_removed(r, p, msg);
|
||||
}
|
||||
|
||||
event Pacf::acld_rule_error(id: count, r: Rule, msg: string)
|
||||
{
|
||||
if ( id !in pacf_acld_id )
|
||||
{
|
||||
Reporter::error(fmt("Pacf acld plugin with id %d not found, aborting", id));
|
||||
return;
|
||||
}
|
||||
|
||||
local p = pacf_acld_id[id];
|
||||
|
||||
event Pacf::rule_error(r, p, msg);
|
||||
}
|
||||
|
||||
function acld_name(p: PluginState) : string
|
||||
{
|
||||
return fmt("PACF acld plugin - using broker topic %s", p$acld_config$acld_topic);
|
||||
}
|
||||
|
||||
function rule_to_acl_rule(r: Rule) : AclRule
|
||||
{
|
||||
local e = r$entity;
|
||||
|
||||
local command: string = "";
|
||||
local arg: string = "";
|
||||
|
||||
if ( e$ty == ADDRESS )
|
||||
{
|
||||
if ( r$ty == DROP )
|
||||
command = "drop";
|
||||
else if ( r$ty == WHITELIST )
|
||||
command = "whitelist";
|
||||
arg = cat(e$ip);
|
||||
}
|
||||
else if ( e$ty == FLOW )
|
||||
{
|
||||
local f = e$flow;
|
||||
if ( ( ! f?$src_h ) && ( ! f?$src_p ) && f?$dst_h && f?$dst_p && ( ! f?$src_m ) && ( ! f?$dst_m ) )
|
||||
{
|
||||
# fixme - check if address is not a subnet
|
||||
if ( is_tcp_port(f$dst_p) && r$ty == DROP )
|
||||
command = "droptcpdsthostport";
|
||||
else if ( is_tcp_port(f$dst_p) && r$ty == WHITELIST )
|
||||
command = "permittcpdsthostport";
|
||||
else if ( is_udp_port(f$dst_p) && r$ty == DROP)
|
||||
command = "dropucpdsthostport";
|
||||
else if ( is_udp_port(f$dst_p) && r$ty == WHITELIST)
|
||||
command = "permitucpdsthostport";
|
||||
|
||||
arg = fmt("%s %d", f$dst_h, f$dst_p);
|
||||
}
|
||||
else if ( f?$src_h && ( ! f?$src_p ) && f?$dst_h && ( ! f?$dst_p ) && ( ! f?$src_m ) && ( ! f?$dst_m ) )
|
||||
{
|
||||
if ( r$ty == DROP )
|
||||
command = "blockhosthost";
|
||||
arg = fmt("%s %s", f$src_h, f$dst_h);
|
||||
}
|
||||
else if ( ( ! f?$src_h ) && ( ! f?$src_p ) && ( ! f?$dst_h ) && f?$dst_p && ( ! f?$src_m ) && ( ! f?$dst_m ) )
|
||||
{
|
||||
if ( is_tcp_port(f$dst_p) && r$ty == DROP )
|
||||
command = "droptcpport";
|
||||
else if ( is_udp_port(f$dst_p) && r$ty == DROP )
|
||||
command = "dropudpport";
|
||||
arg = fmt("%d", f$dst_p);
|
||||
}
|
||||
}
|
||||
|
||||
local ar = AclRule($command=command, $cookie=r$cid, $arg=arg);
|
||||
if ( r?$location )
|
||||
ar$comment = r$location;
|
||||
return ar;
|
||||
}
|
||||
|
||||
function acld_add_rule_fun(p: PluginState, r: Rule) : bool
|
||||
{
|
||||
local ar = rule_to_acl_rule(r);
|
||||
|
||||
if ( p$acld_config?$add_pred )
|
||||
if ( ! p$acld_config$add_pred(p, r, ar) )
|
||||
return F;
|
||||
|
||||
if ( ar$command == "" )
|
||||
return F;
|
||||
|
||||
BrokerComm::event(p$acld_config$acld_topic, BrokerComm::event_args(acld_add_rule, p$acld_id, r, ar));
|
||||
return T;
|
||||
}
|
||||
|
||||
function acld_remove_rule_fun(p: PluginState, r: Rule) : bool
|
||||
{
|
||||
local ar = rule_to_acl_rule(r);
|
||||
if ( ar$command in acld_add_to_remove )
|
||||
ar$command = acld_add_to_remove[ar$command];
|
||||
else
|
||||
return F;
|
||||
|
||||
BrokerComm::event(p$acld_config$acld_topic, BrokerComm::event_args(acld_remove_rule, p$acld_id, r, ar));
|
||||
return T;
|
||||
}
|
||||
|
||||
function acld_init(p: PluginState)
|
||||
{
|
||||
BrokerComm::enable();
|
||||
BrokerComm::connect(cat(p$acld_config$acld_host), p$acld_config$acld_port, 1sec);
|
||||
BrokerComm::subscribe_to_events(p$acld_config$acld_topic);
|
||||
}
|
||||
|
||||
global acld_plugin = Plugin(
|
||||
$name=acld_name,
|
||||
$can_expire = F,
|
||||
$add_rule = acld_add_rule_fun,
|
||||
$remove_rule = acld_remove_rule_fun,
|
||||
$init = acld_init
|
||||
);
|
||||
|
||||
function create_acld(config: AcldConfig) : PluginState
|
||||
{
|
||||
if ( config$acld_topic in pacf_acld_topics )
|
||||
Reporter::warning(fmt("Topic %s was added to Pacf acld plugin twice. Possible duplication of commands", config$acld_topic));
|
||||
else
|
||||
add pacf_acld_topics[config$acld_topic];
|
||||
|
||||
local p: PluginState = [$acld_config=config, $plugin=acld_plugin, $acld_id=pacf_acld_current_id];
|
||||
|
||||
pacf_acld_id[pacf_acld_current_id] = p;
|
||||
++pacf_acld_current_id;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
BrokerComm::incoming_connection_established
|
||||
add_rule, 0, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=10.10.1.4/32, src_p=<uninitialized>, dst_h=74.53.140.153/32, dst_p=<uninitialized>, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_id=1], [command=blockhosthost, cookie=2, arg=10.10.1.4/32 74.53.140.153/32, comment=here]
|
||||
add_rule, 0, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=<uninitialized>, src_p=<uninitialized>, dst_h=<uninitialized>, dst_p=25/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_id=1], [command=droptcpport, cookie=3, arg=25, comment=here]
|
||||
add_rule, 0, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=10.10.1.4/32, mac=<uninitialized>], expire=36000.0, priority=0, location=, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=4, cid=4, _plugin_id=1], [command=drop, cookie=4, arg=10.10.1.4/32, comment=]
|
||||
remove_rule, 0, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=10.10.1.4/32, src_p=<uninitialized>, dst_h=74.53.140.153/32, dst_p=<uninitialized>, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_id=1], [command=restorehosthost, cookie=2, arg=10.10.1.4/32 74.53.140.153/32, comment=here]
|
||||
remove_rule, 0, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=<uninitialized>, src_p=<uninitialized>, dst_h=<uninitialized>, dst_p=25/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_id=1], [command=restoretcpport, cookie=3, arg=25, comment=here]
|
||||
remove_rule, 0, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=10.10.1.4/32, mac=<uninitialized>], expire=36000.0, priority=0, location=, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=4, cid=4, _plugin_id=1], [command=restore, cookie=4, arg=10.10.1.4/32, comment=]
|
|
@ -0,0 +1,7 @@
|
|||
BrokerComm::outgoing_connection_established, 127.0.0.1, 9999/tcp
|
||||
rule added, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=10.10.1.4/32, src_p=<uninitialized>, dst_h=74.53.140.153/32, dst_p=<uninitialized>, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_id=1]
|
||||
rule added, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=<uninitialized>, src_p=<uninitialized>, dst_h=<uninitialized>, dst_p=25/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_id=1]
|
||||
rule added, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=10.10.1.4/32, mac=<uninitialized>], expire=36000.0, priority=0, location=, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=4, cid=4, _plugin_id=1]
|
||||
rule removed, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=10.10.1.4/32, src_p=<uninitialized>, dst_h=74.53.140.153/32, dst_p=<uninitialized>, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_id=1]
|
||||
rule removed, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::FLOW, conn=<uninitialized>, flow=[src_h=<uninitialized>, src_p=<uninitialized>, dst_h=<uninitialized>, dst_p=25/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=36000.0, priority=0, location=here, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_id=1]
|
||||
rule removed, [ty=Pacf::DROP, target=Pacf::FORWARD, entity=[ty=Pacf::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=10.10.1.4/32, mac=<uninitialized>], expire=36000.0, priority=0, location=, c=<uninitialized>, i=<uninitialized>, d=<uninitialized>, s=<uninitialized>, mod=<uninitialized>, id=4, cid=4, _plugin_id=1]
|
111
testing/btest/scripts/base/frameworks/pacf/acld.bro
Normal file
111
testing/btest/scripts/base/frameworks/pacf/acld.bro
Normal file
|
@ -0,0 +1,111 @@
|
|||
# @TEST-SERIALIZE: brokercomm
|
||||
# @TEST-REQUIRES: grep -q ENABLE_BROKER $BUILD/CMakeCache.txt
|
||||
# @TEST-EXEC: btest-bg-run recv "bro -b ../recv.bro broker_port=$BROKER_PORT >recv.out"
|
||||
# @TEST-EXEC: btest-bg-run send "bro -b -r $TRACES/smtp.trace --pseudo-realtime ../send.bro broker_port=$BROKER_PORT >send.out"
|
||||
|
||||
# @TEST-EXEC: btest-bg-wait 20
|
||||
# @TEST-EXEC: btest-diff recv/recv.out
|
||||
# @TEST-EXEC: btest-diff send/send.out
|
||||
|
||||
@TEST-START-FILE send.bro
|
||||
|
||||
@load base/frameworks/pacf
|
||||
|
||||
const broker_port: port &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
suspend_processing();
|
||||
local pacf_acld = Pacf::create_acld(Pacf::AcldConfig($acld_host=127.0.0.1, $acld_port=broker_port, $acld_topic="bro/event/pacftest"));
|
||||
Pacf::activate(pacf_acld, 0);
|
||||
}
|
||||
|
||||
event BrokerComm::outgoing_connection_established(peer_address: string,
|
||||
peer_port: port,
|
||||
peer_name: string)
|
||||
{
|
||||
print "BrokerComm::outgoing_connection_established", peer_address, peer_port;
|
||||
continue_processing();
|
||||
}
|
||||
|
||||
event BrokerComm::outgoing_connection_broken(peer_address: string,
|
||||
peer_port: port)
|
||||
{
|
||||
terminate();
|
||||
}
|
||||
|
||||
event connection_established(c: connection)
|
||||
{
|
||||
local id = c$id;
|
||||
|
||||
local flow1 = Pacf::Flow(
|
||||
$src_h=addr_to_subnet(c$id$orig_h),
|
||||
$dst_h=addr_to_subnet(c$id$resp_h)
|
||||
);
|
||||
local e1: Pacf::Entity = [$ty=Pacf::FLOW, $flow=flow1];
|
||||
local r1: Pacf::Rule = [$ty=Pacf::DROP, $target=Pacf::FORWARD, $entity=e1, $expire=10hrs, $location="here"];
|
||||
|
||||
local flow2 = Pacf::Flow(
|
||||
$dst_p=c$id$resp_p
|
||||
);
|
||||
local e2: Pacf::Entity = [$ty=Pacf::FLOW, $flow=flow2];
|
||||
local r2: Pacf::Rule = [$ty=Pacf::DROP, $target=Pacf::FORWARD, $entity=e2, $expire=10hrs, $location="here"];
|
||||
|
||||
Pacf::add_rule(r1);
|
||||
Pacf::add_rule(r2);
|
||||
Pacf::drop_address(id$orig_h, 10hrs);
|
||||
}
|
||||
|
||||
event Pacf::rule_added(r: Pacf::Rule, p: Pacf::PluginState, msg: string)
|
||||
{
|
||||
print "rule added", r;
|
||||
Pacf::remove_rule(r$id);
|
||||
}
|
||||
|
||||
event Pacf::rule_removed(r: Pacf::Rule, p: Pacf::PluginState, msg: string)
|
||||
{
|
||||
print "rule removed", r;
|
||||
}
|
||||
|
||||
@TEST-END-FILE
|
||||
|
||||
@TEST-START-FILE recv.bro
|
||||
|
||||
@load base/frameworks/pacf
|
||||
@load base/frameworks/broker
|
||||
|
||||
const broker_port: port &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
BrokerComm::enable();
|
||||
BrokerComm::subscribe_to_events("bro/event/pacftest");
|
||||
BrokerComm::listen(broker_port, "127.0.0.1");
|
||||
}
|
||||
|
||||
event BrokerComm::incoming_connection_established(peer_name: string)
|
||||
{
|
||||
print "BrokerComm::incoming_connection_established";
|
||||
}
|
||||
|
||||
event Pacf::acld_add_rule(id: count, r: Pacf::Rule, ar: Pacf::AclRule)
|
||||
{
|
||||
print "add_rule", id, r, ar;
|
||||
|
||||
BrokerComm::event("bro/event/pacftest", BrokerComm::event_args(Pacf::acld_rule_added, id, r, ar$command));
|
||||
}
|
||||
|
||||
event Pacf::acld_remove_rule(id: count, r: Pacf::Rule, ar: Pacf::AclRule)
|
||||
{
|
||||
print "remove_rule", id, r, ar;
|
||||
|
||||
BrokerComm::event("bro/event/pacftest", BrokerComm::event_args(Pacf::acld_rule_removed, id, r, ar$command));
|
||||
|
||||
if ( r$cid == 4 )
|
||||
terminate();
|
||||
}
|
||||
|
||||
@TEST-END-FILE
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue