[pve-devel] [PATCH 1/2] compile ebtables rules

Alexandre DERUMIER aderumier at odiso.com
Tue Jul 15 20:43:20 CEST 2014


>>this one has the old mac patch included. Please use V3. 
Oh, I have missed your v3 patch in all theses mail, I'll send a new version tomorrow morning.

----- Mail original ----- 

De: "Stefan Priebe" <s.priebe at profihost.ag> 
À: "Alexandre Derumier" <aderumier at odiso.com>, pve-devel at pve.proxmox.com 
Envoyé: Mardi 15 Juillet 2014 19:48:19 
Objet: Re: [pve-devel] [PATCH 1/2] compile ebtables rules 

this one has the old mac patch included. Please use V3. 

Am 15.07.2014 19:45, schrieb Alexandre Derumier: 
> -A FORWARD -j PVEFW-FORWARD 
> -A PVEFW-FORWARD -p IPv4 -j ACCEPT #filter mac in iptables for ipv4, so we can speedup rules with conntrack established 
> -A PVEFW-FORWARD -p IPv6 -j ACCEPT 
> -A PVEFW-FORWARD -o fwln+ -j PVEFW-FWBR-OUT 
> -A PVEFW-FWBR-OUT -i tap110i0 -j tap110i0-OUT 
> -A tap110i0-OUT -s ! 36:97:15:91:19:3c -j DROP 
> -A tap110i0-OUT -p ARP -j ACCEPT 
> -A tap110i0-OUT -j DROP 
> -A tap110i0-OUT -j ACCEPT 
> -A PVEFW-FWBR-OUT -i veth130.1 -j veth130.1-OUT 
> -A veth130.1-OUT -s ! 36:95:a9:ae:f5:ec -j DROP 
> -A veth130.1-OUT -j ACCEPT 
> 
> Signed-off-by: Alexandre Derumier <aderumier at odiso.com> 
> --- 
> debian/example/100.fw | 3 ++ 
> src/PVE/Firewall.pm | 102 ++++++++++++++++++++++++++++++++++++++++++++++++- 
> src/pve-firewall | 4 +- 
> 3 files changed, 105 insertions(+), 4 deletions(-) 
> 
> diff --git a/debian/example/100.fw b/debian/example/100.fw 
> index 7a8da48..0388dde 100644 
> --- a/debian/example/100.fw 
> +++ b/debian/example/100.fw 
> @@ -9,6 +9,9 @@ enable: 1 
> # disable/enable MAC address filter 
> macfilter: 0 
> 
> +# allow only layer2 specific protocols 
> +layer2filter_protocols: ARP,802_1Q,IPX,NetBEUI,PPP 
> + 
> # default policy 
> policy_in: DROP 
> policy_out: REJECT 
> diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm 
> index abf122b..48d9b8c 100644 
> --- a/src/PVE/Firewall.pm 
> +++ b/src/PVE/Firewall.pm 
> @@ -2245,6 +2245,9 @@ sub parse_vmfw_option { 
> } elsif ($line =~ m/^(policy_(in|out)):\s*(ACCEPT|DROP|REJECT)\s*$/i) { 
> $opt = lc($1); 
> $value = uc($3); 
> + } elsif ($line =~ m/^(layer2filter_protocols):\s*(((ARP|802_1Q|IPX|NetBEUI|PPP)[,]?)+)\s*$/i) { 
> + $opt = lc($1); 
> + $value = $2; 
> } elsif ($line =~ m/^(ips_queues):\s*((\d+)(:(\d+))?)\s*$/i) { 
> $opt = lc($1); 
> $value = $2; 
> @@ -3000,8 +3003,9 @@ sub compile { 
> 
> my ($ruleset, $ipset_ruleset) = compile_iptables_filter($cluster_conf, $hostfw_conf, $vmfw_configs, $vmdata, 4, $verbose); 
> my ($rulesetv6) = compile_iptables_filter($cluster_conf, $hostfw_conf, $vmfw_configs, $vmdata, 6, $verbose); 
> + my ($ebtables_ruleset) = compile_ebtables_filter($cluster_conf, $hostfw_conf, $vmfw_configs, $vmdata, $verbose); 
> 
> - return ($ruleset, $ipset_ruleset, $rulesetv6); 
> + return ($ruleset, $ipset_ruleset, $rulesetv6, $ebtables_ruleset); 
> } 
> 
> sub compile_iptables_filter { 
> @@ -3150,6 +3154,100 @@ sub compile_iptables_filter { 
> return ($ruleset, $ipset_ruleset); 
> } 
> 
> +sub compile_ebtables_filter { 
> + my ($cluster_conf, $hostfw_conf, $vmfw_configs, $vmdata, $verbose) = @_; 
> + 
> + return ({}, {}) if !$cluster_conf->{options}->{enable}; 
> + 
> + my $ruleset = {}; 
> + 
> + ruleset_create_chain($ruleset, "PVEFW-FORWARD"); 
> + 
> + 
> + ruleset_create_chain($ruleset, "PVEFW-FWBR-OUT"); 
> + #for ipv4 and ipv6, check macaddress in iptables, so we use conntrack 'ESTABLISHED', to speedup rules 
> + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-p IPv4 -j ACCEPT"); 
> + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-p IPv6 -j ACCEPT"); 
> + ruleset_addrule($ruleset, "PVEFW-FORWARD", "-o fwln+ -j PVEFW-FWBR-OUT"); 
> + 
> + # generate firewall rules for QEMU VMs 
> + foreach my $vmid (keys %{$vmdata->{qemu}}) { 
> + eval { 
> + my $conf = $vmdata->{qemu}->{$vmid}; 
> + my $vmfw_conf = $vmfw_configs->{$vmid}; 
> + return if !$vmfw_conf; 
> + 
> + foreach my $netid (keys %$conf) { 
> + next if $netid !~ m/^net(\d+)$/; 
> + my $net = PVE::QemuServer::parse_net($conf->{$netid}); 
> + next if !$net->{firewall}; 
> + my $iface = "tap${vmid}i$1"; 
> + my $macaddr = $net->{macaddr}; 
> + 
> + # ebtables remove preceeding zero so we need todo it too (but only the first) 
> + $macaddr =~ s/^0//; 
> + 
> + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid); 
> + 
> + } 
> + }; 
> + warn $@ if $@; # just to be sure - should not happen 
> + } 
> + 
> + # generate firewall rules for OpenVZ containers 
> + foreach my $vmid (keys %{$vmdata->{openvz}}) { 
> + eval { 
> + my $conf = $vmdata->{openvz}->{$vmid}; 
> + 
> + my $vmfw_conf = $vmfw_configs->{$vmid}; 
> + return if !$vmfw_conf; 
> + 
> + if ($conf->{netif} && $conf->{netif}->{value}) { 
> + my $netif = PVE::OpenVZ::parse_netif($conf->{netif}->{value}); 
> + foreach my $netid (keys %$netif) { 
> + my $d = $netif->{$netid}; 
> + my $bridge = $d->{bridge}; 
> + next if !$bridge || $bridge !~ m/^vmbr\d+(v(\d+))?f$/; # firewall enabled ? 
> + my $macaddr = $d->{mac}; 
> + my $iface = $d->{host_ifname}; 
> + 
> + # ebtables remove preceeding zero so we need todo it too (but only the first) 
> + $macaddr =~ s/^0//; 
> + 
> + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid); 
> + } 
> + } 
> + }; 
> + warn $@ if $@; # just to be sure - should not happen 
> + } 
> + 
> + return $ruleset; 
> +} 
> + 
> +sub generate_tap_layer2filter { 
> + my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid) = @_; 
> + my $options = $vmfw_conf->{options}; 
> + 
> + my $tapchain = $iface."-OUT"; 
> + $macaddr = lc($macaddr); 
> + 
> + ruleset_create_chain($ruleset, $tapchain); 
> + 
> + if (defined($macaddr) && !(defined($options->{macfilter}) && $options->{macfilter} == 0)) { 
> + ruleset_addrule($ruleset, $tapchain, "-s ! $macaddr -j DROP"); 
> + } 
> + 
> + if (defined($options->{layer2filter_protocols})){ 
> + foreach my $proto (split(/,/, $options->{layer2filter_protocols})) { 
> + ruleset_addrule($ruleset, $tapchain, "-p $proto -j ACCEPT"); 
> + } 
> + ruleset_addrule($ruleset, $tapchain, "-j DROP"); 
> + } 
> + 
> + ruleset_addrule($ruleset, $tapchain, "-j ACCEPT"); 
> + ruleset_addrule($ruleset, "PVEFW-FWBR-OUT","-i $iface -j $tapchain"); 
> +} 
> + 
> sub get_ruleset_status { 
> my ($ruleset, $active_chains, $digest_fn, $verbose) = @_; 
> 
> @@ -3475,7 +3573,7 @@ sub update { 
> 
> my $hostfw_conf = load_hostfw_conf(); 
> 
> - my ($ruleset, $ipset_ruleset, $rulesetv6) = compile($cluster_conf, $hostfw_conf); 
> + my ($ruleset, $ipset_ruleset, $rulesetv6, $ebtables_ruleset) = compile($cluster_conf, $hostfw_conf); 
> 
> apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $rulesetv6); 
> }; 
> diff --git a/src/pve-firewall b/src/pve-firewall 
> index 6e5eb16..8e4c68d 100755 
> --- a/src/pve-firewall 
> +++ b/src/pve-firewall 
> @@ -344,7 +344,7 @@ __PACKAGE__->register_method ({ 
> 
> if ($status eq 'running') { 
> 
> - my ($ruleset, $ipset_ruleset, $rulesetv6) = PVE::Firewall::compile($cluster_conf, undef, undef, $verbose); 
> + my ($ruleset, $ipset_ruleset, $rulesetv6, $ebtables_ruleset) = PVE::Firewall::compile($cluster_conf, undef, undef, $verbose); 
> 
> $verbose = 0; # do not show iptables details 
> my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, $verbose); 
> @@ -381,7 +381,7 @@ __PACKAGE__->register_method ({ 
> my $verbose = 1; 
> 
> my $cluster_conf = PVE::Firewall::load_clusterfw_conf(undef, $verbose); 
> - my ($ruleset, $ipset_ruleset, $rulesetv6) = PVE::Firewall::compile($cluster_conf, undef, undef, $verbose); 
> + my ($ruleset, $ipset_ruleset, $rulesetv6, $ebtables_ruleset) = PVE::Firewall::compile($cluster_conf, undef, undef, $verbose); 
> 
> my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, $verbose); 
> my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, $verbose); 
> 


More information about the pve-devel mailing list