Ilija Matoski

    ← Articles

    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