Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

My goal is to run a webserver on port 3000 and make it available to my network over port 80. The best answer I found so far is this nice one liner.

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000

But this only effects incoming packages and I would like the client to get his response back from port 80. The next problem is that the webserver should only be reachable over port 80. So far I'm stuck with this configuration.

# Default Chain Policies
iptables -t filter -P INPUT DROP
iptables -t filter -P OUTPUT DROP
iptables -t filter -P FORWARD DROP

# Allow Loopback Access
iptables -t filter -A INPUT  -i lo -j ACCEPT
iptables -t filter -A OUTPUT -o lo -j ACCEPT

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
iptables -t nat -A POSTROUTING -p tcp -o eth0 --sport 3000 -j SNAT --to

iptables -t filter -A INPUT  -i eth0 -p tcp --dport 3000 -j ACCEPT
iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 3000 -j ACCEPT
share|improve this question
Why can't the webserver just listen on port 80? – David W May 5 '12 at 17:57
I was trying to do that but the user which is running the server is not allowed to bind to ports under 1024. – TheHelix May 5 '12 at 18:17
You don't need anything but the one-line rule you posted. TCP is connection-oriented. Packets going in one direction on the connection always have precisely the same source IP address and port as the destination IP address and port of packets going in the other direction. This is an absolute TCP requirement -- it is impossible to violate it. – David Schwartz May 5 '12 at 21:25
But how do I only accept connection which are redirected from port 3000, since the webserver should only be on port 80. – TheHelix May 6 '12 at 7:40

You need to allow the 'RELATED' and 'ESTABLISHED' states. No need for the POSTROUTING rule.

A web server like apache can bind to port 80 because it runs as root. This enables it to bind to a privileged port < 1024, but it drops root privileges after that and process http request under non-privileged user. So, you should be able to do something similar if you want to bind to port 80.

share|improve this answer
up vote 0 down vote accepted

This seems to do the trick. The webserver is now available over 80 and not over 3000.

iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 80 -j MARK --set-mark 1
iptables -t nat    -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
iptables -t filter -A INPUT      -i eth0 -p tcp --dport 3000 -m state --state NEW,ESTABLISHED -m mark --mark 1 -j ACCEPT
iptables -t filter -A OUTPUT     -o eth0 -p tcp --sport 3000 -m state --state ESTABLISHED -j ACCEPT
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.