Let users set the port range to be used for forward mode NAT: ... <forward mode='nat'> <nat> <port start='1024' end='65535'/> </nat> </forward> ... Signed-off-by: Natanael Copa <ncopa@xxxxxxxxxxxxxxx> --- docs/formatnetwork.html.in | 15 ++++++++++++-- src/conf/network_conf.c | 50 +++++++++++++++++++++++++++++++++++++++++---- src/conf/network_conf.h | 3 ++- src/network/bridge_driver.c | 16 +++++++++++++++ src/util/viriptables.c | 39 +++++++++++++++++++++++++++-------- src/util/viriptables.h | 4 ++++ 6 files changed, 111 insertions(+), 16 deletions(-) diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index 608fce1..381de41 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -138,7 +138,8 @@ 0.4.2</span> <p><span class="since">Since 1.0.3</span> it is possible to - specify the public IPv4 address to be used for the NAT by using + specify the public IPv4 address(es) and ports to be used for + the NAT. A single public address can be specified with the the <code><nat></code> subelement and attribute <code>address</code>: <pre> @@ -160,7 +161,17 @@ </forward> ... </pre> - + The port range to be used for the <code><nat></code> can + be set via the subelement <code><port></code>: + <pre> +... + <forward mode='nat'> + <nat> + <port start='500' end='1000'/> + </nat> + </forward> +... + </pre> </p> </dd> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index fb57b70..1d1dfd3 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1332,7 +1332,8 @@ virNetworkForwardNatDefParseXML(const char *networkName, { int ret = -1; xmlNodePtr *natAddrNodes = NULL; - int nNatAddrs; + xmlNodePtr *natPortNodes = NULL; + int nNatAddrs, nNatPorts; char *addr_start = NULL; char *addr_end = NULL; xmlNodePtr save = ctxt->node; @@ -1392,6 +1393,36 @@ virNetworkForwardNatDefParseXML(const char *networkName, goto cleanup; } + /* ports for SNAT and MASQUERADE */ + nNatPorts = virXPathNodeSet("./port", ctxt, &natPortNodes); + if (nNatPorts < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid <port> element found in <forward> of " + "network %s"), networkName); + goto cleanup; + } else if (nNatPorts > 1) { + virReportError(VIR_ERR_XML_ERROR, + _("Only one <port> element is allowed in <nat> in " + "<forward> in network %s"), networkName); + goto cleanup; + } else if (nNatPorts == 1) { + if (virXPathUInt("string(./port[1]/@start)", ctxt, &def->port_start) < 0 + || def->port_start > 65535) { + + virReportError(VIR_ERR_XML_DETAIL, + _("Missing or invalid 'start' attribute in <port> " + "in <nat> in <forward> in network %s"), + networkName); + goto cleanup; + } + if (virXPathUInt("string(./port[1]/@end)", ctxt, &def->port_end) < 0 + || def->port_end > 65535 || def->port_end < def->port_start) { + virReportError(VIR_ERR_XML_DETAIL, + _("Missing or invalid 'end' attribute in <port> in " + "<nat> in <forward> in network %s"), networkName); + goto cleanup; + } + } ret = 0; cleanup: @@ -2181,6 +2212,7 @@ virNatDefFormat(virBufferPtr buf, char *addr_start = NULL; char *addr_end = NULL; int ret = -1; + int longdef; if (VIR_SOCKET_ADDR_VALID(&fwd->addr_start)) { addr_start = virSocketAddrFormat(&fwd->addr_start); @@ -2194,14 +2226,15 @@ virNatDefFormat(virBufferPtr buf, goto cleanup; } - if (!addr_end && !addr_start) + longdef = addr_end || fwd->port_start || fwd->port_end; + if (!longdef && !addr_start) return 0; virBufferAddLit(buf, "<nat"); if (addr_start && !addr_end) virBufferAsprintf(buf, " address='%s'", addr_start); - if (!addr_end) { + if (!longdef) { virBufferAsprintf(buf, "/>\n"); ret = 0; goto cleanup; @@ -2214,6 +2247,13 @@ virNatDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "<address start='%s' end='%s'/>\n", addr_start, addr_end); + if (fwd->port_start || fwd->port_end) { + virBufferAsprintf(buf, "<port start='%d'", fwd->port_start); + if (fwd->port_end) + virBufferAsprintf(buf, " end='%d'", fwd->port_end); + virBufferAsprintf(buf, "/>\n"); + } + virBufferAdjustIndent(buf, -2); virBufferAsprintf(buf, "</nat>\n"); ret = 0; @@ -2270,7 +2310,9 @@ virNetworkDefFormatInternal(virBufferPtr buf, } shortforward = !(def->forward.nifs || def->forward.npfs || VIR_SOCKET_ADDR_VALID(&def->forward.addr_start) - || VIR_SOCKET_ADDR_VALID(&def->forward.addr_end)); + || VIR_SOCKET_ADDR_VALID(&def->forward.addr_end) + || def->forward.port_start + || def->forward.port_end); virBufferAsprintf(buf, "%s>\n", shortforward ? "/" : ""); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 1a598e3..7df2426 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -175,8 +175,9 @@ struct _virNetworkForwardDef { size_t nifs; virNetworkForwardIfDefPtr ifs; - /* adresses for SNAT */ + /* ranges for NAT */ virSocketAddr addr_start, addr_end; + unsigned int port_start, port_end; }; typedef struct _virPortGroupDef virPortGroupDef; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index d444ddb..0ea49e8 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1592,6 +1592,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, NULL) < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, forwardIf ? @@ -1608,6 +1610,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, "udp") < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, forwardIf ? @@ -1624,6 +1628,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, "tcp") < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, forwardIf ? @@ -1642,6 +1648,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, "udp"); masqerr4: iptablesRemoveForwardMasquerade(driver->iptables, @@ -1650,6 +1658,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, NULL); masqerr3: iptablesRemoveForwardAllowRelatedIn(driver->iptables, @@ -1682,6 +1692,8 @@ networkRemoveMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, "tcp"); iptablesRemoveForwardMasquerade(driver->iptables, &ipdef->address, @@ -1689,6 +1701,8 @@ networkRemoveMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, "udp"); iptablesRemoveForwardMasquerade(driver->iptables, &ipdef->address, @@ -1696,6 +1710,8 @@ networkRemoveMasqueradingIptablesRules(struct network_driver *driver, forwardIf, &network->def->forward.addr_start, &network->def->forward.addr_end, + network->def->forward.port_start, + network->def->forward.port_end, NULL); iptablesRemoveForwardAllowRelatedIn(driver->iptables, diff --git a/src/util/viriptables.c b/src/util/viriptables.c index f2d15bf..3578ab8 100644 --- a/src/util/viriptables.c +++ b/src/util/viriptables.c @@ -807,6 +807,8 @@ iptablesForwardMasquerade(iptablesContext *ctx, const char *physdev, virSocketAddr *addr_start, virSocketAddr *addr_end, + unsigned int port_start, + unsigned int port_end, const char *protocol, int action) { @@ -815,6 +817,7 @@ iptablesForwardMasquerade(iptablesContext *ctx, char *addr_start_str = NULL; char *addr_end_str = NULL; virCommandPtr cmd = NULL; + char port_str[sizeof(":65535-65535")] = ""; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; @@ -849,19 +852,27 @@ iptablesForwardMasquerade(iptablesContext *ctx, if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); + if (protocol && protocol[0]) { + if (port_start == 0 && port_end == 0) { + port_start = 1024; + port_end = 65535; + } + + if (port_start < port_end && port_end < 65536) + snprintf(port_str, sizeof(port_str), ":%d-%d", + port_start, port_end); + } + /* Use --jump SNAT if public addr is specified */ if (addr_start_str && addr_start_str[0]) { char tmpstr[sizeof("123.123.123.123-123.123.123.123:65535-65535")]; - const char *portstr = ""; memset(tmpstr, 0, sizeof(tmpstr)); - if (protocol && protocol[0]) - portstr = ":1024-65535"; if (addr_end_str && addr_end_str[0]) { snprintf(tmpstr, sizeof(tmpstr), "%s-%s%s", - addr_start_str, addr_end_str, portstr); + addr_start_str, addr_end_str, port_str); } else { - snprintf(tmpstr, sizeof(tmpstr), "%s%s", addr_start_str, portstr); + snprintf(tmpstr, sizeof(tmpstr), "%s%s", addr_start_str, port_str); } virCommandAddArgList(cmd, "--jump", "SNAT", @@ -869,8 +880,8 @@ iptablesForwardMasquerade(iptablesContext *ctx, } else { virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL); - if (protocol && protocol[0]) - virCommandAddArgList(cmd, "--to-ports", "1024-65535", NULL); + if (port_str[0]) + virCommandAddArgList(cmd, "--to-ports", &port_str[1], NULL); } ret = iptablesCommandRunAndFree(cmd); @@ -899,9 +910,14 @@ iptablesAddForwardMasquerade(iptablesContext *ctx, const char *physdev, virSocketAddr *addr_start, virSocketAddr *addr_end, + unsigned int port_start, + unsigned int port_end, const char *protocol) { - return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, addr_start, addr_end, protocol, ADD); + return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, + addr_start, addr_end, + port_start, port_end, + protocol, ADD); } /** @@ -924,9 +940,14 @@ iptablesRemoveForwardMasquerade(iptablesContext *ctx, const char *physdev, virSocketAddr *addr_start, virSocketAddr *addr_end, + unsigned int port_start, + unsigned int port_end, const char *protocol) { - return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, addr_start, addr_end, protocol, REMOVE); + return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, + addr_start, addr_end, + port_start, port_end, + protocol, REMOVE); } diff --git a/src/util/viriptables.h b/src/util/viriptables.h index 4241380..f2db368 100644 --- a/src/util/viriptables.h +++ b/src/util/viriptables.h @@ -109,6 +109,8 @@ int iptablesAddForwardMasquerade (iptablesContext *ctx, const char *physdev, virSocketAddr *addr_start, virSocketAddr *addr_end, + unsigned int port_start, + unsigned int port_end, const char *protocol); int iptablesRemoveForwardMasquerade (iptablesContext *ctx, virSocketAddr *netaddr, @@ -116,6 +118,8 @@ int iptablesRemoveForwardMasquerade (iptablesContext *ctx, const char *physdev, virSocketAddr *addr_start, virSocketAddr *addr_end, + unsigned int port_start, + unsigned int port_end, const char *protocol); int iptablesAddOutputFixUdpChecksum (iptablesContext *ctx, const char *iface, -- 1.8.1.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list