implemented ipset rules in iptables
authorAlexandre Derumier <aderumier@odiso.com>
Tue, 1 Apr 2014 14:06:12 +0000 (16:06 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Thu, 3 Apr 2014 05:31:57 +0000 (07:31 +0200)
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@odiso.com>
example/100.fw
example/cluster.fw
src/PVE/Firewall.pm

index 6572fe3..30d1b1b 100644 (file)
@@ -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
index 97f58cb..8af85f6 100644 (file)
@@ -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]
index 6707e66..e63ca63 100644 (file)
@@ -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,