[libvirt] [PATCHv2 0/2] disable default gateway in IPv6 RA for isolated networks

In case of DHCPv6 in isolated network, we start dnsmasq which sends Router Advertisements (RA). If RA containts no gateway then the link-local address of the source of RA is considered a gateway (and guest installs a corresponding default route). If a guest has two network interfaces (public and isolated network) and the user installs a default route through "public" interface, the guest will have something like default via fe80::ffff:1:1 dev eth2 metric 1024 default via fe80::5054:ff:fe0a:d808 dev eth3 proto ra metric 1024 expires 1789sec RA route metric may vary, and it is preferred. The validity of default route is controlled by "default [route] lifetime" field in RA. If it is 0, then the default gateway announced is considered invalid, and no default route is installed into guest. dnsmasq 2.67+ supports "ra-param=<interface>,<RA interval>,<default lifetime>" option. We can pass "ra-param=*,0,0" (here, RA_interval=0 means default) to disable default gateway in RA. This patchset adds detection for "ra-param" in dnsmasq and sets "ra-param=*,0,0" for isolated network if dnsmasq supports it. Maxim Perevedentsev (2): Fix message about dnsmasq BINDTODEVICE capability. dnsmasq: disable IPv6 default gateway in RA for isolated networks src/network/bridge_driver.c | 7 +++++++ src/util/virdnsmasq.c | 8 ++++++-- src/util/virdnsmasq.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) -- 1.8.3.1

--- src/util/virdnsmasq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c index da3e603..d253f44 100644 --- a/src/util/virdnsmasq.c +++ b/src/util/virdnsmasq.c @@ -693,7 +693,7 @@ dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf) (int)caps->version / 1000000, (int)(caps->version % 1000000) / 1000, dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT ", - dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT "); + dnsmasqCapsGet(caps, DNSMASQ_CAPS_BINDTODEVICE) ? "" : "NOT "); return 0; fail: -- 1.8.3.1

On 07/01/2016 07:50 AM, Maxim Perevedentsev wrote:
--- src/util/virdnsmasq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c index da3e603..d253f44 100644 --- a/src/util/virdnsmasq.c +++ b/src/util/virdnsmasq.c @@ -693,7 +693,7 @@ dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf) (int)caps->version / 1000000, (int)(caps->version % 1000000) / 1000, dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT ", - dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT "); + dnsmasqCapsGet(caps, DNSMASQ_CAPS_BINDTODEVICE) ? "" : "NOT "); return 0;
fail:
ACK. (in more ways than one, ie also "ACK! How did I not see that when I wrote it!?!??")

IPv6 RA always contains an implicit default route via the link-local address of the source of RA. This forces the guest to install a route via isolated network, which may disturb the guest's networking in case of multiple interfaces. More info in 013427e6e733f7a662f4e8a9c11f7dad4cd65e3f. The validity of this route is controlled by "default [route] lifetime" field of RA. If the lifetime is set to 0 seconds, then no route is installed by receiver. dnsmasq 2.67+ supports "ra-param=<interface>,<RA interval>,<default lifetime>" option. We pass "ra-param=*,0,0" (here, RA_interval=0 means default) to disable default gateway in RA for isolated networks. --- src/network/bridge_driver.c | 7 +++++++ src/util/virdnsmasq.c | 8 ++++++-- src/util/virdnsmasq.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 0221a38..5020266 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1047,10 +1047,17 @@ networkDnsmasqConfContents(virNetworkObjPtr network, * requests are forwarded on to the dns server listed in the * host's /etc/resolv.conf (since this could be used as a channel * to build a connection to the outside). + * IPv6 RA always contains an implicit default route + * via the sender's link-local address. The only thing we can do + * is set the lifetime of this route to 0, i.e. disable it. */ if (network->def->forward.type == VIR_NETWORK_FORWARD_NONE) { virBufferAddLit(&configbuf, "dhcp-option=3\n" "no-resolv\n"); + if (dnsmasqCapsGet(caps, DNSMASQ_CAPS_RA_PARAM)) { + /* interface=* (any), interval=0 (default), lifetime=0 (seconds) */ + virBufferAddLit(&configbuf, "ra-param=*,0,0\n"); + } } for (i = 0; i < dns->ntxts; i++) { diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c index d253f44..b72b56e 100644 --- a/src/util/virdnsmasq.c +++ b/src/util/virdnsmasq.c @@ -688,12 +688,16 @@ dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf) if (strstr(buf, "--bind-interfaces with SO_BINDTODEVICE")) dnsmasqCapsSet(caps, DNSMASQ_CAPS_BINDTODEVICE); + if (strstr(buf, "--ra-param")) + dnsmasqCapsSet(caps, DNSMASQ_CAPS_RA_PARAM); + VIR_INFO("dnsmasq version is %d.%d, --bind-dynamic is %spresent, " - "SO_BINDTODEVICE is %sin use", + "SO_BINDTODEVICE is %sin use, --ra-param is %spresent", (int)caps->version / 1000000, (int)(caps->version % 1000000) / 1000, dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT ", - dnsmasqCapsGet(caps, DNSMASQ_CAPS_BINDTODEVICE) ? "" : "NOT "); + dnsmasqCapsGet(caps, DNSMASQ_CAPS_BINDTODEVICE) ? "" : "NOT ", + dnsmasqCapsGet(caps, DNSMASQ_CAPS_RA_PARAM) ? "" : "NOT "); return 0; fail: diff --git a/src/util/virdnsmasq.h b/src/util/virdnsmasq.h index ed560da..f47bea3 100644 --- a/src/util/virdnsmasq.h +++ b/src/util/virdnsmasq.h @@ -71,6 +71,7 @@ typedef struct typedef enum { DNSMASQ_CAPS_BIND_DYNAMIC = 0, /* support for --bind-dynamic */ DNSMASQ_CAPS_BINDTODEVICE = 1, /* uses SO_BINDTODEVICE for --bind-interfaces */ + DNSMASQ_CAPS_RA_PARAM = 2, /* support for --ra-param */ DNSMASQ_CAPS_LAST, /* this must always be the last item */ } dnsmasqCapsFlags; -- 1.8.3.1

On 07/01/2016 07:50 AM, Maxim Perevedentsev wrote:
IPv6 RA always contains an implicit default route via the link-local address of the source of RA. This forces the guest to install a route via isolated network, which may disturb the guest's networking in case of multiple interfaces. More info in 013427e6e733f7a662f4e8a9c11f7dad4cd65e3f.
The validity of this route is controlled by "default [route] lifetime" field of RA. If the lifetime is set to 0 seconds, then no route is installed by receiver.
dnsmasq 2.67+ supports "ra-param=<interface>,<RA interval>,<default lifetime>" option. We pass "ra-param=*,0,0" (here, RA_interval=0 means default) to disable default gateway in RA for isolated networks.
ACK (assuming that you've run make syntax-check and make check.) Thanks again for spending the time to investigate this!

On 01.07.2016 14:50, Maxim Perevedentsev wrote:
In case of DHCPv6 in isolated network, we start dnsmasq which sends Router Advertisements (RA). If RA containts no gateway then the link-local address of the source of RA is considered a gateway (and guest installs a corresponding default route).
If a guest has two network interfaces (public and isolated network) and the user installs a default route through "public" interface, the guest will have something like
default via fe80::ffff:1:1 dev eth2 metric 1024 default via fe80::5054:ff:fe0a:d808 dev eth3 proto ra metric 1024 expires 1789sec
RA route metric may vary, and it is preferred. The validity of default route is controlled by "default [route] lifetime" field in RA. If it is 0, then the default gateway announced is considered invalid, and no default route is installed into guest.
dnsmasq 2.67+ supports "ra-param=<interface>,<RA interval>,<default lifetime>" option. We can pass "ra-param=*,0,0" (here, RA_interval=0 means default) to disable default gateway in RA.
This patchset adds detection for "ra-param" in dnsmasq and sets "ra-param=*,0,0" for isolated network if dnsmasq supports it.
Maxim Perevedentsev (2): Fix message about dnsmasq BINDTODEVICE capability. dnsmasq: disable IPv6 default gateway in RA for isolated networks
src/network/bridge_driver.c | 7 +++++++ src/util/virdnsmasq.c | 8 ++++++-- src/util/virdnsmasq.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-)
-- 1.8.3.1
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Pushed now. Thanks! Maxim
participants (3)
-
Laine Stump
-
Maxim Nestratov
-
Maxim Perevedentsev