ni_hao
ni_hao

Reputation: 416

with iptables forwarding port to other client but with recognition of original sender ip

I have a firewall (based on iptables) at dedicated ubuntu server. I have several LAN Clients.

At one of my LAN Clients I am running software where I can restrict acces based on IP. For me it is important that I can restrict that by using WAN IPs so not LAN IPs.

I have configured my firewall so that a/one port is forwarded to a LAN client which work good (solution found at stackoverflow). So far no problems.

However at the LAN client I do not see the IP of external sender but - I think due to the forwarding - the client sees that the packet is coming from my LAN server.

Question is: how to forward a port on my server to another LAN IP with different port, but so that the LAN client recognizes the external IP of the packet.

Lets make it more clear:

server LAN IP: 192.168.1.10 server port: 8080

should be forwarded to: client LAN IP: 192.168.1.20 client LAN port: 8000

With iptables I have:

iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8080 -d 192.168.1.10 -j DNAT --to 192.168.1.20:8000

iptables -A FORWARD -p tcp -d 192.168.1.20 --dport 8000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -t nat -A POSTROUTING -p tcp --dport 8000 -d 192.168.1.20 -j SNAT --to 192.168.1.10

As written that works, but when f.i. someone at IP 88.77.66.55 sends a packet then my LAN client (192.168.1.20) sees that the packet is coming from my LAN server (192.168.1.10) and unfortunately not from 88.77.66.55.

Can I fix that...?

Upvotes: 2

Views: 17653

Answers (3)

ETech
ETech

Reputation: 1607

Let us define:
{source address} - packet sender (some remote address)
{interface address} - packet receiver (firewall external address)
{local address} - packet end point receiver local network address
{local gateway} - firewall local address
{proto block} - IP protocols limitation (i.e. -p tcp -m tcp --dport xxxx)
1. If you want the client to see ip address of packet source - do that:

IPTABLES -t nat -A PREROUTING -s {source address} -d {interface address} {proto block} -j DNAT --to-destination {local address}
IPTABLES -A FORWARD -d {local address} -j ACCEPT

Do not forget to make:

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

It will enable packets forwarding.
In this case, your end point will see original ip address, however, it will try to respond to default gateway, if this address is not in local network range, add:

route add {source address} gw {local gateway}

this will tell your endpoint to send packets for {source address} via {local gateway} (or reply back).
2. You do not want endpoint to see original ip address and do not want to modify routing tables, then add

IPTABLES -t nat -A POSTROUTING -s {source address} -j MASQUERADE

In this case, LAN client will see only {local gateway} address.

In any case, do not forget to masquerade all packets that are going from your local network to remote addresses by:

IPTABLES -t nat -A POSTROUTING !-d 192.168.0.0/16 -j MASQUERADE
  1. You want to keep source address and destination address for further processing. In this case, your {local gateway} will be just a part of packet routing and {local address} has to be just a next hop - use policy routing for that.

First, add your own routing table with lower than 252 tag to /etc/iproute2/rt_tables

Then - you can add rule for {source address} directly to rules set or mark packets from {source address} - both methods will lookup your custom routing table for that packets:

ip rule add from {source address} table custom_table

or

iptables -t mangle -A PREROUTING -s {source address} -j MARK --set-mark 1
ip rule add fwmark 1 table custom_table

And then, make {local address} next hop gateway for these packets:

ip route add default via {local address} table custom_table

Of course, POSTROUTING chain will be applied just before packet exit and you can shape your source address if needed.

Upvotes: 2

Your last rule is the same as a MASQUERADE rule.

eg:

iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE

With MASQUERADE or SNAT, you are modifying the source-IP address as it goes through the first server. The 2nd server sees the packet and sends it's response back to that IP, which is then sent back to the client.

However, the server sees request as coming from 192.168.1.10 - because that's where it's coming from.

client > gateway > iptables-router > server (sees .10) > iptables-router > gateway > client

If you remove the MASQUERADE/SNAT, the server sees the real IP, but when it sends the reply, the packet is going to it's default gateway (default route) which is probably your router or a gateway at your data center. The client gets a response back from an IP address it doesn't know about, and doesn't know what to do with it, so it looks like it's not working. Alternatively, the gateway/rputer sees a SYNACK with no associated connection and drops the packet.

client > gateway > iptables-router > server > gateway (DROP) or > client (DROP)

If you want the server to get the real IP of the client, here are two common ways to make it work:

  1. Set the gateway (default route) of the server to the IP address of the iptables machine (ie: the machine you are running these iptables rules on). In this case, the server sends all external traffic (ie: a response to a random IP address from the internet) to the MAC address of the iptables machine, which is waiting for a reply. iptables will send it back to the client. The webserver machine is behind the iptables machine, using the iptables machine as a router.

client > gateway > iptables-router > server(real IP) > iptables-router > gateway > client

  1. Use an HTTP proxy like nginx which will work the same way you have it working now, with the client only seeing the internal .10 address. However, because it's a proxy, it can send an HTTP header like X-Original-IP-Address: 123.456.789.012 containing the real IP address of the client.

client > gateway > iptables-router > server (sees X-Original-IP header) > iptables-router > gateway > client

Best Regards, Neale

Upvotes: 5

oleg_g
oleg_g

Reputation: 532

Just remove last rule (do not do SNAT). Or restrict SNAT alloving only masquarading of your LAN clients by adding -o eth0 condition (assuming eth0 is external interface):

iptables -t nat -A POSTROUTING -p tcp -o eth0 --dport 8000 -d 192.168.1.20 -j SNAT --to 192.168.1.10

Upvotes: 0

Related Questions