A have a root server with 2 static IP address which are both connected to one interface (eth0 and eth0:1). Now I need to redirect all incoming traffic from one IP address to a VM on the same PC. The VM has it's own local IP address within a virtual switch. (It is reachable from the "root computer"). I've already talked to the provider and he admit that it is possible with NATing but however isn't allowed to give me more detailed instruction. What I already tried:

iptables -t nat -A PREROUTING -p tcp -d 85.214.XXX.XXX -j DNAT --to-destination

iptables -t nat -A PREROUTING -i eth0:1 -j DNAT --to-destination

Both doesn't work. The VM it's self has internet access over one IP address. (Pings from the VM are successful). The problem is, that the incoming traffic (for example 85.214.XXX.XXX:80) is still handled by the "root computer" so it need to be redirected to the VM. Requests over the other IP address (85.12.XXX.XXX:80) must not be redirected. Port 80 was just an example port. There are more ports that http needed.

EDIT1: After using the first command, the traffic doesn't get handled by the "root server" but however does not reach the VM either.

ip -br link: lo UNKNOWN 00:00:00:00:00:00 eth0 UP ac:1f:6b:21:ea:14 eth1 DOWN ac:1f:6b:21:ea:15 virbr0 UP 52:54:00:07:80:05 virbr0-nic DOWN 52:54:00:07:80:05 vnet0 UNKNOWN fe:00:a3:b0:56:10

Ip -br adress: lo UNKNOWN ::1/128 eth0 UP 81.169.XXX.XXX/32 85.214.XXX.XXX/32 fe80::ae1f:6bff:fe21:XXXX/64 eth1 DOWN virbr0 UP virbr0-nic DOWN vnet0 UNKNOWN fe80::fc00:a3ff:feb0:5610/64

Ip route: default via dev eth0 dev eth0 scope link dev eth0 scope link metric 1000 dev virbr0 proto kernel scope link src

Ip-adress -c: iptables-save -c # Generated by iptables-save v1.6.0 on Tue Jun 26 21:12:21 2018 *nat :PREROUTING ACCEPT [77:5491] :INPUT ACCEPT [57:4459] :OUTPUT ACCEPT [26:1644] :POSTROUTING ACCEPT [26:1644] [36:1868] -A PREROUTING -d 85.214.XXX.XXX/32 -p tcp -j DNAT --to-destination [326:23798] -A POSTROUTING -s -d -j RETURN [0:0] -A POSTROUTING -s -d -j RETURN [70:4104] -A POSTROUTING -s ! -d -p tcp -j MASQUERADE --to-ports 1024-65535 [2384:181184] -A POSTROUTING -s ! -d -p udp -j MASQUERADE --to-ports 1024-65535 [1:84] -A POSTROUTING -s ! -d -j MASQUERADE [4:240] -A POSTROUTING -d -j SNAT --to-source 85.214.XXX.XXX COMMIT # Completed on Tue Jun 26 21:12:21 2018 # Generated by iptables-save v1.6.0 on Tue Jun 26 21:12:21 2018 *mangle :PREROUTING ACCEPT [8612376:1647699647] :INPUT ACCEPT [7968616:1098054721] :FORWARD ACCEPT [642923:549577951] :OUTPUT ACCEPT [7286018:1062313751] :POSTROUTING ACCEPT [7752855:1602990616] [363:121944] -A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill COMMIT # Completed on Tue Jun 26 21:12:21 2018 # Generated by iptables-save v1.6.0 on Tue Jun 26 21:12:21 2018 *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT DROP [0:0] :f2b-plesk-modsecurity - [0:0] [82390:7025055] -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT [18:720] -A INPUT -p tcp -m tcp --dport 106 -j DROP [2488:104592] -A INPUT -p tcp -m tcp --dport 3306 -j DROP [153:6168] -A INPUT -p tcp -m tcp --dport 5432 -j DROP [9:360] -A INPUT -p tcp -m tcp --dport 9008 -j DROP [41:1784] -A INPUT -p tcp -m tcp --dport 9080 -j DROP [252:20165] -A INPUT -p udp -m udp --dport 137 -j DROP [10772:2676517] -A INPUT -p udp -m udp --dport 138 -j DROP [488:21600] -A INPUT -p tcp -m tcp --dport 139 -j DROP [849142:43736264] -A INPUT -p tcp -m tcp --dport 445 -j DROP [68:2856] -A INPUT -p udp -m udp --dport 1194 -j DROP [39259:2663130] -A INPUT -p udp -m udp --dport 53 -j DROP [15817:947524] -A INPUT -p tcp -m tcp --dport 53 -j DROP [974:36333] -A INPUT -p icmp -m icmp --icmp-type 8/0 -j ACCEPT [5763490:719804706] -A INPUT -j ACCEPT [327455:532369669] -A FORWARD -d -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT [145660:7917349] -A FORWARD -s -i virbr0 -j ACCEPT [0:0] -A FORWARD -i virbr0 -o virbr0 -j ACCEPT [29309:1533140] -A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable [0:0] -A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable [0:0] -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT [249:11394] -A FORWARD -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j REJECT --reject-with tcp-reset [3875:171296] -A FORWARD -m state --state INVALID -j DROP [0:0] -A FORWARD -i lo -o lo -j ACCEPT [582365:31456904] -A FORWARD -j DROP [363:121944] -A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT [12150865:2418557344] -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT [24:5299] -A OUTPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j REJECT --reject-with tcp-reset [12746:706295] -A OUTPUT -m state --state INVALID -j DROP [494443:29667994] -A OUTPUT -o lo -j ACCEPT [408707:30248531] -A OUTPUT -j ACCEPT [68:6175] -A f2b-plesk-modsecurity -j RETURN COMMIT # Completed on Tue Jun 26 21:12:21 2018

And on the VM:

ip route: default via dev ens3 dev ens3 scope link metric 1000 dev ens3 proto kernel scope link src

  • Have you enabled forwarding with with sysctl -w net.ipv4.conf.all.forwarding=1? – Tomek Jun 21 '18 at 20:43
  • Yes I did. Read my edit1 for more information – MarvinX Jun 22 '18 at 17:57
  • You should provide several network informations for both systems (2nd being the VM) to avoid people having to guess what's wrong: ip -br link; ip -br address; ip route; iptables-save -c. Don't use ifconfig, it confuses people when using multiple IPs (eg, eth0:1, an artefact from ifconfig times, will probably never match in iptables) – A.B Jun 23 '18 at 7:47
  • Yep, iptables-save would be beneficial. Especially the filter table FORWARD policy and chain. – Tomek Jun 23 '18 at 21:48
  • I added all information :) – MarvinX Jun 26 '18 at 19:26

Your FORWARD rules allow VM initiated traffic, outgoing and reply, with these rules:

-A FORWARD -d -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT #reply traffic to the VM
-A FORWARD -s -i virbr0 -j ACCEPT #VM initiated

What they don't allow is incoming traffic, as the counter's high value hints in the next FORWARD rule:

[29309:1533140] -A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable

That's good for security but you'll have to add exceptions.

UPDATE: redirect all traffic, not just a few ports.

The redirection itself:

iptables -t nat -I PREROUTING -d 85.214.XXX.XXX -j DNAT --to-destination

This will redirect all protocols (icmp, tcp, udp (possibly others)), you can add as you wrote initially -p tcp to limit it to tcp.

You have to enable the redirected traffic in the FORWARD chain, since once the traffic is DNATed, it becomes routed, so is subject to the FORWARD chain (and no more to the INPUT chain). At the same time, to guard against any local routing misuse (by the default gateway for example), you can limit this to DNATed traffic only, by querying conntrack (marking packets in the mangle table and checking them here would have worked too):

iptables -I FORWARD -d -m conntrack --ctstate DNAT -j ACCEPT

Notice the -I. Since you're competing with the VM's provider rules (probably virt-manager), you have to take care your exception rules come before the DROP/REJECT rules. Optimally it could come after the ... RELATED,ESTABLISHED ... rule, but you can deal with that later.

Note also that for the same reason (rule coming too late), your VM's outgoing traffic is not using its dedicated IP but the host's IP: the SNAT rule comes too late, after the generic MASQUERADE rule. You have to insert it with a -I and not a -A too until you figure out how to integrate this with (probably?) virt-manager.
AND, also, there's an error in this rule anyway, it should be using -s not -d as in:

iptables -t nat -I POSTROUTING -s ! -d -j SNAT --to-source 85.214.XXX.XXX

Whenever (probably?) virt-manager reinserts its rule (restart etc.), you should have a look again at your rules to see if everything is still in an order allowing what you intend.

That would be out of the scope of this Q/A to address virt-manager integration. Have a look there for example:

Networking - Libvirt Wiki - Forwarding Incoming Connections

  • So you mean it's not possible to redirect all ports from the second IP address to the VM? – MarvinX Jun 28 '18 at 15:14
  • I just didn't get you wanted to redirect all traffic. I changed the answer. – A.B Jun 28 '18 at 19:00
  • @MarvinX Just for information, there can probably be an other completely different method using macvlan or ipvlan (in case macvlan is blocked by the hosting provider): the container or VM might then "own" directly the IP address without NAT involved. I'd know usage for container (using ip link set netns ... to move the interface) , not much for a VM. You can have a look there: Macvlan and IPvlan basics – A.B Jun 29 '18 at 5:42
  • @MarvinX confused: the answer about NAT or the comment about ipvlan (for a qemu VM it appears to be ipvtap) ? – A.B Jun 29 '18 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.