[pve-devel] [PATCH pve-firewall] ebtables: add arp filtering
Alexandre DERUMIER
aderumier at odiso.com
Fri Mar 8 14:53:52 CET 2019
> + my $arpchain = $tapchain."-ARP";
> + ruleset_addrule($ruleset, $tapchain, "-p ARP", "-j $arpchain");
> + ruleset_create_chain($ruleset, $arpchain);
> +
> + foreach my $ip (@{$arpfilter}) {
> + ruleset_addrule($ruleset, $arpchain, "-p ARP --arp-ip-src $ip", '-j RETURN');
>>I wish this could just use the actual ipset :-\
we can't use ipset in ebtables :(
> if (defined($options->{layer2_protocols})){
>>This hunk below seems unrelated? Should probably be a separate patch, or
>>is this related somehow?
We need it, because we need an accept at the end of main tap chain.
(for arp, we need a jump to arpchain, return if ip exist or drop),
I'll make it in a separate patch for more visibility. (and I think it's possible to avoid the extra proto chain)
I'll rework the patch with all your comments, and send a V2 monday
----- Mail original -----
De: "Wolfgang Bumiller" <w.bumiller at proxmox.com>
À: "aderumier" <aderumier at odiso.com>
Cc: "pve-devel" <pve-devel at pve.proxmox.com>
Envoyé: Vendredi 8 Mars 2019 10:25:22
Objet: Re: [pve-devel] [PATCH pve-firewall] ebtables: add arp filtering
On Fri, Mar 08, 2019 at 09:14:08AM +0100, Alexandre Derumier wrote:
> This implemented arp filtering if ipfilter is enable
> https://bugzilla.proxmox.com/show_bug.cgi?id=2125
>
> They are another filters possible (ipv4,rarp),
> i don't known if we need them.
>
> Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
> ---
> src/PVE/Firewall.pm | 42 +++++++++++++++++++++++++++++++++---------
> 1 file changed, 33 insertions(+), 9 deletions(-)
>
> diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
> index 2125d3b..f8ed345 100644
> --- a/src/PVE/Firewall.pm
> +++ b/src/PVE/Firewall.pm
> @@ -3694,9 +3694,16 @@ sub compile_ebtables_filter {
> next if !$net->{firewall};
> my $iface = "tap${vmid}i$1";
> my $macaddr = $net->{macaddr};
> -
> - generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid);
> -
> + my $arpfilter = [];
> + my $ipsets = $vmfw_conf->{ipset};
> + if (defined($ipsets->{"ipfilter-$netid"})){
> + foreach my $ipaddr (@{$ipsets->{"ipfilter-$netid"} }) {
Please try to avoid duplicating hash accesses. Eg. use:
if (defined(my $ipset = $ipsets->{"ipfilter-$netid"})){
foreach my $ipaddr (@$ipset) {
> + my($ip,$version) = parse_ip_or_cidr($ipaddr->{cidr});
Missing spaces (`my ($ip, $version) = `)
> + next if !$ip || ($version && $version != 4);
> + push(@$arpfilter, $ip);
> + }
> + }
> + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter);
> }
> };
> warn $@ if $@; # just to be sure - should not happen
> @@ -3716,7 +3723,9 @@ sub compile_ebtables_filter {
> next if !$net->{firewall};
> my $iface = "veth${vmid}i$1";
> my $macaddr = $net->{hwaddr};
> - generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid);
> + my $arpfilter = [];
> + push(@$arpfilter, $net->{ip}) if $net->{ip};
We do have ipfilter-net* ipsets for containers as well, so this would
need to be filled, too.
> + generate_tap_layer2filter($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter);
> }
> };
> warn $@ if $@; # just to be sure - should not happen
> @@ -3726,7 +3735,7 @@ sub compile_ebtables_filter {
> }
>
> sub generate_tap_layer2filter {
> - my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid) = @_;
> + my ($ruleset, $iface, $macaddr, $vmfw_conf, $vmid, $arpfilter) = @_;
> my $options = $vmfw_conf->{options};
>
> my $tapchain = $iface."-OUT";
> @@ -3741,15 +3750,30 @@ sub generate_tap_layer2filter {
> ruleset_addrule($ruleset, $tapchain, "-s ! $macaddr", '-j DROP');
> }
>
> + if (defined($arpfilter)){
This is always defined because it starts out as an array ref (empty but
defined). You need to use `if (@$arpfilter) {` here.
(As with this currently it'll always jump to an empty -ARP chain
containing only the final `-j DROP` if no ipfilter-netX exists.)
> + my $arpchain = $tapchain."-ARP";
> + ruleset_addrule($ruleset, $tapchain, "-p ARP", "-j $arpchain");
> + ruleset_create_chain($ruleset, $arpchain);
> +
> + foreach my $ip (@{$arpfilter}) {
> + ruleset_addrule($ruleset, $arpchain, "-p ARP --arp-ip-src $ip", '-j RETURN');
I wish this could just use the actual ipset :-\
> + }
> + ruleset_addrule($ruleset, $arpchain, '', '-j DROP');
> + }
> +
> if (defined($options->{layer2_protocols})){
This hunk below seems unrelated? Should probably be a separate patch, or
is this related somehow?
> + my $protochain = $tapchain."-PROTO";
> + ruleset_addrule($ruleset, $tapchain, '', "-j $protochain");
> + ruleset_create_chain($ruleset, $protochain);
> +
> foreach my $proto (split(/,/, $options->{layer2_protocols})) {
> - ruleset_addrule($ruleset, $tapchain, "-p $proto", '-j ACCEPT');
> + ruleset_addrule($ruleset, $protochain, "-p $proto", '-j RETURN');
> }
> - ruleset_addrule($ruleset, $tapchain, '', "-j DROP");
> - } else {
> - ruleset_addrule($ruleset, $tapchain, '', '-j ACCEPT');
> + ruleset_addrule($ruleset, $protochain, '', '-j DROP');
> }
>
> + ruleset_addrule($ruleset, $tapchain, '', '-j ACCEPT');
> +
> ruleset_addrule($ruleset, 'PVEFW-FWBR-OUT', "-i $iface", "-j $tapchain");
> }
>
> --
> 2.11.0
More information about the pve-devel
mailing list