]> git.proxmox.com Git - pve-firewall.git/blobdiff - PVE/Firewall.pm
optimize bridge chains
[pve-firewall.git] / PVE / Firewall.pm
index 09703b086f57873dda4f17735635c25bb8a955d8..fb892904fb77b13dffc34e41b925618076279b3b 100644 (file)
@@ -389,6 +389,7 @@ sub get_etc_services {
 
        if ($line =~ m!^(\S+)\s+(\S+)/(tcp|udp).*$!) {
            $services->{byid}->{$2}->{name} = $1;
+           $services->{byid}->{$2}->{port} = $2;
            $services->{byid}->{$2}->{$3} = 1;
            $services->{byname}->{$1} = $services->{byid}->{$2};
        }
@@ -457,9 +458,13 @@ sub parse_port_name_number_or_range {
     my $nbports = 0;
     foreach my $item (split(/,/, $str)) {
        my $portlist = "";
+       my $oldpon = undef;
        foreach my $pon (split(':', $item, 2)) {
+           $pon = $services->{byname}->{$pon}->{port} if $services->{byname}->{$pon}->{port};
            if ($pon =~ m/^\d+$/){
                die "invalid port '$pon'\n" if $pon < 0 && $pon > 65535;
+               die "port '$pon' must be bigger than port '$oldpon' \n" if $oldpon && ($pon < $oldpon);
+               $oldpon = $pon;
            }else{
                die "invalid port $services->{byname}->{$pon}\n" if !$services->{byname}->{$pon};
            }
@@ -627,33 +632,27 @@ sub ruleset_insertrule {
 sub generate_bridge_chains {
     my ($ruleset, $bridge) = @_;
 
-    if (!ruleset_chain_exist($ruleset, "PVEFW-BRIDGE-IN")){
-       ruleset_create_chain($ruleset, "PVEFW-BRIDGE-IN");
-    }
-
-    if (!ruleset_chain_exist($ruleset, "PVEFW-BRIDGE-OUT")){
-       ruleset_create_chain($ruleset, "PVEFW-BRIDGE-OUT");
-    }
-
     if (!ruleset_chain_exist($ruleset, "PVEFW-FORWARD")){
        ruleset_create_chain($ruleset, "PVEFW-FORWARD");
-
        ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT");
-       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-in --physdev-is-bridged -j PVEFW-BRIDGE-OUT");
-       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-m physdev --physdev-is-out --physdev-is-bridged -j PVEFW-BRIDGE-IN");
     }
 
-    if (!ruleset_chain_exist($ruleset, "$bridge-IN")) {
-       ruleset_create_chain($ruleset, "$bridge-IN");
-       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -j DROP");  # disable interbridge routing
-       ruleset_addrule($ruleset, "PVEFW-BRIDGE-IN", "-j $bridge-IN");
-       ruleset_addrule($ruleset, "$bridge-IN", "-j ACCEPT");
+    if (!ruleset_chain_exist($ruleset, "$bridge")) {
+       ruleset_create_chain($ruleset, "$bridge");
+       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -m physdev --physdev-is-bridged -j $bridge");
+       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -m physdev --physdev-is-bridged -j $bridge");
+       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -j DROP");  # disable interbridge routing
+       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-i $bridge -j DROP"); # disable interbridge routing
     }
 
     if (!ruleset_chain_exist($ruleset, "$bridge-OUT")) {
        ruleset_create_chain($ruleset, "$bridge-OUT");
-       ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o $bridge -j DROP"); # disable interbridge routing
-       ruleset_addrule($ruleset, "PVEFW-BRIDGE-OUT", "-j $bridge-OUT");
+       ruleset_addrule($ruleset, "$bridge", "-m physdev --physdev-is-bridged --physdev-is-in -j $bridge-OUT");
+    }
+
+    if (!ruleset_chain_exist($ruleset, "$bridge-IN")) {
+       ruleset_create_chain($ruleset, "$bridge-IN");
+       ruleset_addrule($ruleset, "$bridge", "-m physdev --physdev-is-bridged --physdev-is-out -j $bridge-IN");
     }
 }
 
@@ -1109,23 +1108,30 @@ sub compile {
 
     my $ruleset = {};
 
-    # setup host firewall rules
     ruleset_create_chain($ruleset, "PVEFW-INPUT");
     ruleset_create_chain($ruleset, "PVEFW-OUTPUT");
+    ruleset_create_chain($ruleset, "PVEFW-FORWARD");
 
     ruleset_create_chain($ruleset, "PVEFW-SET-ACCEPT-MARK");
     ruleset_addrule($ruleset, "PVEFW-SET-ACCEPT-MARK", "-j MARK --set-mark 1");
 
+    my $enable_hostfw = 0;
     $filename = "/etc/pve/local/host.fw";
     if (my $fh = IO::File->new($filename, O_RDONLY)) {
        my $host_rules = parse_host_fw_rules($filename, $fh);
+
+       $enable_hostfw = 1;
+
        enablehostfw($ruleset, $host_rules, $group_rules);
     }
 
     # generate firewall rules for QEMU VMs 
     foreach my $vmid (keys %{$vmdata->{qemu}}) {
        my $conf = $vmdata->{qemu}->{$vmid};
+
        next if !$rules->{$vmid};
+       my $options = $rules->{$vmid}->{options};
+       next if defined($options->{enable}) && ($options->{enable} == 0);
 
        foreach my $netid (keys %$conf) {
            next if $netid !~ m/^net(\d+)$/;
@@ -1138,6 +1144,7 @@ sub compile {
 
            $bridge .= "v$net->{tag}" if $net->{tag};
 
+
            generate_bridge_chains($ruleset, $bridge);
 
            my $macaddr = $net->{macaddr};
@@ -1146,8 +1153,10 @@ sub compile {
        }
     }
 
-    # allow traffic from lo (ourself)
-    ruleset_addrule($ruleset, "PVEFW-INPUT", "-i lo -j ACCEPT");
+    if ($enable_hostfw) {
+       # allow traffic from lo (ourself)
+       ruleset_addrule($ruleset, "PVEFW-INPUT", "-i lo -j ACCEPT");
+    }
 
     return $ruleset;
 }
@@ -1265,6 +1274,9 @@ sub apply_ruleset {
     }
     foreach my $chain (keys %$statushash) {
        next if $statushash->{$chain}->{action} ne 'delete';
+       next if $chain eq 'PVEFW-INPUT';
+       next if $chain eq 'PVEFW-OUTPUT';
+       next if $chain eq 'PVEFW-FORWARD';
        $cmdlist .= "-X $chain\n";
     }