mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
NetControl: Add functions to search for rules affecting IPs/subnets
Adds the functions NetControl::find_rules_addr and NetControl::fund_rules_subnet which return a vector containing all rules affecting a certain IP or subnet.
This commit is contained in:
parent
692662abcc
commit
21c300c333
5 changed files with 223 additions and 2 deletions
|
@ -126,6 +126,20 @@ export {
|
||||||
## asynchronously and thus go wrong at that point.
|
## asynchronously and thus go wrong at that point.
|
||||||
global remove_rule: function(id: string) : bool;
|
global remove_rule: function(id: string) : bool;
|
||||||
|
|
||||||
|
## Searches all rules affecting a certain IP address
|
||||||
|
##
|
||||||
|
## ip: The ip address to search for
|
||||||
|
##
|
||||||
|
## Returns: vector of all rules affecting the IP address
|
||||||
|
global find_rules_addr: function(ip: addr) : vector of Rule;
|
||||||
|
|
||||||
|
## Searches all rules affecting a certain subnet
|
||||||
|
##
|
||||||
|
## sn: The subnet to search for
|
||||||
|
##
|
||||||
|
## Returns: vector of all rules affecting the subnet
|
||||||
|
global find_rules_subnet: function(sn: subnet) : vector of Rule;
|
||||||
|
|
||||||
###### Asynchronous feedback on rules.
|
###### Asynchronous feedback on rules.
|
||||||
|
|
||||||
## Confirms that a rule was put in place.
|
## Confirms that a rule was put in place.
|
||||||
|
@ -271,8 +285,7 @@ global plugin_ids: table[count] of PluginState;
|
||||||
global rules: table[string] of Rule; # Rules indexed by id and cid
|
global rules: table[string] of Rule; # Rules indexed by id and cid
|
||||||
|
|
||||||
# All rules that apply to a certain subnet/IP address.
|
# All rules that apply to a certain subnet/IP address.
|
||||||
# Contains only succesfully added rules.
|
global rules_by_subnets: table[subnet] of set[string];
|
||||||
global rules_by_subnets: table[subnet] of set[Rule];
|
|
||||||
|
|
||||||
# Rules pertaining to a specific entity.
|
# Rules pertaining to a specific entity.
|
||||||
# There always only can be one rule of each type for one entity.
|
# There always only can be one rule of each type for one entity.
|
||||||
|
@ -563,6 +576,96 @@ function activate_impl(p: PluginState, priority: int)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function add_one_subnet_entry(s: subnet, r: Rule)
|
||||||
|
{
|
||||||
|
if ( ! check_subnet(s, rules_by_subnets) )
|
||||||
|
rules_by_subnets[s] = set(r$id);
|
||||||
|
else
|
||||||
|
add rules_by_subnets[s][r$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_subnet_entry(rule: Rule)
|
||||||
|
{
|
||||||
|
local e = rule$entity;
|
||||||
|
if ( e$ty == ADDRESS )
|
||||||
|
{
|
||||||
|
add_one_subnet_entry(e$ip, rule);
|
||||||
|
}
|
||||||
|
else if ( e$ty == CONNECTION )
|
||||||
|
{
|
||||||
|
add_one_subnet_entry(addr_to_subnet(e$conn$orig_h), rule);
|
||||||
|
add_one_subnet_entry(addr_to_subnet(e$conn$resp_h), rule);
|
||||||
|
}
|
||||||
|
else if ( e$ty == FLOW )
|
||||||
|
{
|
||||||
|
if ( e$flow?$src_h )
|
||||||
|
add_one_subnet_entry(e$flow$src_h, rule);
|
||||||
|
if ( e$flow?$dst_h )
|
||||||
|
add_one_subnet_entry(e$flow$dst_h, rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_one_subnet_entry(s: subnet, r: Rule)
|
||||||
|
{
|
||||||
|
if ( ! check_subnet(s, rules_by_subnets) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( r$id !in rules_by_subnets[s] )
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete rules_by_subnets[s][r$id];
|
||||||
|
if ( |rules_by_subnets[s]| == 0 )
|
||||||
|
delete rules_by_subnets[s];
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_subnet_entry(rule: Rule)
|
||||||
|
{
|
||||||
|
local e = rule$entity;
|
||||||
|
if ( e$ty == ADDRESS )
|
||||||
|
{
|
||||||
|
remove_one_subnet_entry(e$ip, rule);
|
||||||
|
}
|
||||||
|
else if ( e$ty == CONNECTION )
|
||||||
|
{
|
||||||
|
remove_one_subnet_entry(addr_to_subnet(e$conn$orig_h), rule);
|
||||||
|
remove_one_subnet_entry(addr_to_subnet(e$conn$resp_h), rule);
|
||||||
|
}
|
||||||
|
else if ( e$ty == FLOW )
|
||||||
|
{
|
||||||
|
if ( e$flow?$src_h )
|
||||||
|
remove_one_subnet_entry(e$flow$src_h, rule);
|
||||||
|
if ( e$flow?$dst_h )
|
||||||
|
remove_one_subnet_entry(e$flow$dst_h, rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_rules_subnet(sn: subnet) : vector of Rule
|
||||||
|
{
|
||||||
|
local ret: vector of Rule = vector();
|
||||||
|
|
||||||
|
local matches = matching_subnets(sn, rules_by_subnets);
|
||||||
|
|
||||||
|
for ( m in matches )
|
||||||
|
{
|
||||||
|
local sn_entry = matches[m];
|
||||||
|
local rule_ids = rules_by_subnets[sn_entry];
|
||||||
|
for ( rule_id in rules_by_subnets[sn_entry] )
|
||||||
|
{
|
||||||
|
if ( rule_id in rules )
|
||||||
|
ret[|ret|] = rules[rule_id];
|
||||||
|
else
|
||||||
|
Reporter::error("find_rules_subnet - internal data structure error, missing rule");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_rules_addr(ip: addr) : vector of Rule
|
||||||
|
{
|
||||||
|
return find_rules_subnet(addr_to_subnet(ip));
|
||||||
|
}
|
||||||
|
|
||||||
function add_rule_impl(rule: Rule) : string
|
function add_rule_impl(rule: Rule) : string
|
||||||
{
|
{
|
||||||
if ( ! plugins_active )
|
if ( ! plugins_active )
|
||||||
|
@ -614,6 +717,9 @@ function add_rule_impl(rule: Rule) : string
|
||||||
{
|
{
|
||||||
rules[rule$id] = rule;
|
rules[rule$id] = rule;
|
||||||
rule_entities[rule$entity, rule$ty] = rule;
|
rule_entities[rule$entity, rule$ty] = rule;
|
||||||
|
|
||||||
|
add_subnet_entry(rule);
|
||||||
|
|
||||||
return rule$id;
|
return rule$id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,6 +809,8 @@ function rule_cleanup(r: Rule)
|
||||||
if ( |r$_active_plugin_ids| > 0 )
|
if ( |r$_active_plugin_ids| > 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
remove_subnet_entry(r);
|
||||||
|
|
||||||
delete rule_entities[r$entity, r$ty];
|
delete rule_entities[r$entity, r$ty];
|
||||||
delete rules[r$id];
|
delete rules[r$id];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
netcontrol debug (Debug-All): init
|
||||||
|
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::MONITOR, entity=[ty=NetControl::FLOW, conn=<uninitialized>, flow=[src_h=192.168.18.50/32, src_p=56981/tcp, dst_h=74.125.239.97/32, dst_p=443/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _added=F]
|
||||||
|
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.18.50/32, mac=<uninitialized>], expire=0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _added=F]
|
||||||
|
netcontrol debug (Debug-All): add_rule: [ty=NetControl::WHITELIST, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.18.50/32, mac=<uninitialized>], expire=0 secs, priority=5, location=, out_port=<uninitialized>, mod=<uninitialized>, id=4, cid=4, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _added=F]
|
||||||
|
netcontrol debug (Debug-All): add_rule: [ty=NetControl::REDIRECT, target=NetControl::FORWARD, entity=[ty=NetControl::FLOW, conn=<uninitialized>, flow=[src_h=192.168.18.50/32, src_p=56981/tcp, dst_h=74.125.239.97/32, dst_p=443/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=0 secs, priority=0, location=, out_port=5, mod=<uninitialized>, id=5, cid=5, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _added=F]
|
||||||
|
netcontrol debug (Debug-All): remove_rule: [ty=NetControl::DROP, target=NetControl::MONITOR, entity=[ty=NetControl::FLOW, conn=<uninitialized>, flow=[src_h=192.168.18.50/32, src_p=56981/tcp, dst_h=74.125.239.97/32, dst_p=443/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x091\x0a}, _active_plugin_ids={\x0a\x091\x0a}, _added=T]
|
||||||
|
netcontrol debug (Debug-All): remove_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.18.50/32, mac=<uninitialized>], expire=0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_ids={\x0a\x091\x0a}, _active_plugin_ids={\x0a\x091\x0a}, _added=T]
|
||||||
|
netcontrol debug (Debug-All): remove_rule: [ty=NetControl::WHITELIST, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.18.50/32, mac=<uninitialized>], expire=0 secs, priority=5, location=, out_port=<uninitialized>, mod=<uninitialized>, id=4, cid=4, _plugin_ids={\x0a\x091\x0a}, _active_plugin_ids={\x0a\x091\x0a}, _added=T]
|
||||||
|
netcontrol debug (Debug-All): remove_rule: [ty=NetControl::REDIRECT, target=NetControl::FORWARD, entity=[ty=NetControl::FLOW, conn=<uninitialized>, flow=[src_h=192.168.18.50/32, src_p=56981/tcp, dst_h=74.125.239.97/32, dst_p=443/tcp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], expire=0 secs, priority=0, location=, out_port=5, mod=<uninitialized>, id=5, cid=5, _plugin_ids={\x0a\x091\x0a}, _active_plugin_ids={\x0a\x091\x0a}, _added=T]
|
||||||
|
Dumping state
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
1
|
||||||
|
[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=1.2.3.4/32, mac=<uninitialized>]
|
||||||
|
0
|
||||||
|
4
|
||||||
|
[ty=NetControl::FLOW, conn=<uninitialized>, flow=[src_h=127.0.0.2/32, src_p=<uninitialized>, dst_h=8.8.8.8/32, dst_p=53/udp, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], NetControl::MODIFY
|
||||||
|
[ty=NetControl::FLOW, conn=<uninitialized>, flow=[src_h=127.0.0.2/32, src_p=<uninitialized>, dst_h=<uninitialized>, dst_p=<uninitialized>, src_m=<uninitialized>, dst_m=<uninitialized>], ip=<uninitialized>, mac=<uninitialized>], NetControl::DROP
|
|
@ -0,0 +1,54 @@
|
||||||
|
# @TEST-EXEC: bro -r $TRACES/tls/ecdhe.pcap %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff .stdout
|
||||||
|
|
||||||
|
# Verify the state of internal tables after rules have been deleted...
|
||||||
|
|
||||||
|
@load base/frameworks/netcontrol
|
||||||
|
|
||||||
|
module NetControl;
|
||||||
|
|
||||||
|
export {
|
||||||
|
global dump_state: function();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dump_state()
|
||||||
|
{
|
||||||
|
print "Dumping state";
|
||||||
|
print rules;
|
||||||
|
print rule_entities;
|
||||||
|
print rules_by_subnets;
|
||||||
|
}
|
||||||
|
|
||||||
|
module GLOBAL;
|
||||||
|
|
||||||
|
global rules: vector of string;
|
||||||
|
|
||||||
|
event NetControl::init()
|
||||||
|
{
|
||||||
|
local netcontrol_debug = NetControl::create_debug(T);
|
||||||
|
NetControl::activate(netcontrol_debug, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
event remove_all()
|
||||||
|
{
|
||||||
|
for ( i in rules )
|
||||||
|
NetControl::remove_rule(rules[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
event dump_info()
|
||||||
|
{
|
||||||
|
NetControl::dump_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
event connection_established(c: connection)
|
||||||
|
{
|
||||||
|
local id = c$id;
|
||||||
|
rules[|rules|] = NetControl::shunt_flow([$src_h=id$orig_h, $src_p=id$orig_p, $dst_h=id$resp_h, $dst_p=id$resp_p], 0secs);
|
||||||
|
rules[|rules|] = NetControl::drop_address(id$orig_h, 0secs);
|
||||||
|
rules[|rules|] = NetControl::whitelist_address(id$orig_h, 0secs);
|
||||||
|
rules[|rules|] = NetControl::redirect_flow([$src_h=id$orig_h, $src_p=id$orig_p, $dst_h=id$resp_h, $dst_p=id$resp_p], 5, 0secs);
|
||||||
|
|
||||||
|
schedule 1sec { remove_all() };
|
||||||
|
schedule 2sec { dump_info() };
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# @TEST-EXEC: bro %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
@load base/frameworks/netcontrol
|
||||||
|
|
||||||
|
global outfile: file;
|
||||||
|
|
||||||
|
event NetControl::init()
|
||||||
|
{
|
||||||
|
local netcontrol_debug = NetControl::create_debug(T);
|
||||||
|
NetControl::activate(netcontrol_debug, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
event NetControl::init_done() &priority=-5
|
||||||
|
{
|
||||||
|
NetControl::shunt_flow([$src_h=192.168.17.1, $src_p=32/tcp, $dst_h=192.168.17.2, $dst_p=32/tcp], 30sec);
|
||||||
|
NetControl::drop_address(1.1.2.2, 15sec, "Hi there");
|
||||||
|
NetControl::whitelist_address(1.2.3.4, 15sec);
|
||||||
|
NetControl::redirect_flow([$src_h=192.168.17.1, $src_p=32/tcp, $dst_h=192.168.17.2, $dst_p=32/tcp], 5, 30sec);
|
||||||
|
NetControl::quarantine_host(127.0.0.2, 8.8.8.8, 127.0.0.3, 15sec);
|
||||||
|
|
||||||
|
outfile = open("out");
|
||||||
|
local rules = NetControl::find_rules_addr(1.2.3.4);
|
||||||
|
print outfile, |rules|;
|
||||||
|
print outfile, rules[0]$entity;
|
||||||
|
rules = NetControl::find_rules_addr(1.2.3.5);
|
||||||
|
print outfile, |rules|;
|
||||||
|
rules = NetControl::find_rules_addr(127.0.0.2);
|
||||||
|
print outfile, |rules|;
|
||||||
|
print outfile, rules[0]$entity, rules[0]$ty;
|
||||||
|
print outfile, rules[3]$entity, rules[3]$ty;
|
||||||
|
close(outfile);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue