AWS: миграция RTFM 2.5 – настройка NAT на Bastion EC2 как замена NAT Gateway

By | 10/16/2017
 

Для доступа в Интернет из приватной сети AWS предоставляет две возможности – NAT Gateway и NAT инстансы.

Сравнение между ними можно почитать тут>>>. Насколько я в курсе – NAT инстансы от AWS появились раньше, а NAT Gateway для VPC – году в 2015. До этого – требовалась ручная настройка NAT на своём инстансе в публичной сети.

Собственно – это и будет задачей на сегодня. Основная цель – уменьшить расходы на инфраструктуру, ибо NAT GW тоже стоит денег.

Дальше выполним:

  1. создадим вручную VPC с двумя подсетями и инстансами в них
  2. настроим NAT трансляцию на инстансе в публичной сети
  3. настроим таблицу маршрутизации для приватной сети на инстанс в публичной сети

Ещё надо будет написать Ansible роль для Bastion хоста для настройки NAT на нём и обновить CloudFormation шаблон для стека RTFM – убрать NAT Gateway и обновить таблицу маршрутизации.

Создание VPC, подсетей, инстансов

VPC

Быстренько делаем всё через веб-консоль.

Создаём VPC:

Subnets

Создаём две подсети в этой VPC – публичную и приватную:

Internet Gateway

Создаём Internet Gateway для доступа VPC к интернету:

Подключаем этот IGW к VPC:

Route Tables

Создаём две таблицы маршрутизации – для публичной и приватной подсетей.

Public Route Table

Таблица для публичной подсети:

Подключаем её к публичной подсети:

Во вкладке Routes добавляем маршрут 0.0.0.0/0 через созданный ранее IGW:

Private Route Table

Аналогично – создаём таблицу для приватной посети, но пока не меняем в ней маршруты – обновим после создания EC2 инстанса, который будет работать в роли NAT-шлюза:

Подключаем её к private subnet:

EC2 инстансы

Запускем два EC2. Один – в публичной сети, он и будет нашим NAT-шлюзом, второй – в приватной подсети.

Первый инстанс:

VPC – nat-test, подсеть – public, присвоить публичный IP – enable:

Второй интстанс – та же VPC, но приватная подсеть, Public IP disable:

В настройках Security Group – разрешаем доступ только из SG публичного инстанса:

Для сетевого интерфейса nat-gw инстанса – отключаем проверку Source/Destination, что бы он мог играть роль NAT-gateway:

Возвращаемся к таблице маршрутизации приватной посети, и задаём маршрут 0.0.0.0/0 через nat-gw инстанс:

Переходим к Security Group nat-gw инстанса, и задаём два правила – 22 отовсюду, и весь трафик для security group инстанса в приватной сети:

Т.е, у нас есть две группы безопасности:

  1. nat-test-sg – SG для NAT-инстанса, которая разрешает:
    • SSH из сети 0.0.0.0/0
    • весь трафик из SG nat-test-sg-priv
  2. nat-test-sg-priv – SSH из сети nat-test-sg

Понятно, что если будут сервисы типа NGINX на сервере в публичной сети – то добавляем  порты 80 и 443 в группу nat-test-sg, и если какая-то MySQL на инстансе в приватной сети – то добавляем 3306 для доступа из nat-test-sg.

Тут всё готово.

Настройка NAT на EC2

Логинимся на EC2 в публичной сети:

ssh ubuntu@34.250.81.116 -i .ssh/rtfm-dev.pem
...
ubuntu@ip-10-0-0-245:~$ sudo -s
sudo: unable to resolve host ip-10-0-0-245
root@ip-10-0-0-245:~#

Проверяем интернет на нём:

root@ip-10-0-0-245:~# ping -c 1 ya.ru
PING ya.ru (87.250.250.242) 56(84) bytes of data.
64 bytes from ya.ru (87.250.250.242): icmp_seq=1 ttl=45 time=47.6 ms
--- ya.ru ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 47.687/47.687/47.687/0.000 ms

Копируем на него ключ и логинимся на инстанс в приватной подсети:

root@ip-10-0-0-245:~# ssh ubuntu@10.0.1.7 -i .ssh/rtfm.dev.pem
...
ubuntu@ip-10-0-1-7:~$

Проверяем доступ в интернет – должен сфейлится, т.к. NAT ещё не настроен:

ubuntu@ip-10-0-1-7:~$ ping -c 1 ya.ru
PING ya.ru (87.250.250.242) 56(84) bytes of data.
--- ya.ru ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

ОК, всё хорошо – доступа нет. Возвращаемся на nat-gw, проверяем таблицу nat в IPTABLES:

root@ip-10-0-0-245:~# iptables -vL -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 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

Настраиваем NAT:

root@ip-10-0-0-245:~# echo 1 > /proc/sys/net/ipv4/ip_forward
root@ip-10-0-0-245:~# iptables --table nat --append POSTROUTING --source 10.0.0.0/16 --destination 0.0.0.0/0 --jump MASQUERADE

Проверяем правила таблицы ещё раз:

root@ip-10-0-0-245:~# iptables -vL -t nat
Chain PREROUTING (policy ACCEPT 33 packets, 2676 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain INPUT (policy ACCEPT 3 packets, 188 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 4 packets, 307 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
4   307 MASQUERADE  all  --  any    any     10.0.0.0/16          anywhere

Снова переходим на приватный инстанс – проверяем ещё раз:

ubuntu@ip-10-0-1-7:~$ ping -c 1 ya.ru
PING ya.ru (87.250.250.242) 56(84) bytes of data.
64 bytes from ya.ru (87.250.250.242): icmp_seq=1 ttl=41 time=45.9 ms
--- ya.ru ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 45.996/45.996/45.996/0.000 ms

Всё работает.

NAT on startup

Последний штрих – добавить включение NAT при рестарте NAT-инстанса.

Создаём каталог для правил IPTABLES:

mkdir /etc/iptables

Сохраняем правила:

iptables-save > /etc/iptables/iptables.rules

Находим исполняемый файл iptables-restore:

which iptables-restore
/sbin/iptables-restore

Создаём systemd-сервис iptables:

mkdir /usr/lib/systemd/system
vim /usr/lib/systemd/system/iptables.service

Указываем:

[Unit]
Description=Packet Filtering Framework
Before=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables/iptables.rules
ExecReload=/sbin/iptables-restore /etc/iptables/iptables.rules
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Проверяем:

systemd-analyze verify /usr/lib/systemd/system/iptables.service

Добавляем в автозапуск:

systemctl enable iptables.service
Created symlink from /etc/systemd/system/multi-user.target.wants/iptables.service to /usr/lib/systemd/system/iptables.service.

Обновляем /etc/sysctl.conf, добавляем forwading постоянно:

...
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
...

Сохраняем, перезагружаем машину:

root@ip-10-0-0-245:~# reboot
Connection to 34.250.81.116 closed by remote host.
Connection to 34.250.81.116 closed.

После перезагрузки проверяем статус IPTABLES:

ubuntu@ip-10-0-0-245:~$ systemctl status iptables.service
● iptables.service - Packet Filtering Framework
Loaded: loaded (/usr/lib/systemd/system/iptables.service; enabled; vendor preset: enabled)
Active: active (exited) since Mon 2017-10-16 11:56:35 UTC; 59s ago
Process: 828 ExecStart=/sbin/iptables-restore /etc/iptables/iptables.rules (code=exited, status=0/SUCCESS)
Main PID: 828 (code=exited, status=0/SUCCESS)
Tasks: 0
Memory: 0B
CPU: 0
CGroup: /system.slice/iptables.service
Oct 16 11:56:35 ip-10-0-0-245 systemd[1]: Starting Packet Filtering Framework...
Oct 16 11:56:35 ip-10-0-0-245 systemd[1]: Started Packet Filtering Framework.

Правила:

ubuntu@ip-10-0-0-245:~$ sudo iptables -vL -t nat
sudo: unable to resolve host ip-10-0-0-245
Chain PREROUTING (policy ACCEPT 8 packets, 1098 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain INPUT (policy ACCEPT 2 packets, 148 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 7 packets, 502 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
7   502 MASQUERADE  all  --  any    any     10.0.0.0/16          anywhere

И доступ в интернет с инстанса в приватной сети:

ubuntu@ip-10-0-0-245:~$ ssh -t ubuntu@10.0.1.7 -i .ssh/rtfm.dev.pem "ping -c 1 ya.ru"
PING ya.ru (87.250.250.242) 56(84) bytes of data.
64 bytes from ya.ru (87.250.250.242): icmp_seq=1 ttl=41 time=48.2 ms
--- ya.ru ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 48.291/48.291/48.291/0.000 ms
Connection to 10.0.1.7 closed.

Всё работает.

P.S. не забываем удалить все тестовые ресурсы 🙂