18

I have an Ubuntu box I wish to use as NAT instance (among other things). I would prefer to avoid using the NAT AMIs provided by Amazon, and instead configuring NAT myself.

Currently, my host has a single network interface (as shown in http://docs.amazonwebservices.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html ).

Should I be able to configure my Ubuntu host as the NAT instance for the other hosts in my Amazon network?

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination         
       5      454 MASQUERADE  all  --  *      eth0    0.0.0.0/0            0.0.0.0/0  

I tried configuring a NAT rule in the Ubuntu host (10.200.0.51). My second host is on a different network (10.200.10.41/24). So I wrote:

route add -net 10.200.0.0 netmask 255.255.255.0 dev eth0 # So I can reach 10.200.0.51
route add default gw 10.200.0.51

But the machine lost the connection.

What am I misunderstanding regading the usage of NAT instances and routing in Amazon?

1
  • One minor comment, you didn't need to: route add default gw 10.200.0.51 AWS will automatically send traffic via your NAT box if you correctly configure your default route in the AWS console.
    – Slawomir
    Jun 6, 2016 at 5:34

4 Answers 4

22

You can check Amazon's script to configure NAT on a Linux machine, it comes with their default ami-vpc-nat AMI, in /usr/local/sbin/configure-pat.sh

It looks like this:

#!/bin/bash
# Configure the instance to run as a Port Address Translator (PAT) to provide 
# Internet connectivity to private instances. 

function log { logger -t "vpc" -- $1; }

function die {
    [ -n "$1" ] && log "$1"
    log "Configuration of PAT failed!"
    exit 1
}

# Sanitize PATH
PATH="/usr/sbin:/sbin:/usr/bin:/bin"

log "Determining the MAC address on eth0..."
ETH0_MAC=$(cat /sys/class/net/eth0/address) ||
    die "Unable to determine MAC address on eth0."
log "Found MAC ${ETH0_MAC} for eth0."

VPC_CIDR_URI="http://169.254.169.254/latest/meta-data/network/interfaces/macs/${ETH0_MAC}/vpc-ipv4-cidr-block"
log "Metadata location for vpc ipv4 range: ${VPC_CIDR_URI}"

VPC_CIDR_RANGE=$(curl --retry 3 --silent --fail ${VPC_CIDR_URI})
if [ $? -ne 0 ]; then
   log "Unable to retrive VPC CIDR range from meta-data, using 0.0.0.0/0 instead. PAT may be insecure!"
   VPC_CIDR_RANGE="0.0.0.0/0"
else
   log "Retrieved VPC CIDR range ${VPC_CIDR_RANGE} from meta-data."
fi

log "Enabling PAT..."
sysctl -q -w net.ipv4.ip_forward=1 net.ipv4.conf.eth0.send_redirects=0 && (
   iptables -t nat -C POSTROUTING -o eth0 -s ${VPC_CIDR_RANGE} -j MASQUERADE 2> /dev/null ||
   iptables -t nat -A POSTROUTING -o eth0 -s ${VPC_CIDR_RANGE} -j MASQUERADE ) ||
       die

sysctl net.ipv4.ip_forward net.ipv4.conf.eth0.send_redirects | log
iptables -n -t nat -L POSTROUTING | log

log "Configuration of PAT complete."
exit 0
1
  • Don't forget to run it on boot from /etc/rc.d/rc.local Nov 11, 2017 at 19:13
18

I have installed an Amazon NAT AMI and checked the relevant configuration:

[root@ip-10-200-0-172 ec2-user]# iptables -L -n -v -x -t nat
Chain PREROUTING (policy ACCEPT 11 packets, 660 bytes)
    pkts      bytes target     prot opt in     out     source               destination         

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

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

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination         
     357    24057 MASQUERADE  all  --  *      eth0    10.200.0.0/16        0.0.0.0/0

[root@ip-10-200-0-172 ec2-user]# cat /proc/sys/net/ipv4/ip_forward 
1

In addition, the machine needs to have a public IP, and the Sourc/Dest check needs to be disabled.

This machine can then be used as NAT instance.

Routing for other hosts is configured at EC2 level (using the "Routing table" feature).

2
  • 1
    yeah, the source/dest check is the thing that tripped me up when i had to do this.
    – Sirex
    Jul 10, 2013 at 4:58
  • Is anyone doing NAT logging? I'm thinking I should be able to insert a logging statement at the beginning of postrouting like so: iptables -t nat -I POSTROUTING -j LOG --log-level 4 It seems to work, anyone have a better suggestion?
    – jorfus
    May 13, 2015 at 0:47
5

There are few instructions that helped me.

Notes:

  • 10.0.0.23 - private ip of instance, that i decided to make as "nat-instance", this instance with EIP.
  • 10.0.0.0/24 - vpc subnet

On "nat-instance", as root user:

sysctl -q -w net.ipv4.ip_forward=1 net.ipv4.conf.eth0.send_redirects=0
iptables -t nat -C POSTROUTING -o eth0 -s 10.0.0.0/24 -j MASQUERADE 2> /dev/null || iptables -t nat -A POSTROUTING -o eth0 -s 10.0.0.0/24 -j MASQUERADE

after this:

[sysctl file]
net.ipv4.ip_forward = 1
net.ipv4.conf.eth0.send_redirects = 0

[iptables]
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  10.0.0.0/24          0.0.0.0/0 

via AWS Console:

Grant all traffic from 10.0.0.0/24 (into security groups)
Set disabled source/dest. check (right click on "nat" instance)

In other instances without EIP:

sudo route add default gw 10.0.0.23

UPD: I've found out, that each new instance in my VPC detected internet correctly after pinging default gw.

So:

[ec2-user@ip-10-0-0-6 ~]$ ping google.com
PING google.com (173.194.33.71) 56(84) bytes of data.
^C
--- google.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2356ms

[ec2-user@ip-10-0-0-6 ~]$ ping 10.0.0.23
PING 10.0.0.230 (10.0.0.23) 56(84) bytes of data.
64 bytes from 10.0.0.23: icmp_seq=1 ttl=64 time=1.22 ms
64 bytes from 10.0.0.23: icmp_seq=2 ttl=64 time=0.539 ms
64 bytes from 10.0.0.23: icmp_seq=3 ttl=64 time=0.539 ms
^C
--- 10.0.0.23 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2500ms
rtt min/avg/max/mdev = 0.539/0.768/1.228/0.326 ms
[ec2-user@ip-10-0-0-6 ~]$ ping google.com
PING google.com (173.194.33.70) 56(84) bytes of data.
64 bytes from sea09s15-in-f6.1e100.net (173.194.33.70): icmp_seq=1 ttl=55 time=13.5 ms
64 bytes from sea09s15-in-f6.1e100.net (173.194.33.70): icmp_seq=2 ttl=55 time=14.2 ms

I known, this is not a problem, but it can save some time

1

I found out that the problem was when we specified the ethernet interface in the iptables configuration (-o eth0), removing it solve my problem

my previous iptable config:

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

new config:

sudo iptables -t nat -A POSTROUTING -j MASQUERADE
1
  • tested on ubuntu 21.04
    – David G
    Feb 11, 2022 at 23:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .