I have a test VDS box with real IP. If i start web server on physical interface port 80, it can be opened from another computer via it's ip address (and default port 80):
python -m SimpleHTTPServer 80
But if i try to reditect port 80 from physical interface eth0
to loopback 127.0.0.1 port 8080 i can connect it from another computer on port 8080, but can't connect on port 80, it's just endless 'connecting'. Seems like no redirection occurs:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:8080
python -m SimpleHTTPServer 8080
What i'm doing wrong? :(
P.S. Binding server on '127.0.0.1:8080' produce same result, but it does not matter since server running on '0.0.0.0:8080' will accept connection redirected to '127.0.0.1:8080'. AFAIK. :(
iptables -L
result:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
iptables -t nat -L
result:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:http to:127.0.0.1:8080
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
netstat -nlp
result:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 676/sshd
tcp6 0 0 :::22 :::* LISTEN 676/sshd
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node PID/Program name Path
unix 2 [ ACC ] STREAM LISTENING 7964 600/acpid /var/run/acpid.socket
unix 2 [ ACC ] STREAM LISTENING 6590 1/init @/com/ubuntu/upstart
unix 2 [ ACC ] SEQPACKET LISTENING 6760 231/udevd /run/udev/control
unix 2 [ ACC ] STREAM LISTENING 7030 345/dbus-daemon /var/run/dbus/system_bus_socket
ifconfig -a
result:
eth0 Link encap:Ethernet HWaddr 00:16:3e:da:1a:98
inet addr:5.14.223.181 Bcast:5.14.223.255 Mask:255.255.255.0
inet6 addr: fe80::140:3eff:febe:201a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:371264 errors:0 dropped:59 overruns:0 frame:0
TX packets:2093 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:17377545 (17.3 MB) TX bytes:214428 (214.4 KB)
Interrupt:25
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:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:552 (552.0 B) TX bytes:552 (552.0 B)
Simply replace your rule with this one.
It should work. This will redirect all your 80 port traffic on eth0 to 8080 port of localhost where you are running tomcat.
One other way of doing this without iptables (as I am not even sure whether it's possible with iptables) is using the xinetd services. To use this, install xinetd on your machine (usually it is by default installed). Create a file like this:
Put this content in the file:
Just restart the xinted service.
And it will work like charm.
I have been trying to solve this problem for a while now, and while I ultimately decided not to bind my server process to localhost (I used 0.0.0.0:PORT), for a while I was unsure of where my incoming packets were actually going given I thought I had the right NAT rule.
The answer was that the kernel was intercepting them as martian packets, and discarding them to the side.
This site has a pretty easy set of instructions for setting up logging of martian packets, should you want to see if this was happening to you.
Another solution is to use nginx as a reverse proxy. In that case, you would allow packets with a destination port of 80 through the iptables firewall (check to make sure you are not dropping during the FILTER and the NAT stages -- you can check by running
sudo iptables -t nat -L -v
orsudo iptables -t filter -L -v
). From there nginx listens across all interfaces for traffic destined for port 80. Finding some related to the incoming HTTP request, you can then have nginx forward this request for you to localhost:8080 (127.0.0.1:8080) using the proxy_pass directive.@MonomiDev's post here provides you the actual nginx config that would allow you to do this -- and then if you don't have nginx installed there are tons of tutorials both here on Stack and online to get you started.
What if you do this:
The last time I use a DNAT rule like that, I also had to put in an SNAT rule on POSTROUTING to make it work correctly.