[pve-devel] [PATCH] optimize : accept from physical interfaces on bridges

Alexandre Derumier aderumier at odiso.com
Tue Apr 22 05:57:15 CEST 2014


They are a lot of chance that a packet is coming/going  from/to external network.

Currently, we need to check all tap chains before accept the packet from eth|bond interface.

This can have a big performance impact (mainly for drop|reject, as we don't have an established connection).
So It could be a problem in case of a ddos attack for example.

without optimize
----------------
-A vmbr1-FW -m physdev --physdev-is-in -j vmbr1-OUT

   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT

-A vmbr1-FW -m physdev --physdev-is-out -j vmbr1-IN

   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN

-A vmbr1-FW -m mark --mark 0x1 -j ACCEPT
-A vmbr1-FW -m physdev --physdev-is-out -j ACCEPT

with optimize
------------
-A vmbr1-FW -m physdev --physdev-is-in -j vmbr1-OUT

   -A vmbr1-OUT -m physdev --physdev-in ethX --physdev-is-bridged -g PVEFW-SET-ACCEPT-MARK
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT
   -A vmbr1-OUT -m physdev --physdev-in tapxxxi0 -j tapxxxi0-OUT

-A vmbr1-FW -m physdev --physdev-is-out -j vmbr1-IN
   -A vmbr1-IN -m physdev --physdev-out ethX --physdev-is-bridged -j ACCEPT
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN
   -A vmbr1-IN -m physdev --physdev-out tapxxxi0 --physdev-is-bridged -j tapxxxi0-IN

-A vmbr1-FW -m mark --mark 0x1 -j ACCEPT
-A vmbr1-FW -m physdev --physdev-is-out -j ACCEPT

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 src/PVE/Firewall.pm |   44 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 7ef38fa..83d7c1c 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -15,7 +15,7 @@ use File::Basename;
 use File::Path;
 use IO::File;
 use Net::IP;
-use PVE::Tools qw(run_command lock_file);
+use PVE::Tools qw(run_command lock_file dir_glob_foreach);
 use Encode;
 
 my $hostfw_conf_filename = "/etc/pve/local/host.fw";
@@ -1378,7 +1378,7 @@ sub ruleset_addlog {
 }
 
 sub generate_bridge_chains {
-    my ($ruleset, $hostfw_conf, $bridge, $routing_table) = @_;
+    my ($ruleset, $hostfw_conf, $bridge, $routing_table, $bridges_config) = @_;
 
     my $options = $hostfw_conf->{options} || {};
 
@@ -1393,12 +1393,26 @@ sub generate_bridge_chains {
 
     if (!ruleset_chain_exist($ruleset, "$bridge-OUT")) {
 	ruleset_create_chain($ruleset, "$bridge-OUT");
+
+	if($options->{optimize}){
+	    foreach my $interface (@{$bridges_config->{$bridge}}) {
+		ruleset_addrule($ruleset, "$bridge-OUT", "-m physdev --physdev-is-bridged --physdev-in $interface -g PVEFW-SET-ACCEPT-MARK");
+	    }
+	}
+
 	ruleset_addrule($ruleset, "$bridge-FW", "-m physdev --physdev-is-in -j $bridge-OUT");
 	ruleset_insertrule($ruleset, "PVEFW-INPUT", "-i $bridge -m physdev --physdev-is-in -j $bridge-OUT");
     }
 
     if (!ruleset_chain_exist($ruleset, "$bridge-IN")) {
 	ruleset_create_chain($ruleset, "$bridge-IN");
+
+	if($options->{optimize}){
+	    foreach my $interface (@{$bridges_config->{$bridge}}) {
+		ruleset_addrule($ruleset, "$bridge-IN", "-m physdev --physdev-is-bridged --physdev-out $interface -j ACCEPT");
+	    }
+	}
+
 	ruleset_addrule($ruleset, "$bridge-FW", "-m physdev --physdev-is-out -j $bridge-IN");
 	ruleset_addrule($ruleset, "$bridge-FW", "-m mark --mark 1 -j ACCEPT");
 	# accept traffic to unmanaged bridge ports
@@ -1636,10 +1650,10 @@ sub generate_tap_rules_direction {
 
     # plug the tap chain to bridge chain
     if ($direction eq 'IN') {
-	ruleset_insertrule($ruleset, "$bridge-IN",
+	ruleset_addrule($ruleset, "$bridge-IN",
 			   "-m physdev --physdev-is-bridged --physdev-out $iface -j $tapchain");
     } else {
-	ruleset_insertrule($ruleset, "$bridge-OUT",
+	ruleset_addrule($ruleset, "$bridge-OUT",
 			   "-m physdev --physdev-in $iface -j $tapchain");
     }
 }
@@ -2188,6 +2202,22 @@ sub read_local_vm_config {
     return $vmdata;
 };
 
+sub read_bridges_config {
+
+    my $bridgehash = {};
+
+    dir_glob_foreach('/sys/class/net', 'vmbr(\d+)', sub {
+        my ($bridge) = @_;
+
+	dir_glob_foreach("/sys/class/net/$bridge/brif", '((eth|bond)(\d+)(\.(\d+))?)', sub {
+	    my ($interface) = @_;
+	    push @{$bridgehash->{$bridge}}, $interface;
+	});
+    });
+
+    return $bridgehash;
+};
+
 sub load_vmfw_conf {
     my ($vmid) = @_;
 
@@ -2552,6 +2582,8 @@ sub compile {
     my $vmfw_configs = read_vm_firewall_configs($vmdata);
 
     my $routing_table = read_proc_net_route();
+    
+    my $bridges_config = read_bridges_config();
 
     my $ipset_ruleset = {};
     generate_ipset_chains($ipset_ruleset, $cluster_conf);
@@ -2589,7 +2621,7 @@ sub compile {
 
 	    $bridge .= "v$net->{tag}" if $net->{tag};
 
-	    generate_bridge_chains($ruleset, $hostfw_conf, $bridge, $routing_table);
+	    generate_bridge_chains($ruleset, $hostfw_conf, $bridge, $routing_table, $bridges_config);
 
 	    my $macaddr = $net->{macaddr};
 	    generate_tap_rules_direction($ruleset, $cluster_conf, $hostfw_conf, $iface, $netid, $macaddr,
@@ -2623,7 +2655,7 @@ sub compile {
 		    next; # fixme?
 		}
 
-		generate_bridge_chains($ruleset, $hostfw_conf, $bridge, $routing_table);
+		generate_bridge_chains($ruleset, $hostfw_conf, $bridge, $routing_table, $bridges_config);
 
 		my $macaddr = $d->{mac};
 		my $iface = $d->{host_ifname};
-- 
1.7.10.4



More information about the pve-devel mailing list