[libvirt] [PATCH v4 2/2] bridge driver: don't masquerade local subnet broadcast/multicast packets

Laszlo Ersek lersek at redhat.com
Wed Sep 25 11:03:37 UTC 2013


On 09/25/13 12:54, Laine Stump wrote:
> On 09/25/2013 06:45 AM, Laszlo Ersek wrote:
>> Packets sent by guests on virbrN, *or* by dnsmasq on the same, to
>> - 255.255.255.255/32 (netmask-independent local network broadcast
>>   address), or to
>> - 224.0.0.0/24 (local subnetwork multicast range)
>> are never forwarded, hence it is not necessary to masquerade them.
>>
>> In fact we must not masquerade them: translating their source addresses or
>> source ports (where applicable) may confuse receivers on virbrN.
>>
>> One example is the DHCP client in OVMF (= UEFI firmware for virtual
>> machines):
>>
>>   http://thread.gmane.org/gmane.comp.bios.tianocore.devel/1506/focus=2640
>>
>> It expects DHCP replies to arrive from remote source port 67. Even though
>> dnsmasq conforms to that, the destination address (255.255.255.255) and
>> the source address (eg. 192.168.122.1) in the reply allow the UDP
>> masquerading rule to match, which rewrites the source port to or above
>> 1024. This prevents the DHCP client in OVMF from accepting the packet.
>>
>> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=709418
>>
>> Signed-off-by: Laszlo Ersek <lersek at redhat.com>
>> ---
>>  v2->v4:
>>  - Rename iptables(Add|Remove)ForwardDontMasquerade to
>>           iptables(Add|Remove)DontMasquerade [Laine].
>>
>>  src/network/bridge_driver_linux.c | 70 ++++++++++++++++++++++++++++++++++++---
>>  1 file changed, 66 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
>> index 80430a8..066779a 100644
>> --- a/src/network/bridge_driver_linux.c
>> +++ b/src/network/bridge_driver_linux.c
>> @@ -127,6 +127,9 @@ out:
>>      return ret;
>>  }
>>  
>> +static const char networkLocalMulticast[] = "224.0.0.0/24";
>> +static const char networkLocalBroadcast[] = "255.255.255.255/32";
>> +
>>  int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
>>                                          virNetworkIpDefPtr ipdef)
>>  {
>> @@ -167,11 +170,20 @@ int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
>>      /*
>>       * Enable masquerading.
>>       *
>> -     * We need to end up with 3 rules in the table in this order
>> +     * We need to end up with 5 rules in the table in this order
>>       *
>> -     *  1. protocol=tcp with sport mapping restriction
>> -     *  2. protocol=udp with sport mapping restriction
>> -     *  3. generic any protocol
>> +     *  1. do not masquerade packets targeting 224.0.0.0/24
>> +     *  2. do not masquerade packets targeting 255.255.255.255/32
>> +     *  3. masquerade protocol=tcp with sport mapping restriction
>> +     *  4. masquerade protocol=udp with sport mapping restriction
>> +     *  5. generic, masquerade any protocol
>> +     *
>> +     * 224.0.0.0/24 is the local network multicast range. Packets are not
>> +     * forwarded outside.
>> +     *
>> +     * 255.255.255.255/32 is the broadcast address of any local network. Again,
>> +     * such packets are never forwarded, but strict DHCP clients don't accept
>> +     * DHCP replies with changed source ports.
>>       *
>>       * The sport mappings are required, because default IPtables
>>       * MASQUERADE maintain port numbers unchanged where possible.
>> @@ -238,8 +250,50 @@ int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
>>          goto masqerr5;
>>      }
>>  
>> +    /* exempt local network broadcast address as destination */
>> +    if (iptablesAddDontMasquerade(&ipdef->address,
>> +                                  prefix,
>> +                                  forwardIf,
>> +                                  networkLocalBroadcast) < 0) {
>> +        if (forwardIf)
>> +            virReportError(VIR_ERR_SYSTEM_ERROR,
>> +                           _("failed to add iptables rule to prevent local broadcast masquerading on %s"),
>> +                           forwardIf);
>> +        else
>> +            virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
>> +                           _("failed to add iptables rule to prevent local broadcast masquerading"));
>> +        goto masqerr6;
>> +    }
>> +
>> +    /* exempt local multicast range as destination */
>> +    if (iptablesAddDontMasquerade(&ipdef->address,
>> +                                  prefix,
>> +                                  forwardIf,
>> +                                  networkLocalMulticast) < 0) {
>> +        if (forwardIf)
>> +            virReportError(VIR_ERR_SYSTEM_ERROR,
>> +                           _("failed to add iptables rule to prevent local multicast masquerading on %s"),
>> +                           forwardIf);
>> +        else
>> +            virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
>> +                           _("failed to add iptables rule to prevent local multicast masquerading"));
>> +        goto masqerr7;
>> +    }
>> +
>>      return 0;
>>  
>> + masqerr7:
>> +    iptablesRemoveDontMasquerade(&ipdef->address,
>> +                                 prefix,
>> +                                 forwardIf,
>> +                                 networkLocalBroadcast);
>> + masqerr6:
>> +    iptablesRemoveForwardMasquerade(&ipdef->address,
>> +                                    prefix,
>> +                                    forwardIf,
>> +                                    &network->def->forward.addr,
>> +                                    &network->def->forward.port,
>> +                                    "tcp");
>>   masqerr5:
>>      iptablesRemoveForwardMasquerade(&ipdef->address,
>>                                      prefix,
>> @@ -275,6 +329,14 @@ void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
>>      const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
>>  
>>      if (prefix >= 0) {
>> +        iptablesRemoveDontMasquerade(&ipdef->address,
>> +                                     prefix,
>> +                                     forwardIf,
>> +                                     networkLocalMulticast);
>> +        iptablesRemoveDontMasquerade(&ipdef->address,
>> +                                     prefix,
>> +                                     forwardIf,
>> +                                     networkLocalBroadcast);
>>          iptablesRemoveForwardMasquerade(&ipdef->address,
>>                                          prefix,
>>                                          forwardIf,
> 
> ACK. I'll push both patches as soon as I've done a sanity build locally.
> 
> Thanks for putting up with the nit-picking and false direction.

I think your comments have all been to the point -- I never had the
impression of nit-picking.

Thank you very much!
Laszlo




More information about the libvir-list mailing list