Publi

Conectividad de instancias en AWS. Instancias NAT y puertas de enlace

Instancias NAT en AWS
Uno de los puntos fuertes de Amazon Web Services es que podemos configurar la arquitectura de red a nuestro gusto entre instancias EC2, o incluso entre varios servicios que tengamos contratados. La clave de esto, es que nos permite conectar servicios entre ellos de forma privada. Porque hay veces que nos interesa que un servicio esté conectado a Internet y todo el mundo pueda acceder a él, pero otras veces queremos que sea un servicio oculto al que sólo algunas personas puedan acceder.

El servicio VPC nos permite hacer esto y muchas cosas más. Una de las configuraciones más comunes puede ser tener una instancia como servidor web con dos interfaces de red. Uno de ellos conectado a una subred pública y otro conectado a una subred privada. La subred pública tendrá conexión a Internet y, de hecho, estaremos escuchando en esa interfaz. La interfaz privada estará conectada con otras máquinas que pueden ser servidores de base de datos, caché o almacenamiento. En esta configuración, sólo el servidor web será visible a Internet. Aislando todo lo posible las demás máquinas que, ni siquiera tendrán IP pública para poder conectarnos a ellas.

Resumiendo la configuración

Voy a resumir los pasos para crear un VPC, subredes, tablas de enrutamiento, y dos instancias: una conectada a la red pública y a la privada y otra conectada solo a la privada. La instancia de la subred pública tendrá IP pública. No seré muy detallado, pero si esto lo tienes claro puedes saltar al siguiente punto.

Lo primero es crear un VPC. Ésta es mi configuración:
Crear VPC en Amazon Web Services

Ahora creamos dos subredes (subnets). Una será pública y otra privada. En este punto veo muy importante ponerle nombre a todo. Puede parecer una pérdida de tiempo pero nos ahorrará muchos calentamientos de cabeza en el futuro. También vemos la tabla de enrutamiento de la subred pública:
Crear subnets dentro de la VPC

Aquí muestro las dos tablas de enrutamiento disponibles (route tables), una para la red pública y otra para la red privada. Debemos asegurarnos de que la tabla de enrutamiento privada esté asociada a la subred privada y la tabla de enrutamiento pública, asociada a la subred pública (es una obviedad, pero no está de más verificarlo para evitar errores).
La tabla de enrutamiento de la subred privada sólo tendrá un elemento. El destino 172.31.0.0/16 con el objetivo local.
Route tables

Configuremos ahora las instancias. Crearemos dos para nuestras pruebas. La primera de ellas llamada NAT GW Instance será la que tenga conexión con dos interfaces de red, uno conectado a la red pública y otro a la red privada (El que vemos en la imagen). La segunda instancia sólo tendrá conexión con la red privada.
Tendremos que anotar el interfaz de red que está conectado a la red pública porque será donde tendremos que asignar una dirección IP (Elastic IP) para poder conectarnos desde el exterior.
En la imagen también vemos los detalles del security group. Como es de pruebas, sólo aceptamos conexiones SSH de todo el mundo.
Instancias EC2 públicas y privada

Para simplificar, vamos a asignar el mismo Security Group a los dos interfaces que tenemos conectados a la red privada. Uno de cada instancia. Aunque en la realidad cada uno podrá tener sus propias restricciones de entrada y salida. En esta imagen vemos el interfaz de red privado de nuestra máquina NAT GW con el Security Group (que será el mismo para la otra máquina), en el que aceptamos todo lo que venga de 172.0.0.0/8:

Cómo conectarme a la instancia

Si queremos conectarnos a ellas, podríamos utilizar ProxyCommand junto con SSH o administrarlas desde el servidor web u otra máquina que tenga conectividad con las dos redes. Si, por ejemplo estamos utilizando un servidor RDS de Amazon, esta máquina no tendrá SSH y tendremos que hacerlo así.

Eso sí, estas máquinas privadas, como no tienen conexión con la red pública, tampoco tendrán conexión a Internet. Por lo que, si queremos actualizar su software, realizar instalaciones o, utilizar un servicio online como cliente no podremos.

La solución sería, en este caso, conectar las instancias a una puerta de enlace NAT. Simplificando, tenemos que hacer como nuestro router de casa. Como las máquinas de la red privada no tienen conexión a Internet, ni IP pública, necesitamos que una máquina que esté en las dos redes nos deje utilizar su conexión. Si nos fijamos, todos los dispositivos conectados desde el router de casa están conectando desde la misma IP pública. Nuestras instancias necesitan una IP pública que utilizar.

Cómo conectar las instancias privadas a Internet

Por ahora, nos olvidamos de la instancia pública.
Un primer enfoque puede ser conectando una NAT Gateway a la subred privada. Eso nos dará conectividad a Internet, sin tener que tocar nada en las instancias. Y actuará como un router. Eso sí, tendremos que reservar una EIP y asignársela a esta puerta de enlace para poder trabajar (y las IPs en Amazon están contadas, sólo puedes reservar 5 IPs por zona). Esta es una forma rápida y cómoda de hacerlo. Además, no tienes que preocuparte de la puerta de enlace porque está administrada por Amazon. Eso sí, tiene un coste.

Para ello, tendremos que crear una NAT Gateway y asociarlo a la subred pública (que es donde tenemos enchufada la Internet Gateway). También debemos asociar una EIP:
Crear NAT Gateway

Luego, tendremos que editar las tablas de enrutamiento de nuestra red privada, y añadir para el destino 0.0.0.0/0 como objetivo nuestra nueva nat-gateway:
Editar tablas de enrutamiento

Crear una instancia NAT

Ahora bien. Si no queremos utilizar una NAT Gatewey o queremos dar más funcionalidad. Además, nos puede salir incluso más barato que tener funcionando la NAT Gateway todo el tiempo. Podemos crear una instancia NAT que haga la misma tarea. Dependiendo del tráfico o el procesamiento del mismo que necesitemos podemos contratar una instancia muy pequeña (una t2.micro o t2.nano). Aquí, podemos aprovechar e instalar servicios de firewall o IDS.

Lo primero que debemos hacer es desmarcar la verificación de origen y destino de datos (change Source/Dest. Check) de los dos interfaces de red de nuestra instancia NAT GW. Esto es así porque ahora, esta instancia recibirá y enviará datos que no son para ella, sino para otra máquina dentro de la red. Por lo que esta medida de seguridad ya no aplica:
Source/Dest. check

Ahora, desde nuestra instancia NAT hacemos lo siguiente:

sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -P FORWARD DROP
sudo iptables -A FORWARD -i eth0 -d 172.0.0.0/8 -j ACCEPT
sudo iptables -A FORWARD -i eth1 -s 172.0.0.0/8 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

En este punto podemos elegir si conectar las instancias privadas a mano, o hacerlo automáticamente.

Conectar las instancias privadas a mano

Para ello, accederemos a ellas, por ejemplo con ProxyCommand por SSH. Y luego debemos añadir la IP de nuestra instancia NAT como puerta de enlace y eliminar la puerta de enlace anterior. Para ello:

sudo route add default gw 172.31.21.19
sudo route del default gw 172.16.0.1

Pero esto no es muy cómodo. Y alguna vez puede darnos problemas, aunque es una posible restricción si no queremos que todas las máquinas tengan conexión a Internet.

Conectar las instancias privadas automática

Ahora provocaremos que la dirección por defecto de la puerta de enlace devuelta por DHCP cuando inicia nuestra instancia redirija a nuestra instancia NAT. Por lo que la conectividad será totalmente transparente. Para ello, debemos editar la tabla de enrutamiento de la subred privada haciendo que el destino 0.0.0.0/0 apunte al dispositivo de red de nuestra instancia NAT conectado a la subred privada. Se ve mucho más claro en la imagen:

Con la instancia conectada

Una vez tengamos la instancia privada conectada, ya sea de forma manual o automática. Ya podremos acceder al exterior, por ejemplo con ping o curl.

Entrada o salida de datos

De momento sólo estamos permitiendo tráfico desde nuestra red privada hacia el exterior y viceversa. Aunque en el caso de hacer de puerta de enlace, siempre podemos utilizar esta regla:

sudo iptables -A FORWARD -i eth0 -d 172.0.0.0/8 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i eth1 -s 172.0.0.0/8 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Para asegurarnos de que sólo las conexiones que ha establecido la red interna puedan volver a ella.

Aunque una práctica muy común en estos casos es que, ya que tenemos una máquina que filtra el tráfico. Suponemos que hemos utilizado más reglas de iptables para evitar muchas conexiones simultáneas, estamos rechazando paquetes e IPs que no nos gustan. Podemos utilizar firewalls como APF, servicios como fail2ban o IDS como Snort u OSSEC. Así que esta máquina, nos puede proteger de todo lo malo. O, al menos intentarlo. Eso sí, nos va a quitar muchísimo tráfico erróneo e intentos de penetración a nuestros servicios. Además, de esta forma las máquinas que ejecutan nuestros servicios no estarán 100% expuestas a Internet. Sino que, cuando alguien desde fuera acceda a un determinado puerto de mi máquina NAT Gateway Firewall, podrá acceder al final al servicio que está en la red privada.

Como ejemplo, en la máquina privada (cuya IP privada es 172.31.19.240) vamos a poner un servidor web escuchando en el puerto 80. Primero debemos añadir el puerto 80 al Security Group público de nuestra máquina NAT. Luego en dicha máquina ejecutaremos lo siguiente:

sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 172.31.19.240

Con esto estaremos permitiendo las conexiones desde el exterior por el puerto 80, y seguidamente dirigiendo esa conexión a nuestra máquina privada.

De la misma manera que hablo de un servidor web por el puerto 80, podemos hacerlo con cualquier puerto o servicio. Así aunque nuestra IP externa sea única, podemos tener varios servicios atendidos por varias máquinas diferentes. O incluso puede que nuestra máquina privada, el servicio que debemos atender por el puerto 80 lo tenga abierto en el puerto 8000. Entonces podríamos hacer:

sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 8000 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 172.31.19.240:8000

Aunque hablando de servidores web, también podemos instalar un Apache o Nginx en nuestra máquina NAT Gateway Firewall (aunque ya estamos instalando muchas cosas), y hacer que dicho Apache acceda vía proxy inverso a nuestra máquina privada. Incluso podemos alojar varios servicios y hacer que cada uno de ellos sea atendido por una máquina diferente.

Configuración persistente

Todo esto que hemos hecho se perderá cuando se reinicie el ordenador. Aunque podemos instalar el paquete iptables-persistent y ejecutar:

sudo service iptables-persistent save

Del mismo modo podemos ejecutar un script cuando se inicie el sistema con todas las líneas que hemos ejecutado de iptables. Además, para que el IP Forwarding sea efectivo al arrancar debemos editar /etc/sysctl.conf modificando o añadiendo la línea:

net.ipv4.ip_forward=1

Foto principal: rawpixel.com

También podría interesarte...

Leave a Reply