[libvirt] [PATCH v3 2/4] util/viriptables: add/remove rules that short-circuit masquerading
Laine Stump
laine at laine.org
Tue Sep 24 09:24:27 UTC 2013
On 09/23/2013 08:03 PM, Laszlo Ersek wrote:
> The functions
> - iptablesAddDontMasquerade(),
> - iptablesRemoveDontMasquerade()
> handle exceptions in the masquerading implemented in the POSTROUTING chain
> of the "nat" table. Such exceptions should be added as chronologically
> latest, logically top-most rules.
>
> The bridge driver will call these functions beginning with the next patch:
> some special destination IP addresses always refer to the local
> subnetwork, even though they don't match any practical subnetwork's
> netmask. Packets from virbrN targeting such IP addresses are never routed
> outwards, but the current rules treat them as non-virbrN-destined packets
> and masquerade them. This causes problems for some receivers on virbrN.
>
> Signed-off-by: Laszlo Ersek <lersek at redhat.com>
> ---
> v2->v3:
> - Rename iptables(Add|Remove)ForwardDontMasquerade to
> iptables(Add|Remove)DontMasquerade [Laine].
> - Pass (address, prefix) pairs as both source and destination parameters
> to these functions.
> - Introduce virPfxSocketAddr structure for simpler handling of said
> (address, prefix) pairs.
>
> src/util/viriptables.h | 11 +++++++
> src/util/viriptables.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
> src/libvirt_private.syms | 2 ++
> 3 files changed, 95 insertions(+)
>
> diff --git a/src/util/viriptables.h b/src/util/viriptables.h
> index 447f4a8..fcff5f8 100644
> --- a/src/util/viriptables.h
> +++ b/src/util/viriptables.h
> @@ -26,6 +26,11 @@
>
> # include "virsocketaddr.h"
>
> +typedef struct {
> + virSocketAddr addr;
> + unsigned int prefix;
> +} virPfxSocketAddr;
> +
I'm conflicted about whether or not it's really beneficial to have this
struct (is the setup really worth it just to save one arg?), but I
suppose it doesn't hurt anything, so I'll go along with it if nobody
else objects. It *does* make these functions' APIs inconsistent with the
other iptables functions that take a separate addr and prefix, though -
if we keep this then we should probably update the rest of the API to be
consistent (not in this patch though).
> int iptablesAddTcpInput (int family,
> const char *iface,
> int port);
> @@ -94,6 +99,12 @@ int iptablesRemoveForwardMasquerade (virSocketAddr *netaddr,
> virSocketAddrRangePtr addr,
> virPortRangePtr port,
> const char *protocol);
> +int iptablesAddDontMasquerade (const virPfxSocketAddr *src,
> + const char *physdev,
> + const virPfxSocketAddr *dst);
> +int iptablesRemoveDontMasquerade (const virPfxSocketAddr *src,
> + const char *physdev,
> + const virPfxSocketAddr *dst);
> int iptablesAddOutputFixUdpChecksum (const char *iface,
> int port);
> int iptablesRemoveOutputFixUdpChecksum (const char *iface,
> diff --git a/src/util/viriptables.c b/src/util/viriptables.c
> index 52e2bde..90fe900 100644
> --- a/src/util/viriptables.c
> +++ b/src/util/viriptables.c
> @@ -832,6 +832,88 @@ iptablesRemoveForwardMasquerade(virSocketAddr *netaddr,
> }
>
>
> +/* Don't masquerade traffic coming from the network associated with the bridge
> + * if said traffic targets @destaddr/@destprefix.
> + */
> +static int
> +iptablesDontMasquerade(const virPfxSocketAddr *src,
> + const char *physdev,
> + const virPfxSocketAddr *dst,
> + int action)
> +{
> + int ret = -1;
> + char *srcStr = NULL;
> + char *dstStr = NULL;
> + virCommandPtr cmd = NULL;
> +
> + if (!(srcStr = iptablesFormatNetwork(&src->addr, src->prefix)))
> + return -1;
> +
> + if (!(dstStr = iptablesFormatNetwork(&dst->addr, dst->prefix)))
> + goto cleanup;
> +
> + if (!VIR_SOCKET_ADDR_IS_FAMILY(&src->addr, AF_INET)) {
> + /* Higher level code *should* guaranteee it's impossible to get here. */
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Attempted to NAT '%s'. NAT is only supported for IPv4."),
> + srcStr);
> + goto cleanup;
> + }
Don't you need to do the same check for dst?
> +
> + cmd = iptablesCommandNew("nat", "POSTROUTING", AF_INET, action);
> +
> + if (physdev && physdev[0])
> + virCommandAddArgList(cmd, "--out-interface", physdev, NULL);
> +
> + virCommandAddArgList(cmd, "--source", srcStr, "--destination", dstStr,
> + "--jump", "RETURN", NULL);
> + ret = virCommandRun(cmd, NULL);
> +cleanup:
> + virCommandFree(cmd);
> + VIR_FREE(dstStr);
> + VIR_FREE(srcStr);
> + return ret;
> +}
> +
> +/**
> + * iptablesAddDontMasquerade:
> + * @src: the source network address and prefix
> + * @physdev: the physical output device or NULL
> + * @destaddr: the destination network address and prefix
> + *
> + * Add rules to the "nat" IP table to avoid masquerading from @src/srcprefix to
> + * @dst/dstprefix on @physdev.
> + *
> + * Returns 0 in case of success and -1 on failure.
> + */
> +int
> +iptablesAddDontMasquerade(const virPfxSocketAddr *src,
> + const char *physdev,
> + const virPfxSocketAddr *dst)
> +{
> + return iptablesDontMasquerade(src, physdev, dst, ADD);
> +}
> +
> +/**
> + * iptablesRemoveDontMasquerade:
> + * @src: the source network address and prefix
> + * @physdev: the physical output device or NULL
> + * @destaddr: the destination network address and prefix
> + *
> + * Remove rules from the "nat" IP table that prevent masquerading from
> + * @src/srcprefix to @dst/dstprefix on @physdev.
> + *
> + * Returns 0 in case of success and -1 on failure.
> + */
> +int
> +iptablesRemoveDontMasquerade(const virPfxSocketAddr *src,
> + const char *physdev,
> + const virPfxSocketAddr *dst)
> +{
> + return iptablesDontMasquerade(src, physdev, dst, REMOVE);
> +}
> +
> +
> static int
> iptablesOutputFixUdpChecksum(const char *iface,
> int port,
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 50e2f48..fb212ce 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1446,6 +1446,7 @@ virInitctlSetRunLevel;
>
>
> # util/viriptables.h
> +iptablesAddDontMasquerade;
> iptablesAddForwardAllowCross;
> iptablesAddForwardAllowIn;
> iptablesAddForwardAllowOut;
> @@ -1456,6 +1457,7 @@ iptablesAddForwardRejectOut;
> iptablesAddOutputFixUdpChecksum;
> iptablesAddTcpInput;
> iptablesAddUdpInput;
> +iptablesRemoveDontMasquerade;
> iptablesRemoveForwardAllowCross;
> iptablesRemoveForwardAllowIn;
> iptablesRemoveForwardAllowOut;
More information about the libvir-list
mailing list