Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
mxrouter: Generalize ipsets
Currently mxrouter supports only a single ipset with a fixed name,
type, source filename and option set.

Switch to a more general scheme, where the mxrouter config file can
define and use multiple ipsets with different properties.

Syntax:

	ipset(setname,type,filename,options...)

e.g.:

	ipset('ip-blacklist','hash:ip','/etc/local/mxrouter/ip-blacklist','counters');
	...
	rule('filter','FORWARD','-m set --match-set ip-blacklist src -j DROP');

At the same time, switch to an atomic swap, so that we can't end up
with a incomplete ipset if we hit an error after processing the
input file only in part.

Still unsupported: Types other than 'hash:ip', because before we can use
other types, we'd need to defined a syntax for the file.
  • Loading branch information
donald committed Sep 30, 2019
1 parent f27bd71 commit dda7e33
Showing 1 changed file with 66 additions and 13 deletions.
79 changes: 66 additions & 13 deletions mxrouter/mxrouterctl
Expand Up @@ -316,6 +316,56 @@ sub configure_vlans {
}
}

my $want_ipsets; # { name => [type,filename,create-options]) , ... }

sub ipset {
my ($name,$type,$filename,@options)=@_;
$want_ipsets->{$name}=[$type,$filename,@options];
}

sub read_active_ipsets {
my $active_ipsets; # { $name => 1 , ... )
open my $p,'-|','ipset','--list','-n' or die "$!";
while (<$p>) {
chomp;
$active_ipsets->{$_}=1;
}
return $active_ipsets;
}

sub unconfigure_ipsets {
my ($have_ipsets)=@_;
for my $name (sort keys %$have_ipsets) {
sys('ipset','destroy',$name);
}
}

sub configure_ipsets {
my ($want_ipsets)=@_;
for my $name (sort keys %$want_ipsets) {
my ($type,$filename,@options)=@{$want_ipsets->{$name}};
sys('ipset','create',$name,$type,@options);
}
}
sub reload_ipsets {
my ($want_ipsets)=@_;
for my $name (sort keys %$want_ipsets) {
my ($type,$filename,@options)=@{$want_ipsets->{$name}};
my $tmp="$name-TMP";
warn "read ipset $name from $filename\n";
system('ipset','create',$tmp,$type,@options) and exit 1;
$type eq 'hash:ip' or die "read ipset type $type from file not implemented\n";
open my $in,'<',$filename or die "$filename: $!\n";
while (<$in>) {
s/#.*//;
/^\s*(\d+\.\d+\.\d+\.\d+)\s*$/ or next;
system('ipset','add',$tmp,$1) and exit 1;
}
system('ipset','swap',$name,$tmp) and exit 1;
system('ipset','destroy',$tmp) and exit 1;
}
}

our %radvd; # ( 'net03' => 'AdvSendAdvert on;prefix 2a02:d480:e08:20::/64;' , ...)

sub radvd {
Expand Down Expand Up @@ -358,17 +408,8 @@ sub disable_ipv4_rp_filter {
$disable_ipv4_rp_filter{$if}=1;
}

sub reload_ip_blacklist {
sys('ipset','flush','ip-blacklist');
if (-e '/etc/local/mxrouter/ip-blacklist') {
open my $in,'<','/etc/local/mxrouter/ip-blacklist' or die "/etc/local/mxrouter/ip-blacklist: $!\n";
while (<$in>) {
s/#.*//;
/^\s*(\d+\.\d+\.\d+\.\d+)\s*$/ or next;
system('ipset','add','ip-blacklist',$1);
}
}
}



sub start {

Expand Down Expand Up @@ -494,6 +535,17 @@ sub start {
set_ipv4_routing(1);
}

my $have_ipsets=read_active_ipsets();
my ($new_ipsets,$del_ipsets)=({},{});
for (keys %$want_ipsets) {
$new_ipsets->{$_}=$want_ipsets->{$_}
unless exists $have_ipsets->{$_};
}
for (keys %$have_ipsets) {
$del_ipsets->{$_} = $have_ipsets->{$_}
unless exists $want_ipsets->{$_};
}

stop_process_if($process_ulogd);
stop_process_if($process_dhcrelay);
stop_process_if($process_radvd);
Expand Down Expand Up @@ -530,14 +582,15 @@ sub start {
start_process_if($process_dhcrelay);
start_process_if($process_radvd);

configure_ipsets($new_ipsets);
unless ($opt_noop) {
sys('ipset','create','-exist','ip-blacklist','hash:ip','counters');
reload_ip_blacklist();
open my $pipe,'|-','iptables-restore' or die "$!\n";
print $pipe rules_in_restore_format();
close $pipe or die "$!\n";
$? and exit 1;
}
unconfigure_ipsets($del_ipsets);
reload_ipsets($want_ipsets);
}

sub move_dev_into_ns {
Expand Down

0 comments on commit dda7e33

Please sign in to comment.