iptables conditional masquerade

Hi everyone,

I have a LAN with :

  • 1 internet box (192.168.1.1)
  • 1 Debian host (192.168.1.224)
  • 3 Windows hosts (192.168.1.32/33/34)

The internet box is set to route all incoming traffic to the Debian host (DMZ).

Then the Debian host is set to accept certain packets and forward others to the windows hosts. It's all based on the port number:

  • port 22 accepted
  • port 80 accepted
  • port 59032 forwarded to 192.168.1.32:5900
  • port 59033 forwarded to 192.168.1.33:5900
  • port 59034 forwarded to 192.168.1.34:5900

That allows me to ssh and web into my Debian host and to vnc into my Windows host from the outside world.

This is done by using iptables with the following rules:

iptables -t filter -A INPUT -i eth0 -p $tcp --dport 22 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p $tcp --dport 80 -j ACCEPT
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 59032 -j DNAT --to 192.168.1.32:5900
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 59033 -j DNAT --to 192.168.1.33:5900
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 59034 -j DNAT --to 192.168.1.34:5900

The Debian host is happy receiving connections from the outside world.
But VNC on Windows would block packets if they are not from 192.168.1.0/24.
I could remove that restriction on the Windows host but NO, that's not what I want to do. So I'm using one more rule for iptables:

iptables -t nat -A POSTROUTING -j MASQUERADE

That way, the Windows host believe that the VNC connection is comming from the local server.

For future improvement reasons, I would rather masquerade only certain packets. So my idea is to do something in the nat.PREROUTING chain so that the nat.POSTROUTING chain will be able to tell whether a packet should be masqueraded or not.

Is there a way to achieve that or any workaround?

Thanks for your help.

Santiago