Bug 1079917
| Summary: | The packets can not be NATed by using an inclusive range of IP addresses in SNAT in iptables. | ||
|---|---|---|---|
| Product: | Red Hat Enterprise Linux 7 | Reporter: | Hu Jianwei <jiahu> |
| Component: | libvirt | Assignee: | Ján Tomko <jtomko> |
| Status: | CLOSED ERRATA | QA Contact: | Virtualization Bugs <virt-bugs> |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | 7.0 | CC: | dyuan, honzhang, iptables-maint-list, jdenemar, laine, lcheng, mzhan, rbalakri, twoerner |
| Target Milestone: | rc | ||
| Target Release: | --- | ||
| Hardware: | x86_64 | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | libvirt-1.2.13-1.el7 | Doc Type: | Bug Fix |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2015-11-19 05:45:36 UTC | Type: | Bug |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
If this functionality is not supported on 3.10.0 kernel, how is it possible to actually add such rules to the nat table? My understanding is that a single --to-source range is still supported in 3.x kernels. libvirt only adds a single --to-source arg, so the restriction that Thomas is pointing out should not apply. But more to the point - s far as I can tell, the setup being tested here is that libvirt is being told that NAT should be done using the range 10.x.x.104-10.x.x.124 as source addresses, but the host owns/uses only a few of the addresses in that range. My assumption is that iptables is doing its thing at a layer low enough that it cannot know that only certain IP addresses in the given range are actually in use on the host, so it is likely NATing to an IP address that is unused, and naturally the response packets never get back to the host. You can verify this by running tcpdump on the destination of the ping to see what source address is used. If this is what's happening, then I would consider this as a documentation problem if anything - it should simply be noted in the description of the ip address range that 1) only a single range is supported, and 2) *all* the IP addresses in the given range must be in use on an interface on the host, otherwise the response packets will never get back to the host for forwarding to the guest. Can you rerun your test while running tcpdump on 10.x.x.123 to check for the ping packets and report the result here? Laine, please have a look at the iptables-extensions man page in the SNAT section:
In Kernels up to 2.6.10, you can add several --to-source
options. For those kernels, if you specify more than one source
address, either via an address range or multiple --to-source
options, a simple round-robin (one after another in cycle) takes
place between these addresses. Later Kernels (>= 2.6.11-rc1)
don't have the ability to NAT to multiple ranges anymore.
"if you specify more than one source address, either via an address range or multiple --to-source options" is the important information.
This means that also address ranges within a single --to-source option are affected.
Upstream patch adding the documentation suggested as 2) in comment 6: https://www.redhat.com/archives/libvir-list/2015-February/msg00642.html Now pushed upstream:
commit 794235e813ffa9c56f2756501640398b0450de79
Author: Ján Tomko <jtomko>
CommitDate: 2015-02-18 15:36:45 +0100
docs: clarify nat range behavior
All the addresses from the range are used, not just those
that are in use on the host.
https://bugzilla.redhat.com/show_bug.cgi?id=1079917
git describe: v1.2.12-150-g794235e
Verify it as follows. [root@localhost ~]# rpm -q libvirt libvirt-1.2.14-1.el7.x86_64 [root@localhost ~]# firefox /usr/share/doc/libvirt-docs-1.2.14/html/formatnetwork.html ... Since 1.0.3 it is possible to specify a public IPv4 address and port range to be used for the NAT by using the <nat> subelement. Note that all addresses from the range are used, not just those that are in use on the host. The address range is set with the <address> subelements and start and stop attributes: ... Move to VERIFIED according to comment 6 and comment 17. Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://rhn.redhat.com/errata/RHBA-2015-2202.html |
This is a more complete excerpt from the iptables-extensions man page: SNAT This target is only valid in the nat table, in the POSTROUTING and INPUT chains, and user-defined chains which are only called from those chains. It specifies that the source address of the packet should be modified (and all future packets in this connection will also be man‐ gled), and rules should cease being examined. It takes the following options: --to-source [ipaddr[-ipaddr]][:port[-port]] which can specify a single new source IP address, an inclusive range of IP addresses. Optionally a port range, if the rule also specifies one of the following protocols: tcp, udp, dccp or sctp. If no port range is specified, then source ports below 512 will be mapped to other ports below 512: those between 512 and 1023 inclusive will be mapped to ports below 1024, and other ports will be mapped to 1024 or above. Where possible, no port alteration will occur. In Kernels up to 2.6.10, you can add several --to-source options. For those kernels, if you specify more than one source address, either via an address range or multiple --to-source options, a simple round-robin (one after another in cycle) takes place between these addresses. Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multi‐ ple ranges anymore. 1) In Kernels up to 2.6.10, you can add several --to-source options. 2) Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges anymore. With the kernel version you provided this falls into 2): kernel-3.10.0-110.el7.x86_64 Reassigning to libvirt for verification.