0
  1. I have AWS VPC with 1 public subnet and 1 private subnet.
  2. I have my web-server running on port 80 in private subnet.
  3. I want this webserver be accessible form public internet
  4. Yes, The VPC security groups have correct configuration so this is not an issue.
  5. No, I don't want to use ELB or nginX/Haproxy. Lets not get into that discussion.
  6. I want to achieve this via IPtalbes. I want to have an instance with public IP address in public subnet which should act as a Linux router using iptables.

These are the commands I have run my instance which is in public subnet and has a public IP address.

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.1.132:80

Where:

  1. 10.0.1.132 is the IP address of my web server sitting in private subnet.
  2. and eth0 is the interface of my instance which is acting as a router and has a private IP address of 10.0.0.151

I have IP forwarding enables:

# sysctl  -p
net.ipv4.ip_forward = 1

and here is my iptables status:

# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere            tcp dpt:http to:10.0.1.132:80

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Now, when I reach to public DNS of my Linux router, I don't get anything:

$ curl -IL ec2-54-201-38-205.us-west-2.compute.amazonaws.com
HTTP/1.0 504 Gateway Time-out
Server: squid/2.7.STABLE9
Date: Wed, 20 Nov 2013 10:22:57 GMT
Content-Type: text/html
Content-Length: 1145
X-Squid-Error: ERR_CONNECT_FAIL 61
X-Cache: MISS from localhost
X-Cache-Lookup: MISS from localhost:3128
Via: 1.0 localhost:3128 (squid/2.7.STABLE9)
Connection: close

So it means, whatever I did is not working.

Question

I was expecting that when I reach port 80 on my public facing Linux router, It should have redirected the request to port 80 of my internal web server but this is not working. What is wrong with my set up OR iptables rules?

Thanks.

  • You have no mention of ACL rules, have you configured these correctly? – Drew Khoury Nov 20 '13 at 12:44
  • 1
    question, why try and roll your own solution when you could make use of AWS best practice aws.amazon.com/articles/2781451301784570 – Drew Khoury Nov 20 '13 at 12:46
  • @Drew Khoury, the post I have written is just a test case which replicates my scenario. In reality, I have redshift running in private subnet on port 5439 and I want my customers to access it from internet. Hence I am trying to make it work by having a Linux router in the Public subnet. This solution works just fine by using ssh port forwarding but it needs me to reveal the Redshift hostname which I do not want. Also, I could have used "TCP" forwarding feature of AWS ELB, but then I have to pay for ELB. Hence I am aiming for a Linux instance acting as router. Hope that was clear. – slayedbylucifer Nov 20 '13 at 14:55
  • I am having the same issues with this. I have turned off source destination checks on the nat server and cannot get anything to forward. Has anyone found the solution? – user287841 May 7 '15 at 19:15
1

With only the DNAT rule, your webserver will try to send the reply directly to the (public) source IP of the client, which it probably can't reach from its private subnet. You will also need an SNAT or MASQERADE rule on the router for this to work. Something like this:

iptables -t nat -A POSTROUTING -p tcp --dport 80 -j MASQUERADE
  • +1. thanks for the hint. I am trying various MASQUERADE commands but none seem to work so far. – slayedbylucifer Nov 20 '13 at 14:50
  • for debugging purposes, you should check where the packets (and reply packets) arrive and where they get stuck. To check this, it's best to run tcpdumps on the webserver and on the router machine. – etagenklo Nov 21 '13 at 13:51
0

Use

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.1.132:80
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

The masquerading rule is already there if you are using an Amazon Linux AMI VPC NAT instance, otherwise add

sudo iptables -t nat -A POSTROUTING -p tcp --dport 80 -j MASQUERADE

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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