2

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 192.168.0.2:80

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
TheHelix
  • 21
  • 3
  • Why can't the webserver just listen on port 80? – David W May 05 '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 05 '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 05 '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 06 '12 at 07:40

2 Answers2

2

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.

Khaled
  • 35,688
  • 8
  • 69
  • 98
0

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
TheHelix
  • 21
  • 3