Websocket traffic forwarding using iptables

I’ve had a problem, I needed to route websocket trafic from internal server for external access, but I ran into a lot of problems, like not connecting, or the connections dropped, so let’s see how we can route the traffic successfully

The machines are all behind a iptables firewall.

I was using socket.io server in the background on multiple machines and I needed them all to be accessible from the outside through different ports.

The server is setup like this:

eth0      Link encap:Ethernet  HWaddr ##:##:##:##
          inet ##:##:##:##  Bcast:##:##:##:##  Mask:255.255.255.224
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:15151497 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11137070 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:7810856929 (7.8 GB)  TX bytes:4719777638 (4.7 GB)
          Interrupt:20 Memory:ec300000-ec320000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:50967 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50967 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:9190223 (9.1 MB)  TX bytes:9190223 (9.1 MB)

vboxnet1  Link encap:Ethernet  HWaddr 0a:00:27:00:00:01
          inet addr:192.168.22.251  Bcast:192.168.22.255  Mask:255.255.255.0
          inet6 addr: fe80::800:27ff:fe00:1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:102350 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:20302629 (20.3 MB)

So to create the correct iptables rules, we do the following:

iptables -t nat -A PREROUTING -p tcp --dport <OUTSIDE_PORT> -j DNAT --to-destination <INTERNAL_IP_ADDRESS>:<INTERNAL_PORT>
iptables -t nat -A POSTROUTING -p tcp --dport <INTERNAL_PORT> -j MASQUERADE

So in my case I had:

iptables -t nat -A PREROUTING -p tcp --dport 31261 -j DNAT --to-destination 192.168.22.1:31261
iptables -t nat -A POSTROUTING -p tcp --dport 31261 -j MASQUERADE

Let explain what happens with these commands:

  • -j DNAT Destination-NAT (DNAT) - Changing the recipient

    If you want to change the receipient of a packet, Destination NAT (DNAT) is your choice! DNAT can be used for servers running behind a firewall. Obviously the receipient has to be changed before any routing decisions are made, therefore DNAT is meaningful within the PREROUTING chain and the OUTPUT chain (for locally generated packets) only

  • -j MASQUERADE - Change sender to router’s IP-Adress

    Using the MASQUERADE target every packet receives the IP of the router’s outgoing interface. The advantage over SNAT is that dynamically assigned IP addresses from the provider do not affect the rule, there is no need to adopt the rule. For ordinary SNAT you would have to change the rule every time the IP of the outgoing interface changes. As for SNAT, MASQUERADE is meaningful within the POSTROUTING-chain only. Unlike SNAT, MASQUERADE does not offer further options.

  • -p tcp The protocol type

Now the connection should be established