Score:1

Ubuntu IPTables Port forwarding and NAT

tm flag

I am coping with an issue for the past days with which I cannot get my head arround, it addresses routing.

Setup and context:

NetworkDiagram

As depicted in the diagram below, my goal is to call the "Remote Target" from the "Source-VM". The packets need to travel through the "Router-VM" and subsequently through a VPN tunnel (here depicted by the name "GatewaySubnet" to the target 128.20.20.5).

The Router-VM is a Ubuntu machine that has two NICs associated with it.

The tunnel is working fine (the call from the "Router-VM" to the "Remote-Target" is working correctly.

But as far as the Remote-Target is concerned, the packets need to be having the "SRC=" parameter of the Nic in the subnet SNET-AKS (here 10.0.9.0/24) - as this is the only subnet whitelisted there as origin. This cannot be changed.

My question:

How do I need to configure the IPTABLES in the Router-VM so that:

  • the packets (on Port 9080) are forwarded correctly, as:

    • Source-VM (10.0.12.4) -> Router-VM (10.0.25.20 [ETH1]

    • Router-VM (10.0.25.20 [ETH1]) -> Router-VM (10.0.9.4 [ETH0])

    • Router-VM (10.0.9.4 [ETH0]) -> Remote-Target (128.20.20.5)

  • and back with the answer of that request.

The commands I have executed:

# Public interface
EXTIF="eth1"
EXTIP="10.0.25.20"

# Private interface
VPNIF="eth0"
VPNIFIP="10.0.9.4"

# Target destination
CBTARGETIP="128.20.20.5"

echo "1" > /proc/sys/net/ipv4/ip_forward

$IPTABLES -A FORWARD -i $EXTIF -o $VPNIF -p tcp --syn --dport 9080 -m conntrack --ctstate NEW -j ACCEPT
$IPTABLES -A FORWARD -i $EXTIF -o $VPNIF -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $VPNIF -o $EXTIF -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 9080 -j DNAT --to-destination $CBTARGETIP
$IPTABLES -t nat -A POSTROUTING -o $VPNIF -p tcp --dport 9080 -d $CBTARGETIP -j SNAT --to-source $VPNIFIP

The iptable:

~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
LOG        tcp  --  anywhere             anywhere             LOG level warning prefix "filter INPUT: "

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:9080 flags:FIN,SYN,RST,ACK/SYN ctstate NEW
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
LOG        tcp  --  anywhere             anywhere             LOG level warning prefix "filter FORWARD: "
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
LOG        tcp  --  anywhere             anywhere             LOG level warning prefix "filter OUTPUT: "


~$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere             tcp dpt:9080 to:128.20.20.5
LOG        tcp  --  anywhere             anywhere             LOG level warning prefix "nat PREROUTING: "

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       tcp  --  anywhere             128.20.20.5         tcp dpt:9080 to:10.0.9.4
LOG        tcp  --  anywhere             anywhere             LOG level warning prefix "nat POSTROUTING: "

Current result:

  • The call on Source-VM is not succesful.

  • on Router-VM I can see that

    • the traffic incoming from eth1 is forwarded to eth0

    • this traffic is correctly routed to the target-resource (128.20.20.55)

  • But:

    • logging the iptable hooks, it seems that the DST= tag is not modified to 10.0.9.4, instead it stays with the original IP address of Source-VM.

I have tried a lot of Googling - but I am stuck and I really, really appreciate a hint towards any mistakes or trials to debug this process, as I cannot get it to work.

I highly appreciate it - thanks a lot!

Setting up the iptables based on multiple conditions, mostly with the script mentioned above.

Tom Yan avatar
in flag
`it seems that the DST= tag is not modified to 10.0.9.4, instead it stays with the original IP address of Source-VM` I think you mean `SRC=`? So basically the problem is that the `SNAT` rule does not seem to work as you expect? Do traffics for `128.20.20.5` directly / logically go out via `eth0` though? Or do they actually go out via a tunnel interface (since you mentioned VPN)? Can you add the output of `ip r` on `Router-VM` to your question?
Tom Yan avatar
in flag
You may even simply omit `-o $VPNIF` in the SNAT rule. The match is sort of redundant. (But *if* my theory is right here, `--to-source $VPNIFIP` is mostly likely wrong too. Probably it should be some "actual" VPN IP assigned to `Router-VM`. You may replace `-j SNAT --to-source $VPNIFIP` with the somewhat-less efficient `-j MASQUERADE` if you don't really know how things work.)
Score:0
by flag

The packet coming from Source-VM is skipping the second step in your desired flow because the "DNAT" rule is translating the destination of the incoming packet, which should be your Router-VM, to the Remote Target directly.

Lets modify the "DNAT" rule to translate the destination to the IP of your "eth0" (Router-VM ETH0 10.0.9.4) instead of the Remote Target.

So, for the iptables rules:

# Enable IP forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward

# Clear previous rules
$IPTABLES -F
$IPTABLES -t nat -F

# Forwarding rules
$IPTABLES -A FORWARD -i $EXTIF -o $VPNIF -p tcp --syn --dport 9080 -m conntrack --ctstate NEW -j ACCEPT
$IPTABLES -A FORWARD -i $EXTIF -o $VPNIF -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $VPNIF -o $EXTIF -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# NAT rules
$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 9080 -j DNAT --to-destination $VPNIFIP:9080
$IPTABLES -t nat -A POSTROUTING -o $VPNIF -p tcp --dport 9080 -j SNAT --to-source $VPNIFIP
Tom Yan avatar
in flag
`which should be your Router-VM` ugh why?
Saxtheowl avatar
by flag
This ensures the packet is first routed to "eth0" interface, then the source of the packet is changed to "eth0", and finally, the packet is sent to the Remote Target
Tom Yan avatar
in flag
I think you are misinterpreting or so here. `Router-VM` is not some kind of "literal" proxy. `finally, the packet is sent to the Remote Target` would not happen with the rule you give. (But well, I *could be* wrong. The OP hasn't made things really clear.)
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.