From ba791b1f670d2d02d981b28a6e52f056906e18f2 Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Tue, 1 Apr 2014 16:06:12 +0200 Subject: [PATCH] implemented ipset rules in iptables I'm reusing shorewall syntax, +mynetgroup also fixing iprange and iplist vmid.fw ------- IN SSH(ACCEPT) net0 192.168.2.192 # only allow SSH from 192.168.2.192 IN SSH(ACCEPT) net0 10.0.0.1-10.0.0.10 #accept SSH for ip in range 10.0.0.1 to 10.0.0.10 IN SSH(ACCEPT) net0 10.0.0.1,10.0.0.2,10.0.0.3 #accept ssh for 10.0.0.1 or 10.0.0.2 or 10.0.0.3 IN SSH(ACCEPT) net0 +mynetgroup #accept ssh for netgroup mynetgroup cluster.fw ---------- IN ACCEPT 10.0.0.1 IN ACCEPT 10.0.0.1-10.0.0.10 IN ACCEPT 10.0.0.1,10.0.0.2,10.0.0.3 IN ACCEPT +mynetgroup Signed-off-by: Alexandre Derumier --- example/100.fw | 4 +++ example/cluster.fw | 5 ++-- src/PVE/Firewall.pm | 62 +++++++++++++++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/example/100.fw b/example/100.fw index 6572fe3..30d1b1b 100644 --- a/example/100.fw +++ b/example/100.fw @@ -43,6 +43,10 @@ ips_queues: 0:3 IN SSH(ACCEPT) net0 IN SSH(ACCEPT) net0 # a comment IN SSH(ACCEPT) net0 192.168.2.192 # only allow SSH from 192.168.2.192 +IN SSH(ACCEPT) net0 10.0.0.1-10.0.0.10 #accept SSH for ip in range 10.0.0.1 to 10.0.0.10 +IN SSH(ACCEPT) net0 10.0.0.1,10.0.0.2,10.0.0.3 #accept ssh for 10.0.0.1 or 10.0.0.2 or 10.0.0.3 +IN SSH(ACCEPT) net0 +mynetgroup #accept ssh for netgroup mynetgroup + |IN SSH(ACCEPT) net0 # disabled rule # add a security group diff --git a/example/cluster.fw b/example/cluster.fw index 97f58cb..8af85f6 100644 --- a/example/cluster.fw +++ b/example/cluster.fw @@ -15,8 +15,9 @@ OUT ACCEPT - - icmp - - [group group3] IN ACCEPT 10.0.0.1 -IN ACCEPT 10.0.0.2 -IN ACCEPT 10.0.0.2 +IN ACCEPT 10.0.0.1-10.0.0.10 +IN ACCEPT 10.0.0.1,10.0.0.2,10.0.0.3 +IN ACCEPT +mynetgroup [netgroup mynetgroup] diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 6707e66..e63ca63 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -603,6 +603,9 @@ sub parse_address_list { my $nbaor = 0; foreach my $aor (split(/,/, $str)) { + if($nbaor > 0 && $aor =~ m/-/){ + die "you can use a range in a list"; + } if (!Net::IP->new($aor)) { my $err = Net::IP::Error(); die "invalid IP address: $err\n"; @@ -610,7 +613,6 @@ sub parse_address_list { $nbaor++; } } - return $nbaor; } sub parse_port_name_number_or_range { @@ -914,7 +916,7 @@ sub ipset_get_chains { } sub ruleset_generate_cmdstr { - my ($ruleset, $chain, $rule, $actions, $goto) = @_; + my ($ruleset, $chain, $rule, $actions, $goto, $cluster_conf) = @_; return if defined($rule->{enable}) && !$rule->{enable}; @@ -922,18 +924,40 @@ sub ruleset_generate_cmdstr { my $nbdport = defined($rule->{dport}) ? parse_port_name_number_or_range($rule->{dport}) : 0; my $nbsport = defined($rule->{sport}) ? parse_port_name_number_or_range($rule->{sport}) : 0; - my $nbsource = $rule->{source} ? parse_address_list( $rule->{source}) : 0; - my $nbdest = $rule->{dest} ? parse_address_list($rule->{dest}) : 0; my @cmd = (); push @cmd, "-i $rule->{iface_in}" if $rule->{iface_in}; push @cmd, "-o $rule->{iface_out}" if $rule->{iface_out}; - push @cmd, "-m iprange --src-range" if $nbsource > 1; - push @cmd, "-s $rule->{source}" if $rule->{source}; - push @cmd, "-m iprange --dst-range" if $nbdest > 1; - push @cmd, "-d $rule->{dest}" if $rule->{dest}; + my $source = $rule->{source}; + my $dest = $rule->{dest}; + + if ($source){ + if($source =~ m/^(\+)(\S+)$/){ + die "no such netgroup $2" if !$cluster_conf->{ipset}->{$2}; + push @cmd, "-m set --match-set $2 src"; + + }elsif ($source =~ m/^(\d+)\.(\d+).(\d+).(\d+)\-(\d+)\.(\d+).(\d+).(\d+)$/){ + push @cmd, "-m iprange --src-range $source"; + + }else{ + push @cmd, "-s $source"; + } + } + + if ($dest){ + if($dest =~ m/^(\+)(\S+)$/){ + die "no such netgroup $2" if !$cluster_conf->{ipset}->{$2}; + push @cmd, "-m set --match-set $2 dst"; + + }elsif ($dest =~ m/^(\d+)\.(\d+).(\d+).(\d+)\-(\d+)\.(\d+).(\d+).(\d+)$/){ + push @cmd, "-m iprange --dst-range $dest"; + + }else{ + push @cmd, "-s $dest"; + } + } if ($rule->{proto}) { push @cmd, "-p $rule->{proto}"; @@ -1033,7 +1057,7 @@ my $apply_macro = sub { }; sub ruleset_generate_rule { - my ($ruleset, $chain, $rule, $actions, $goto) = @_; + my ($ruleset, $chain, $rule, $actions, $goto, $cluster_conf) = @_; my $rules; @@ -1044,7 +1068,7 @@ sub ruleset_generate_rule { } foreach my $tmp (@$rules) { - if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $tmp, $actions, $goto)) { + if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $tmp, $actions, $goto, $cluster_conf)) { ruleset_addrule($ruleset, $chain, $cmdstr); } } @@ -1240,10 +1264,10 @@ sub ruleset_generate_vm_rules { next if $rule->{type} ne $lc_direction; if ($direction eq 'OUT') { ruleset_generate_rule($ruleset, $chain, $rule, - { ACCEPT => "PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" }); + { ACCEPT => "PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" }, undef, $cluster_conf); } else { my $accept = generate_nfqueue($options); - ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept , REJECT => "PVEFW-reject" }); + ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept , REJECT => "PVEFW-reject" }, undef, $cluster_conf); } } } @@ -1419,7 +1443,7 @@ sub enable_host_firewall { foreach my $rule (@$rules) { next if $rule->{type} ne 'in'; - ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }); + ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, undef, $cluster_conf); } # implement input policy @@ -1444,7 +1468,7 @@ sub enable_host_firewall { foreach my $rule (@$rules) { next if $rule->{type} ne 'out'; - ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }); + ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => $accept_action, REJECT => "PVEFW-reject" }, undef, $cluster_conf); } # implement output policy @@ -1468,7 +1492,7 @@ sub generate_group_rules { foreach my $rule (@$rules) { next if $rule->{type} ne 'in'; - ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => "PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" }); + ruleset_generate_rule($ruleset, $chain, $rule, { ACCEPT => "PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" }, undef, $cluster_conf); } $chain = "GROUP-${group}-OUT"; @@ -1481,7 +1505,7 @@ sub generate_group_rules { # we use PVEFW-SET-ACCEPT-MARK (Instead of ACCEPT) because we need to # check also other tap rules later ruleset_generate_rule($ruleset, $chain, $rule, - { ACCEPT => 'PVEFW-SET-ACCEPT-MARK', REJECT => "PVEFW-reject" }); + { ACCEPT => 'PVEFW-SET-ACCEPT-MARK', REJECT => "PVEFW-reject" }, undef, $cluster_conf); } } @@ -1556,9 +1580,9 @@ sub parse_fw_rule { parse_port_name_number_or_range($dport) if defined($dport); parse_port_name_number_or_range($sport) if defined($sport); - - parse_address_list($source) if $source; - parse_address_list($dest) if $dest; + + parse_address_list($source) if $source && $source !~ m/^(\+)(\S+)$/; + parse_address_list($dest) if $dest && $dest !~ m/^(\+)(\S+)$/; return { type => $type, -- 2.39.2