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

Stefan Priebe s.priebe at profihost.ag
Tue Jul 15 19:48:19 CEST 2014


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