[libvirt] [PATCH v2 5/7] network: set firewalld zone of bridges to "libvirt" zone when appropriate
Laine Stump
laine at laine.org
Fri Feb 1 15:10:21 UTC 2019
On 2/1/19 8:24 AM, Daniel P. Berrangé wrote:
> On Thu, Jan 31, 2019 at 08:24:56PM -0500, Laine Stump wrote:
>> From: Laine Stump <laine at redhat.com>
>>
>> This patch restores broken guest network connectivity after a host
>> firewalld is switched to using an nftables backend. It does this by
>> adding libvirt networks' bridge interfaces to the new "libvirt" zone
>> in firewalld.
>>
>> After this patch, the bridge interface of any network created by
>> libvirt (when firewalld is active) will be added to the firewalld
>> zone called "libvirt" if it exists (regardless of the firewalld
>> backend setting). This behavior does *not* depend on whether or not
>> libvirt has installed the libvirt zone file (set with
>> "--with[out]-firewalld-zone" during the configure phase of the package
>> build).
>>
>> If the libvirt zone doesn't exist (either because the package was
>> configured to not install it, or possibly it was installed, but
>> firewalld doesn't support rule priorities, resulting in a parse
>> error), the bridge will remain in firewalld's default zone, which
>> could be innocuous (in the case that the firewalld backend is
>> iptables, guest networking will still function properly with the
>> bridge in the default zone), or it could be disastrous (if the
>> firewalld backend is nftables, we can be assured that guest networking
>> will fail). In order to be unobtrusive in the former case, and
>> informative in the latter, when the libvirt zone doesn't exist we
>> then check the firewalld version to see if it's new enough to support
>> the nftables backend, and then if the backend is actually set to
>> nftables, before logging an error (and failing the net-start
>> operation, since the network couldn't possibly work anyway).
>>
>> When the libvirt zone is used, network behavior is *slightly*
>> different from behavior of previous libvirt. In the past, libvirt
>> network behavior would be affected by the configuration of firewalld's
>> default zone (usually "public"), but now it is affected only by the
>> "libvirt" zone), and thus almost surely warrants a release note for
>> any distro upgrading to libvirt 5.1 or above. Although it's
>> unfortunate that we have to deal with a mandatory behavior change, the
>> architecture of multiple hooks makes it impossible to *not* change
>> behavior in some way, and the new behavior is arguably better (since
>> it will now be possible to manage access to the host from virtual
>> machines vs from public interfaces separately).
>>
>> Resolves: https://bugzilla.redhat.com/1638342
>> Creates-and-Resolves: https://bugzilla.redhat.com/1650320
>> Signed-off-by: Laine Stump <laine at laine.org>
>> ---
>>
>> NB: I had considered that it might be useful to cache the results of
>> checking the list of active zones, the firewalld version, or the
>> firewalld backend, but in my tests of restarting libvirtd with 100
>> active networks, the full startup time (from the beginning of
>> "systemctl restart libvirtd.service" until successful return from a
>> subsequent "virsh list") showed 42 seconds and a bit regardless of
>> whether or not I made those checks. This tells me that the amount of
>> time to be saved by caching the results of a single call vs calling
>> once for each network are insignificant relative to everything else
>> that is being done. Because any cached values would need to be stored
>> in the network driver state object, and thus require acquiring the
>> driver-wide lock to update at potentially very different times
>> (e.g. in the response to a dbus message informing us that firewalld
>> was restarted, as well as while starting a new network from an API
>> call) I consider the chance of a bug in my code causing an obscure
>> deadlock sometime in the future to be a much greater concern than
>> maybe saving 1/10th of a second out of 42 (and lock contention might
>> eliminate the gain anyway(), so I have left the code to retrieve the
>> list of zones once for each network start.
>>
>> Changes in V2:
>>
>> * split off from Patch 5. This patch only sets the libvirt zone if it
>> exists (and attempts to somewhat document the behavior in
>> firewall.html), it doesn't install the libvirt zone.
>>
>> * check for existence of libvirt zone before attempting to set it.
>>
>> * if libvirt zone doesn't exist, only log an error in the case that
>> the firewalld version is new enough to have an nftables backend, and
>> the backend is actually set to nftables.
>>
>>
>> docs/firewall.html.in | 33 +++++++++++++++++++++
>> src/network/bridge_driver_linux.c | 48 +++++++++++++++++++++++++++++++
>> 2 files changed, 81 insertions(+)
>>
>> diff --git a/docs/firewall.html.in b/docs/firewall.html.in
>> index 0a50687c26..5d584e582e 100644
>> --- a/docs/firewall.html.in
>> +++ b/docs/firewall.html.in
>> @@ -129,6 +129,39 @@ MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24</pre>
>> </li>
>> </ul>
>>
>> + <h3><a id="fw-firewalld-and-virtual-network-driver">firewalld and the virtual network driver</a>
>> + </h3>
>> + <p>
>> + If <a href="https://firewalld.org">firewalld</a> is active on
>> + the host, libvirt will attempt to place the bridge interface of
>> + a libvirt virtual network into the firewalld zone named
>> + "libvirt" (thus making all guest->host traffic on that network
>> + subject to the rules of the "libvirt" zone). This is done
>> + because, if firewalld is using its nftables backend (available
>> + since firewalld 0.6.0) the default firewalld zone (which would
>> + be used if libvirt didn't explicitly set the zone) prevents
>> + forwarding traffic from guests through the bridge, as well as
>> + preventing DHCP, DNS, and most other traffic from guests to
>> + host. The zone named "libvirt" is installed into the firewalld
>> + configuration by libvirt (not by firewalld), and allows
>> + forwarded traffic through the bridge as well as DHCP, DNS, TFTP,
>> + and SSH traffic to the host - depending on firewalld's backend
>> + this will be implemented via either iptables or nftables
>> + rules. libvirt's own rules outlined above will *always* be
>> + iptables rules regardless of which backend is in use by
>> + firewalld.
>> + </p>
>> + <p>
>> + NB: Prior to libvirt 5.1.0, the firewalld "libvirt" zone did not
>> + exist, and prior to firewalld 0.7.0 a feature crucial to making
>> + the "libvirt" zone operate properly (rich rule priority
>> + settings) was not implemented in firewalld. In cases where one
>> + or the other of the two packages is missing the necessary
>> + functionality, it's still possible to have functional guest
>> + networking by setting the firewalld backend to "iptables" (in
>> + firewalld prior to 0.6.0, this was the only backend available).
>> + </p>
>> +
>> <h3><a id="fw-network-filter-driver">The network filter driver</a>
>> </h3>
>> <p>This driver provides a fully configurable network filtering capability
>> diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
>> index e5e48c90f1..9d2e6877ae 100644
>> --- a/src/network/bridge_driver_linux.c
>> +++ b/src/network/bridge_driver_linux.c
>> @@ -27,6 +27,7 @@
>> #include "virstring.h"
>> #include "virlog.h"
>> #include "virfirewall.h"
>> +#include "virfirewalld.h"
>>
>> #define VIR_FROM_THIS VIR_FROM_NONE
>>
>> @@ -670,6 +671,53 @@ int networkAddFirewallRules(virNetworkDefPtr def)
>> virFirewallPtr fw = NULL;
>> int ret = -1;
>>
>> + /* if firewalld is active, try to set the "libvirt" zone. This is
>> + * desirable (for consistency) if firewalld is using the iptables
>> + * backend, but is necessary (for basic network connectivity) if
>> + * firewalld is using the nftables backend
>> + */
>> + if (virFirewallDIsRegistered() == 0) {
>
> The indentation here is odd - its 4 spaces too much for the
> surrounding context.
I did that to eliminate the pointless churn in the next patch, which
would have just indented all this code by 4 spaces, thus making it more
difficult to see what exactly was changed (you would have to either look
through the diff line by line, or apply it and use diff -w).
So should I still reindent? (I guess now that you've seen the trimmed
down patches, this version has already done its job, so there's not much
downside unless someone comes along 5 years from now and is interested
in exactly the next commit, which seems unlikely...)
>
> With that fixed
>
> Reviewed-by: Daniel P. Berrangé <berrange at redhat.com>
>
> Regards,
> Daniel
More information about the libvir-list
mailing list