Iptables port forwarding with restrictions on some

iptablesnat;port-forwarding

I have a set of services where I'd like to set IP based ACLs (whitelist) for one, but not for the other. The issues seems to show up as the services run on the same port internally (port 80) but I use different ports on the gateway to access them.

Port 8088 on Gateway -> Port 80 on 10.0.0.A (with IP whitelist)
Port 80 on Gateway -> Port 80 on 10.0.0.B

And I can get this to work with everything open with the following rules:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8088 -j DNAT --to 10.0.0.A:80
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to 10.0.0.B
iptables -A FORWARD -p tcp -i eth0 --dport 80 -j ACCEPT

The issue is that the FORWARD ACCEPT rule covers both of these nat rules, as they seem to be based on the destination port (–dport 80), instead of the incoming port on the gateway (80 vs 8088).

I can't figure out how to rewrite the FORWARD rule into 2 separate rules so that I can have different behaviour for connections coming into the gateway on 80 vs 8088.

Additional info:

lsb_release -d
Description:    Debian GNU/Linux 7.5 (wheezy)
iptables --version
iptables v1.4.14

1st Solution Attempt
I have been able to spin off a chain and perform the routing there, but I am unable to add the ACL (reject) line due to the following error message:

x_tables: ip_tables: REJECT target: only valid in filter table, not nat

Here's what I put in:

iptables -t nat -N Whitelist
iptables -t nat -A Whitelist -p tcp -j DNAT --to 10.0.0.A:80
iptables -t nat -A Whitelist -s <whatsmyip.org> -j RETURN
iptables -t nat -A Whitelist -j REJECT
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8088 -j Whitelist

Everything works fine until line 4, where the REJECT inside nat fails. If I comment the REJECT line out, I can confirm that the remainder of the logic works and the port becomes open to the wild because nothing is rejected.

Next Solution Attempt
Seem to be tripping up on the original issue while working with a properly setup separate chain. The PREROUTING rule changing the port right off the top still seems to cause an issue with the non-nat ACL attempt. The ACL rules have no effect and the port is open to the wild.

iptables -N Whitelist
iptables -A Whitelist -s <whatsmyip.org> -j RETURN
iptables -A Whitelist -j REJECT
iptables -A INPUT -i eth0 -p tcp --dport 8088 -j Whitelist
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8088 -j DNAT --to 10.0.0.A:80

Solution Attempt #3
I tried setting up the whitelist first, then attempting port redirection after resolution of the whitelist. While the rules load, it does not have the intended effect as traffic does not reach it's intended destination from the whitelisted IP. Although I'm not actually 100% sure what the behaviour actually is. I can't tell if the traffic is being rejected in iptables, or maybe the connection is being accepted and pushed through to the destination on port 8088 without the port change? I'm not sure how to verify if the port redirect is actually being done. Here's the rules for this attempt:

iptables -N Whitelist
iptables -A Whitelist -s <whatsmyip.org> -j RETURN
iptables -A Whitelist -j REJECT
iptables -A INPUT -i eth0 -p tcp --dport 8088 -j Whitelist
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8088 -j DNAT --to 10.0.0.A
iptables -t nat -A OUTPUT -p tcp --dport 8088 -j REDIRECT --to-ports 80

Current status
Unresolved. Unsure if I should see if I can figure out another way to redirect the port after the whitelist, or if there's an easy way to determine where the current solution is failing (is it forwarding through 8088 without the 80 redirect, or is it simply being blocked?)

Best Answer

Change

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8088 -j DNAT --to 10.0.0.A:80

to jump to a user-user defined chain that implements your acls. E.g.,

iptables -t nat -N foo
iptables -t nat -A foo --source 192.168.0.0/24 -j RETURN
iptables -t nat -A foo -j REJECT

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8088 -j foo

Edit:

iptables -N foo
iptables -A foo --source 192.168.0.0/24 -j RETURN
iptables -A foo -j REJECT
iptables -A INPUT -i eth0 -p tcp --dport 8088 -j foo

You design your packet filtering completely ignoring any NAT you are doing.