AWS VPC + IPtables + NAT: Port Forwarding is not working
Solution 1
Finally, I Cracked it !!!!
On the NAT instance, I had to change below command:
From:
iptables -t nat -A POSTROUTING -o eth0 -s 10.0.0.0/16 -j MASQUERADE
To:
iptables -t nat -A POSTROUTING -j MASQUERADE
And it WORKED!!!!
So, I will be creating a new question soon on ServerFault asking what are the advantages and disadvantages in using above two commands.
Solution 2
- Make sure that you are allowing tcp port
2222
inboud from0.0.0.0/0
on the security group for your nat box - Make sure you have your VPC "Route Table" setup properly.
- At least two separate tables (one associated with the private subnet, one associated with the public subnet)
- Your
10.0.1.0
(private) subnet should have a route table rule like: Destination:0.0.0.0/0
, Target: "Nat box" - Your
10.0.0.0
(public) subnet should have a route table rule like: Destination:0.0.0.0/0
, Target: "Internet gateway" Make sure you have Source/destination checking disabled on the NIC for your NAT box, no NATting fun without it. (I know you already have this but its really important, so including it for some future viewer)
Make sure outbound packets know where to go:
iptables --table nat --append POSTROUTING --source 10.0.0.0/16 --destination 0.0.0.0/0 --jump MASQUERADE
Make sure inboud packets to
2222
get rerouted properly:iptables --table nat --append PREROUTING --protocol tcp --dport 2222 --jump DNAT --to-destination 10.0.1.243:22
Solution 3
This posts helped me a lot in understanding AWS NAT. So I started to investigate what made iptables -t nat -A POSTROUTING -j MASQUERADE
it worked.
Well the answer I found the above statement is allowing the NAT box to source NAT the 'LAPTOP' IP to '10.0.0.54' while same time performing destination NAT to 10.0.1.243. At this time the private subnet box is ssh request coming from NAT device only. This command is actually decreasing the security of the private subnet server. It is recommended to use the below command to fine tune the private subnet access through ssh and NAT box as mentioned below;
iptables --table nat --append POSTROUTING --source "INTERNET IP of the Laptop" --destination 10.0.1.243 --jump MASQUERADE
Related videos on Youtube
slayedbylucifer
A Linux/Virtualization Sys-admin working on cloud computing. I do the system administration stuff as well as Datacenter Automation which essentially involves scripting. Been working on shell scripting for long which eventually got me interested in perl scripting. Recently I picked up python and still learning it.
Updated on September 18, 2022Comments
-
slayedbylucifer over 1 year
Yesterday, I posted a question here but I think was not clear enough in my words. BTW, This question is not a duplicate.
I have AWS VPC Setup as below.
GOAL/PROBLEM: SSH to Server A from internet. And It is not working.
Server A is in private subnet and hence I want to enable iptables NATing on the my NAT instance so that I can ssh to SErver A directly from internet
I ran below command on NAT instance:
NAT# iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 10.0.1.243:22
IP forwarding is enableed on NAT instance:
NAT# sysctl -p net.ipv4.ip_forward = 1
MASQUERADE is running on NAT instance:
NAT# iptables -t nat -vnL POSTROUTING Chain POSTROUTING (policy ACCEPT 6 packets, 312 bytes) pkts bytes target prot opt in out source destination 199 16466 MASQUERADE all -- * eth0 10.0.0.0/16 0.0.0.0/0
AWS Security groups are configured fine to allow various access needed for this test case.
Troubleshooting:
I can telnet from NAT to Server A on port 22. So Access is good.
When I run
telnet 54.213.116.251 2222
on my laptop, I see below entry in tcpdump on NAT:NAT# tcpdump -n -i eth0 dst 10.0.1.243 and port 22 09:59:13.738316 IP xxx.xxx.xxx.xxx.51709 > 10.0.1.243.ssh: Flags [S], seq 1868541786, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0 09:59:16.737009 IP xxx.xxx.xxx.xxx.51709 > 10.0.1.243.ssh: Flags [S], seq 1868541786, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0 09:59:22.775567 IP xxx.xxx.xxx.xxx.51709 > 10.0.1.243.ssh: Flags [S], seq 1868541786, win 8192, options [mss 1460,nop,nop,sackOK], length 0
So it means the iptables is routing the packets to
10.0.1.243
. (BTW,xxx.xxx.xxx.xxx
is public ip address of my laptop)But When I run tcpdump on Server A, I do not see anything coming from
10.0.0.54
which is the Internal/Private IP address of NAT (And I think this is the problem):Server A# tcpdump -n src 10.0.0.54 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
But if I telnet from NAT instance to Server A, I see good stuff in tcpdump on Server A(This means, My overall
PREROUTING
Rule is not working as expected):Server A# tcpdump -n src 10.0.0.54 05:01:47.500080 IP 10.0.0.54.44627 > 10.0.1.243.ssh: Flags [S], seq 2862522431, win 14600, options [mss 1460,sackOK,TS val 3013083 ecr 0,nop,wscale 7], length 0 05:01:47.501601 IP 10.0.0.54.44627 > 10.0.1.243.ssh: Flags [.], ack 760676524, win 115, options [nop,nop,TS val 3013083 ecr 12074896], length 0 05:01:47.535720 IP 10.0.0.54.44627 > 10.0.1.243.ssh: Flags [.], ack 22, win 115, options [nop,nop,TS val 3013092 ecr 12074928], length 0
Conclusion:
From tcpdump output on NAT, It seems that Iptables is forwarding my packets fine.
from TCP dump on Server A, I have good connectivity from NAT to Server A.
But in End-to-end, I am not able to connect to the server A from my laptop.
(BTW, I know SSH tunnel and other good stuff. But I want only Iptables to help me with this.)
-
Dusan Bajic over 10 yearsDid you disable source/destination checking on your NAT instance?
-
slayedbylucifer over 10 yearsWhat does it mean? How to check that? I searched the entire Iptables man page but is does not say thing about source/destination checking (unless I missed anything obvious.)
-
Dusan Bajic over 10 yearsYou have to do that in AWS web console (or CLI). docs.aws.amazon.com/AmazonVPC/latest/UserGuide/…
-
slayedbylucifer over 10 yearsThanks. I find that it is already
Disabled
for the NAT instance.
-
-
slayedbylucifer over 10 yearsYour every single suggestions are already in place. Thanks.
-
c4urself over 10 yearsI updated it to show all the steps
-
slayedbylucifer over 10 yearsThanks. +1 for your efforts. Your
MASQUERADE
command is not helpful in my case. May be I am missing something. The OnlyMASQUERADE
command that gets me flying is the the one I have mentioned in my answer. -
Neven almost 8 yearsMan thanks in a million. Had the same problem, same.... Every step was in place... but this "-o eth0" was there as well. Removed it, worked like charm. Thanks in million.
-
Ryan Shillington almost 8 yearsThe reason why it works is because the "-s 10.0.0.0/16" says to only translate packets with source ip 10.x.x.x. I'm guessing your home laptop was on your home network and was coming from some external IP so the NAT was ignoring your laptop's requests. Others may want to run "ip r" on the linux command line to see if eth0 is really the name of their ethernet device. If not, change it to whatever your eth device is named (ex. ens192 or whatever).
-
Ryan Shillington almost 8 yearsOh, also, I learned the above by reading the iptables man page. It's really good and not a long read. I highly recommend it. Run "man iptables" from the command prompt to see it in all it's glory.