[pve-devel] [PATCH 1/3] implemented ipset rules in iptables

Alexandre Derumier aderumier at odiso.com
Tue Apr 1 16:06:12 CEST 2014


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 <aderumier at odiso.com>
---
 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 54235fb..e6809ef 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -602,6 +602,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";
@@ -609,7 +612,6 @@ sub parse_address_list {
 	    $nbaor++;
 	}
     }
-    return $nbaor;
 }
 
 sub parse_port_name_number_or_range {
@@ -913,7 +915,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};
 
@@ -921,18 +923,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}";
@@ -1032,7 +1056,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;
 
@@ -1043,7 +1067,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);
 	}
     }
@@ -1239,10 +1263,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);
 	    }
 	}
     }
@@ -1418,7 +1442,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
@@ -1443,7 +1467,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
@@ -1467,7 +1491,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";
@@ -1480,7 +1504,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);
     }
 }
 
@@ -1555,9 +1579,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,
-- 
1.7.10.4



More information about the pve-devel mailing list