From: Alexandre Derumier Date: Tue, 22 Apr 2014 03:57:15 +0000 (+0200) Subject: optimize : accept from physical interfaces on bridges X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=commitdiff_plain;h=1a301a8d78ec8e25cc5ccebd48b59b1fe1406540 optimize : accept from physical interfaces on bridges 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 --- 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};