Forward http traffic to another ip address with iptables

We want to forward all http traffic to another IP address on an Amazon EC2 stock Linux machine (CentOS based). I know how to do this with proxy rules and apache, but I was assuming iptables would be a much faster solution (perhaps not!)

Commands

sudo iptables -P INPUT ACCEPT
sudo iptables -F
sudo iptables -A PREROUTING -t nat -p tcp -i eth0 --dport 80 -j DNAT --to 208.68.208.81:80
sudo iptables -A FORWARD -p tcp -d 208.68.208.81 --dport 80 -j ACCEPT

iptables -t nat -L -v -n

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DNAT       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80 to:208.68.208.81:80

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 11 packets, 820 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 11 packets, 820 bytes)
 pkts bytes target     prot opt in     out     source               destination

iptables -L -v -n

Chain INPUT (policy ACCEPT 202 packets, 15705 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            208.68.208.81       tcp dpt:80

Chain OUTPUT (policy ACCEPT 145 packets, 13747 bytes)
 pkts bytes target     prot opt in     out     source               destination

http://208.68.208.81 into a web browser works, but when I try the ip address of the EC2 machine with this config I get a timeout. I do see some packets show up with watch -d iptables -t nat -L -v -n

Help!

Update: added -i eth0 to PREROUTING rule


Solution 1:

There are three potential problems I see (contary to the other answer I don't see anything that would cause a "loop" even in the unedited version of your question).

  1. IP forwarding must be enabled.
  2. After being natted and placed back on the network the packet may fall victim to source address filtering as it looks very much like a spoofed packet.
  3. Responses to packets that go through a NAT must go through the same NAT so the reverse translation can be performed. Otherwise the client will get a response with the wrong source IP/port which it is likely to drop (if it has not already been dropped by reverse path filtering).

You can work arround points 2 and 3 by using a SNAT or MASQURADE rule in addition to the DNAT but if you do that then you lose the original source IP of the traffic. That will make abuse control very difficult.

Another soloution to points 2 and 3 would be to set up a VPN between the two servers. Then use DNAT to forward traffic over the VPN and source IP based routing to bring the replies back to the NAT.

Solution 2:

You may use rinetd to simply forward your ip traffic.

Solution 3:

You have created a loop. Make sure you add the in interface to the PREROUTING rule (eg. -i eth1 or whatever).

You may also need a rule like this:

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination 

  45M 3723M MASQUERADE  all  --  *     WAN_IF  0.0.0.0/0            0.0.0.0/0  

Otherwise the packets will go directly from the machine they were forwarded to back to the client, I think, which will not be expecting them from that host.