network: allow configuring firewalld zone for virtual network bridge device

Since we're setting the zone anyway, it will be useful to allow
setting a different (custom) zone for each network. This will be done
by adding a "zone" attribute to the "bridge" element, e.g.:

   ...
   <bridge name='virbr0' zone='myzone'/>
   ...

If a zone is specified in the config and it can't be honored, this
will be an error.

Signed-off-by: Laine Stump <laine@laine.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Laine Stump 2019-01-09 16:51:31 -05:00
parent ae05211a36
commit 30a6f91686
9 changed files with 106 additions and 42 deletions

View File

@ -151,6 +151,11 @@ MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24</pre>
iptables rules regardless of which backend is in use by
firewalld.
</p>
<p>
NB: It is possible to manually set the firewalld zone for a
network's interface with the "zone" attribute of the network's
"bridge" element.
</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

View File

@ -152,6 +152,23 @@
<span class="since">Since 1.2.11, requires kernel 3.17 or
newer</span>
</p>
<p>
The optional <code>zone</code> attribute of
the <code>bridge</code> element is used to specify
the <a href="https://firewalld.org">firewalld</a>
zone for the bridge of a network with <code>forward</code>
mode of "nat", "route", "open", or one with
no <code>forward</code> specified. By default, the bridges
of all virtual networks with these forward modes are placed
in the firewalld zone named "libvirt", which permits
incoming DNS, DHCP, TFTP, and SSH to the host from guests on
the network. This behavior can be changed either by
modifying the libvirt zone (using firewalld management
tools), or by placing the network in a different zone (which
will also be managed using firewalld tools).
<span class="since">Since 5.1.0</span>
</p>
</dd>
<dt><code>mtu</code></dt>

View File

@ -279,6 +279,12 @@
</data>
</define>
<define name="zoneName">
<data type="string">
<param name="pattern">[a-zA-Z0-9_\-]+</param>
</data>
</define>
<define name="filePath">
<data type="string">
<param name="pattern">.+</param>

View File

@ -58,6 +58,12 @@
</attribute>
</optional>
<optional>
<attribute name="zone">
<ref name="zoneName"/>
</attribute>
</optional>
<optional>
<attribute name="stp">
<ref name="virOnOff"/>

View File

@ -203,6 +203,7 @@ virNetworkDefFree(virNetworkDefPtr def)
VIR_FREE(def->name);
VIR_FREE(def->bridge);
VIR_FREE(def->bridgeZone);
VIR_FREE(def->domain);
virNetworkForwardDefClear(&def->forward);
@ -1684,6 +1685,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
/* Parse bridge information */
def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
def->bridgeZone = virXPathString("string(./bridge[1]/@zone)", ctxt);
stp = virXPathString("string(./bridge[1]/@stp)", ctxt);
def->stp = (stp && STREQ(stp, "off")) ? false : true;
@ -1920,6 +1922,13 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->name);
goto error;
}
if (def->bridgeZone) {
virReportError(VIR_ERR_XML_ERROR,
_("bridge zone not allowed in %s mode (network '%s')"),
virNetworkForwardTypeToString(def->forward.type),
def->name);
goto error;
}
if (def->macTableManager) {
virReportError(VIR_ERR_XML_ERROR,
_("bridge macTableManager setting not allowed "
@ -1931,9 +1940,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
ATTRIBUTE_FALLTHROUGH;
case VIR_NETWORK_FORWARD_BRIDGE:
if (def->delay || stp) {
if (def->delay || stp || def->bridgeZone) {
virReportError(VIR_ERR_XML_ERROR,
_("bridge delay/stp options only allowed in "
_("bridge delay/stp/zone options only allowed in "
"route, nat, and isolated mode, not in %s "
"(network '%s')"),
virNetworkForwardTypeToString(def->forward.type),
@ -2508,6 +2517,7 @@ virNetworkDefFormatBuf(virBufferPtr buf,
if (hasbridge || def->bridge || def->macTableManager) {
virBufferAddLit(buf, "<bridge");
virBufferEscapeString(buf, " name='%s'", def->bridge);
virBufferEscapeString(buf, " zone='%s'", def->bridgeZone);
if (hasbridge)
virBufferAsprintf(buf, " stp='%s' delay='%ld'",
def->stp ? "on" : "off", def->delay);

View File

@ -235,6 +235,7 @@ struct _virNetworkDef {
int connections; /* # of guest interfaces connected to this network */
char *bridge; /* Name of bridge device */
char *bridgeZone; /* name of firewalld zone for bridge */
int macTableManager; /* enum virNetworkBridgeMACTableManager */
char *domain;
int domainLocalOnly; /* enum virTristateBool: yes disables dns forwarding */

View File

@ -671,6 +671,24 @@ int networkAddFirewallRules(virNetworkDefPtr def)
virFirewallPtr fw = NULL;
int ret = -1;
if (def->bridgeZone) {
/* if a firewalld zone has been specified, fail/log an error
* if we can't honor it
*/
if (virFirewallDIsRegistered() < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("zone %s requested for network %s "
"but firewalld is not active"),
def->bridgeZone, def->name);
goto cleanup;
}
if (virFirewallDInterfaceSetZone(def->bridge, def->bridgeZone) < 0)
goto cleanup;
} else {
/* 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
@ -717,6 +735,7 @@ int networkAddFirewallRules(virNetworkDefPtr def)
}
}
}
}
fw = virFirewallNew();

View File

@ -1,7 +1,7 @@
<network>
<name>local</name>
<uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
<bridge name="virbr1"/>
<bridge name="virbr1" zone="myzone"/>
<mac address='12:34:56:78:9A:BC'/>
<forward mode="route" dev="eth1"/>
<ip address="192.168.122.1" netmask="255.255.255.0">

View File

@ -4,7 +4,7 @@
<forward dev='eth1' mode='route'>
<interface dev='eth1'/>
</forward>
<bridge name='virbr1' stp='on' delay='0'/>
<bridge name='virbr1' zone='myzone' stp='on' delay='0'/>
<mac address='12:34:56:78:9a:bc'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
</ip>