1

problem:

I have a TCP server and client that each listen on port 9000. I have the server and client deployed on two different hosts where traffic can only pass through port 80 between them. I want the source port (9000) to be maintained when packets are sent between them (see the SNAT rule below) so that the PREROUTING rule can identify the packets with --source-port.

approach:

I'm trying to setup iptables rules such that the server routes its traffic from port 9000 to port 80, and a complimentary rule for the client where the incoming traffic on port 80 is routed to 9000 locally.

I've come up with this script to apply the rules. I've tried this with a few variations and packets seem to get accepted by the server host, but not accepted by the PREROUTING (inbound) rule.

#!/bin/bash

apply_inbound_rules() {
    # Allow incoming server traffic from port 80 to the TCP client
    sudo iptables -t nat \
        -I PREROUTING \
        -p tcp --destination-port $PROXY_PORT \
        -j REDIRECT --to-port $TCP_PORT
}

apply_outbound_rules() {
    # Setup outgoing packets created by the TCP server
    # to route through local port 80
    # and received on port 80 on the client host
    sudo iptables -t nat \
        -I OUTPUT \
        -p tcp --destination-port $TCP_PORT \
        -j DNAT --to-destination :$PROXY_PORT

    # To maintain the TCP_PORT
    sudo iptables -t nat \
        -I POSTROUTING \
        -p tcp --destination-port $PROXY_PORT \
        -j SNAT --to-source :$TCP_PORT
}

apply_inbound_rules
apply_outbound_rules

Does anyone have experience creating rules like this? It seems like it would be a common problem but I can't seem to figure it out.

4
  • Should the inbound rule use --source-port, then? Dec 30, 2017 at 8:59
  • I want to use source port, the issue is that the packet's source port is a random port. I'm trying to setup a rule so that the packet's source port is maintained when it leaves the client so that when it reaches the server it can be identified from other TCP traffic with different source ports. The SNAT rule doesn't seem to set the source port
    – thanos
    Dec 30, 2017 at 9:02
  • I suppose you've already tried with MASQUERADE instead of SNAT? Dec 30, 2017 at 10:19
  • I've looked into it, though I can't seem to figure out why/how to use it in this context. I thought it was for when the destination IP could change? My guess from your suggestion is to replace the SNAT rule with iptables -t nat -I POSTROUTING -j MASQUERADE?
    – thanos
    Dec 30, 2017 at 15:05

1 Answer 1

2

This is a translation of my comment into a response.

The rules should be adjusted to rely on an outbound MASQUERADE of source port to handle return packets. Thus, outgoing packets should be DNAT-ed with the rule you have, and MASQUERADE-ed with a rule:

iptables -t nat -A POSTROUTING -p tcp --destination-port $PROXY_PORT -j MASQUERADE --to-ports $TCP_PORT

Use that rule instead of your SNAT rule.

Incoming packets relating to those that have been MASQUERADE-ed will get their destination ports duly return-mapped.

(corrected as per comment)

2
  • That rule works well, but it maintains the PROXY_PORT instead of the original TCP_PORT. I've tried a few variations of the rule you listed and can't seem to find one that maintains the TCP_PORT from a client connection. Do you know how to modify the rule to maintain the TCP_PORT?
    – thanos
    Dec 31, 2017 at 6:09
  • Read over the masquerade documentation and got the rule working iptables -t nat -I POSTROUTING -p tcp --destination-port $PROXY_PORT -j MASQUERADE --to-ports $TCP_PORT. Thank you!
    – thanos
    Dec 31, 2017 at 6:12

You must log in to answer this question.

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