[libvirt] [RFC PATCH] network: add an option to disable dnsmasq's bind-dynamic

When building vlans on top of veth networks, dnsmasq doesn't catch DNS requests on the vlans interfaces. Allowing to disable the bind-dynamic helps this use case. --- src/conf/network_conf.c | 12 ++++++++++++ src/conf/network_conf.h | 1 + src/network/bridge_driver.c | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index f4a9df0..63e26e1 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1987,6 +1987,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) xmlNodePtr forwardNode = NULL; char *ipv6nogwStr = NULL; char *trustGuestRxFilters = NULL; + char *binddynamicStr = NULL; xmlNodePtr save = ctxt->node; xmlNodePtr bandwidthNode = NULL; xmlNodePtr vlanNode; @@ -2049,6 +2050,16 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) VIR_FREE(trustGuestRxFilters); } + /* Default for binddynamic is on */ + def->binddynamic = true; + binddynamicStr = virXPathString("string(./@binddynamic)", ctxt); + if (binddynamicStr) { + if (STRNEQ(binddynamicStr, "no")) { + def->binddynamic = false; + } + VIR_FREE(binddynamicStr); + } + /* Parse network domain information */ def->domain = virXPathString("string(./domain[1]/@name)", ctxt); tmp = virXPathString("string(./domain[1]/@localOnly)", ctxt); @@ -2326,6 +2337,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) VIR_FREE(ipNodes); VIR_FREE(portGroupNodes); VIR_FREE(ipv6nogwStr); + VIR_FREE(binddynamicStr); VIR_FREE(trustGuestRxFilters); ctxt->node = save; return NULL; diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index f69d999..163581e 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -253,6 +253,7 @@ struct _virNetworkDef { virNetDevBandwidthPtr bandwidth; virNetDevVlan vlan; int trustGuestRxFilters; /* enum virTristateBool */ + bool binddynamic; /* to force off bind_dynamic option of dnsmasq */ }; typedef struct _virNetworkObj virNetworkObj; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index d195085..5dddc4b 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -988,7 +988,8 @@ networkDnsmasqConfContents(virNetworkObjPtr network, /* dnsmasq will *always* listen on localhost unless told otherwise */ virBufferAddLit(&configbuf, "except-interface=lo\n"); - if (dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)) { + if (network->def->binddynamic && + dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)) { /* using --bind-dynamic with only --interface (no * --listen-address) prevents dnsmasq from responding to dns * queries that arrive on some interface other than our bridge -- 2.1.4

On 06.05.2015 15:29, Cédric Bosdonnat wrote:
When building vlans on top of veth networks, dnsmasq doesn't catch DNS requests on the vlans interfaces. Allowing to disable the bind-dynamic helps this use case. ---
src/conf/network_conf.c | 12 ++++++++++++ src/conf/network_conf.h | 1 + src/network/bridge_driver.c | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-)
I know this is patch just to demonstrate the idea, so I will not point out obvious (e.g. missing RNG schema and documentation).
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index f4a9df0..63e26e1 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1987,6 +1987,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) xmlNodePtr forwardNode = NULL; char *ipv6nogwStr = NULL; char *trustGuestRxFilters = NULL; + char *binddynamicStr = NULL; xmlNodePtr save = ctxt->node; xmlNodePtr bandwidthNode = NULL; xmlNodePtr vlanNode; @@ -2049,6 +2050,16 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) VIR_FREE(trustGuestRxFilters); }
+ /* Default for binddynamic is on */ + def->binddynamic = true; + binddynamicStr = virXPathString("string(./@binddynamic)", ctxt); + if (binddynamicStr) { + if (STRNEQ(binddynamicStr, "no")) {
s/STRNEQ/STREQ/ or even better virTristateSwitchTypeFromString(). Moreover, I'm curious if we can come up with not so dnsmasq specific attribute name. But that's just cosmetics.
+ def->binddynamic = false; + } + VIR_FREE(binddynamicStr); + } + /* Parse network domain information */ def->domain = virXPathString("string(./domain[1]/@name)", ctxt); tmp = virXPathString("string(./domain[1]/@localOnly)", ctxt); @@ -2326,6 +2337,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) VIR_FREE(ipNodes); VIR_FREE(portGroupNodes); VIR_FREE(ipv6nogwStr); + VIR_FREE(binddynamicStr); VIR_FREE(trustGuestRxFilters); ctxt->node = save; return NULL; diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index f69d999..163581e 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -253,6 +253,7 @@ struct _virNetworkDef { virNetDevBandwidthPtr bandwidth; virNetDevVlan vlan; int trustGuestRxFilters; /* enum virTristateBool */ + bool binddynamic; /* to force off bind_dynamic option of dnsmasq */ };
typedef struct _virNetworkObj virNetworkObj; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index d195085..5dddc4b 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -988,7 +988,8 @@ networkDnsmasqConfContents(virNetworkObjPtr network, /* dnsmasq will *always* listen on localhost unless told otherwise */ virBufferAddLit(&configbuf, "except-interface=lo\n");
- if (dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)) { + if (network->def->binddynamic && + dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)) {
I think the logic should be slightly different, when specifically requested in XML but not provided by dnsmasq an error must be thrown.
/* using --bind-dynamic with only --interface (no * --listen-address) prevents dnsmasq from responding to dns * queries that arrive on some interface other than our bridge
Since this is not the first request I see to disable dynamic bind I think it's really needed. I'm too lazy to dig out the other requests from history (maybe it was a bugzilla I saw, or an IRC chat, or here on the list, ...). So, ACK to the idea. Michal

On 05/07/2015 05:58 AM, Michal Privoznik wrote:
On 06.05.2015 15:29, Cédric Bosdonnat wrote:
When building vlans on top of veth networks, dnsmasq doesn't catch DNS requests on the vlans interfaces. Allowing to disable the bind-dynamic helps this use case. ---
/* using --bind-dynamic with only --interface (no * --listen-address) prevents dnsmasq from responding to dns * queries that arrive on some interface other than our bridge
Since this is not the first request I see to disable dynamic bind I think it's really needed. I'm too lazy to dig out the other requests from history (maybe it was a bugzilla I saw, or an IRC chat, or here on the list, ...).
The problem is that we started using --bind-dynamic in response to CVE-2012-3411: https://bugzilla.redhat.com/show_bug.cgi?id=833033 For more history, look at commit 753ff83a (when --bind-dynamic was originally added, resolving the CVE), d66eb786 (which re-removed listening on localhost, accidentally removed in the previous commit), then finally commit 4b31da34 (which made a similar fix available for older dnsmasq versions that don't have bind-dynamic and don't require it). I think using --bind-dynamic is too big a stick for this problem - instead maybe we should see if there's a reasonable way to update the interface list to add and remove the veth interfaces as the lxc domains are started and stopped (the complication here is that dnsmasq would probably need to be restarted after changing the interface list, since it drops all capabilities and changes to user "nobody" immediately after its initialization. I also remember somebody asking about the behavior that is caused by bind-dynamic, but can't find it right now via google or in my irc logs. So likely it would be good to add such an option anyway, just not named "binddynamic" (the name of that option doesn't make any sense even in the context of dnsmasq! :-P). Instead, it should be called something like "publiclyAccessible" (that's a bit long, but you get the idea), so: <dns publiclyAccessible='yes'/> Again, though, I don't think users of LXC domains should be forced to throw such a big switch just to get DNS working for their guests.
participants (3)
-
Cédric Bosdonnat
-
Laine Stump
-
Michal Privoznik