I have an application sitting on a host (let's call it host1) that sends TLS-encrypted TCP packets to another host's port 5015 (let's call it host2). Due to network restrictions, the host1 must have all inbound and outbound traffic enter and leave through either 80 or 443. I have no access to host2.


My thinking is that I could create an iptables rule on host1 that will route/redirect/forward the 5015 traffic out of 443 and have to have it arrive at host2:5015. The problem I'm having is creating the right rule. Here's what I have so far:


_apply_outbound_rules() {
    # Forward outgoing packets through the proxy port
    sudo iptables -t nat \
        -I OUTPUT 1 \
        -p tcp --destination-port $TCP_TRAFFIC_PORT \
        -j DNAT --to-destination :$PROXY_PORT

    # Send packets to host2:5015 port (this is likely the rule to fix)
    sudo iptables -t nat \
        -I POSTROUTING 1 \
        -p tcp --destination-port $PROXY_PORT \
        -j SNAT --to-source :$TCP_TRAFFIC_PORT


Does anyone know how to do this? It seems like a common thing to run into, but I'm having trouble with it.

  • and there is no port restrictions for incoming packets ?
    – Bharat
    Commented Apr 16, 2018 at 17:49
  • @Bharat I should have specified that all traffic must come in and out of either port 80 or 443 on host1, thanks for pointing that out. I'll update the question to state that
    – thanos
    Commented Apr 16, 2018 at 18:29
  • Have you tried echo 1 > /proc/sys/net/ipv4/ip_forward? That will enable routing in the kernel.
    – dogoncouch
    Commented Apr 16, 2018 at 18:36
  • @dogoncouch Just checked that file, kernel routing is enabled on host1. Do you know how to modify the rules to change the packet's destination port to 5015 after it leaves 443?
    – thanos
    Commented Apr 16, 2018 at 18:53
  • 1
    @Hans-MartinMosner I appreciate your advice, I'll specify and say that this is to ship application metadata using Filebeat (host1) to a hosted ELK stack on Logz.io (host2) under the network restrictions (which are a bureaucratic hassle to get altered). And of course, the module will only be deployed if all legal contracts and parameters were agreed and signed off on beforehand by all parties.
    – thanos
    Commented Apr 17, 2018 at 6:10

2 Answers 2


First, NAT in linux is stateful. Meaning you don't need an outbound and an inbound rule. When traffic comes back in that was NATed outbound, linux will automatically un-NAT that return traffic.

Though the main problem you're going to have is that a TCP session is defined by the combination of:

  • source IP
  • source port
  • destination IP
  • destination port

Source IP is already limited to a single value (IP of host1). Destination IP is already a single value (IP of host2). Source port only has 2 possible values (80 & 443). And destination port is limited to a single value (5015).
This means that you can only establish a maximum of 2 simultaneous connections (if you load balance the SNAT across the 2 ports). And even with sequential connections, you're likely to run into issues with port reuse things like the port being in a TIME_WAIT state.

However that said, if you really want to try this, the rule that should do it is:

iptables -t nat -I POSTROUTING \
  -d $HOST2_IP -p tcp --dport $TCP_TRAFFIC_PORT \
  -j SNAT --to-source :$PROXY_PORT
  • thanks for that, it's useful to know about the possible resource contention between the ports. I tried your rule replacing the previous POSTROUTING rule (using it after the OUTPUT rule) and then again alone, but couldn't get the packets to show at host2:5015
    – thanos
    Commented Apr 16, 2018 at 23:27
  • Is the rule meant to be used with another rule before hitting POSTROUTING? Because the connection is over TLS, would an INPUT rule to initiate the first connection over host1:5015 and host2:5015 be required? I have the following, but it also seems not to work sudo iptables -t nat -I PREROUTING -p tcp --source-port $TCP_TRAFFIC_PORT --destination-port $PROXY_PORT -j REDIRECT --to-port $TCP_TRAFFIC_PORT
    – thanos
    Commented Apr 16, 2018 at 23:30
  • I'm not sure what you're asking about INPUT, but no, you should not have any other iptables rules in place.
    – phemmer
    Commented Apr 17, 2018 at 0:09
  • My understanding is that for the initial TLS handshake between both hosts, an inbound rule on host1 using PREROUTING (not INPUT, my mistake) may be needed so that exchange of packets could occur. Is that correct?
    – thanos
    Commented Apr 17, 2018 at 5:04

Do you know on which port the application runs at your host, if no then you need to map all source ports to either 80 or 443

Try below with replacing host2ip.

iptables -t nat -A POSTROUTING -p tcp -d host2ip -j SNAT -m multiport  --sports 1:65535 --to-source :443

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .