From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id C39796B2BD for ; Fri, 18 Mar 2022 14:26:10 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id BAB751DF1D for ; Fri, 18 Mar 2022 14:26:10 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 652031DF14 for ; Fri, 18 Mar 2022 14:26:09 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 390F346EC1; Fri, 18 Mar 2022 14:26:09 +0100 (CET) Date: Fri, 18 Mar 2022 14:26:05 +0100 From: Wolfgang Bumiller To: Alexandre Derumier Cc: pve-devel@lists.proxmox.com Message-ID: <20220318132605.mevywhdgakluajz4@wobu-vie.proxmox.com> References: <20210910153430.4045276-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210910153430.4045276-1-aderumier@odiso.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.356 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: Re: [pve-devel] [PATCH V2 pve-firewall] add cluster ebtables_dst_macfilter option. X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Mar 2022 13:26:10 -0000 Sorry for the late reply. On Fri, Sep 10, 2021 at 05:34:29PM +0200, Alexandre Derumier wrote: > This new option allow filtering of destination macs for ingress traffic. > > This is a protection from bad/hosting networks (like hetzner) flooding > traffic with non-hosted mac. > > To be fast, one rule, this use the "--among-dst mac,mac,mac,mac," syntax. > broadcast mac ff:ff:ff:ff:ff:ff is always allowed > > currently, ebtables-restore segfault if too many are defined > https://www.spinics.net/lists/netfilter/msg55995.html > > So, I'm using "--among-dst-file", loading macs from an external file. It's a little awkward but works, I guess, however, it does mess with the digests we use to verify the ruleset and therefore keeps logging errors in syslog. This will need fixing. How many entries can you have before this starts happening anyway? And how many entries do you expect there to be? > Note that "ebtables-save" still show the syntax with "--among-dst mac,mac,mac," > (with a comma at the end), so I compile the full mac list with --among-dst to > compare, and if update is needed, I'm writing the dst file in > /var/lib/pve-firewall/chain-macfilter, and replace among-dst syntax by among-dst-file > > Changelog v2: > - as we use one rule for performance, add all vms/ct macaddress when vm firewall is enabled. > (even if vm macfilter option is disabled). > > Signed-off-by: Alexandre Derumier > --- > src/PVE/Firewall.pm | 40 ++++++++++++++++++++++++++++++++++++---- > 1 file changed, 36 insertions(+), 4 deletions(-) > > diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm > index edc5336..8277ee0 100644 > --- a/src/PVE/Firewall.pm > +++ b/src/PVE/Firewall.pm > @@ -1221,6 +1221,11 @@ our $cluster_option_properties = { > default => 1, > optional => 1, > }, > + ebtables_dst_macfilter => { > + description => "Filtering VM/CT destination mac for ingress traffic.", > + type => 'boolean', > + optional => 1, > + }, > policy_in => { > description => "Input policy.", > type => 'string', > @@ -2867,7 +2872,7 @@ sub parse_clusterfw_option { > if (($value > 1) && ((time() - $value) > 60)) { > $value = 0 > } > - } elsif ($line =~ m/^(ebtables):\s*(0|1)\s*$/i) { > + } elsif ($line =~ m/^(ebtables|ebtables_dst_macfilter):\s*(0|1)\s*$/i) { > $opt = lc($1); > $value = int($2); > } elsif ($line =~ m/^(policy_(in|out)):\s*(ACCEPT|DROP|REJECT)\s*$/i) { > @@ -3948,11 +3953,19 @@ sub compile_ebtables_filter { > ruleset_create_chain($ruleset, "PVEFW-FORWARD"); > > ruleset_create_chain($ruleset, "PVEFW-FWBR-OUT"); > + > + if ($cluster_conf->{options}->{ebtables_dst_macfilter}) { > + #filtering destination mac for ipv4/ipv6 > + ruleset_create_chain($ruleset, "PVEFW-FWBR-IN"); > + ruleset_addrule($ruleset, 'PVEFW-FORWARD', '-i fwln+', '-j PVEFW-FWBR-IN'); > + } > + > #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'); > > + my $maclist = []; > # generate firewall rules for QEMU VMs > foreach my $vmid (sort keys %{$vmdata->{qemu}}) { > eval { > @@ -3975,7 +3988,7 @@ sub compile_ebtables_filter { > push(@$arpfilter, $ip); > } > } > - generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter); > + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter, $maclist); > } > }; > warn $@ if $@; # just to be sure - should not happen > @@ -4012,17 +4025,23 @@ sub compile_ebtables_filter { > push @$arpfilter, $ip; > } > } > - generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter); > + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter, $maclist); > } > }; > warn $@ if $@; # just to be sure - should not happen > } > > + if ($cluster_conf->{options}->{'ebtables_dst_macfilter'} && @$maclist > 0) { > + push @$maclist, 'ff:ff:ff:ff:ff:ff'; #allow broadcast mac > + my $maclist_str = join ',',sort(@$maclist); > + ruleset_addrule($ruleset, 'PVEFW-FWBR-IN', "--among-dst ! $maclist_str,", '-j DROP'); > + } > + > return $ruleset; > } > > sub generate_tap_layer2filter { > - my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter) = @_; > + my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter, $maclist) = @_; > my $options = $vmfw_conf->{options}; > > my $tapchain = $iface."-OUT"; > @@ -4037,6 +4056,10 @@ sub generate_tap_layer2filter { > ruleset_addrule($ruleset, $tapchain, "-s ! $macaddr", '-j DROP'); > } > > + if (defined($macaddr)) { > + push @$maclist, $macaddr; > + } > + > if (@$arpfilter){ > my $arpchain = $tapchain."-ARP"; > ruleset_addrule($ruleset, $tapchain, "-p ARP", "-j $arpchain"); > @@ -4225,6 +4248,15 @@ sub get_ebtables_cmdlist { > next if ! $pve_include; > $pve_include = 0; > } > + > + if ($cmd =~ m/^-A (\S+) --among-dst ! (\S+) -j DROP/) { > + my $chain = $1; > + my $maclist_raw = $2."\n"; > + my $filename = "$pve_fw_status_dir/ebtables_macfilter-$chain"; > + PVE::Tools::file_set_contents($filename, $maclist_raw); > + $cmd = "-A $1 --among-dst-file ! $filename -j DROP"; > + } > + > $cmdlist .= "$cmd\n"; > } > } > -- > 2.30.2