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 +

firewalld and the virtual network driver +

+

+ If firewalld 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. +

+

+ 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). +

+

The network filter driver

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..bcc4d69d85 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) { + + /* if the "libvirt" zone exists, then set it. If not, and + * if firewalld is using the nftables backend, then we + * need to log an error because the combination of + * nftables + default zone means that traffic cannot be + * forwarded (and even DHCP and DNS from guest to host + * will probably no be permitted by the default zone + */ + if (virFirewallDZoneExists("libvirt")) { + if (virFirewallDInterfaceSetZone(def->bridge, "libvirt") < 0) + goto cleanup; + } else { + unsigned long version; + int vresult = virFirewallDGetVersion(&version); + + if (vresult < 0) + goto cleanup; + + /* Support for nftables backend was added in firewalld + * 0.6.0. Support for rule priorities (required by the + * 'libvirt' zone, which should be installed by a + * libvirt package, *not* by firewalld) was not added + * until firewalld 0.7.0 (unless it was backported). + */ + if (version >= 6000 && + virFirewallDGetBackend() == VIR_FIREWALLD_BACKEND_NFTABLES) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld is set to use the nftables " + "backend, but the required firewalld " + "'libvirt' zone is missing. Either set " + "the firewalld backend to 'iptables', or " + "ensure that firewalld has a 'libvirt' " + "zone by upgrading firewalld to a " + "version supporting rule priorities " + "(0.7.0+) and/or rebuilding " + "libvirt with --with-firewalld-zone")); + goto cleanup; + } + } + } + fw = virFirewallNew(); virFirewallStartTransaction(fw, 0);