Для доступа в Интернет из приватной сети AWS предоставляет две возможности – NAT Gateway и NAT инстансы.
Сравнение между ними можно почитать тут>>>. Насколько я в курсе – NAT инстансы от AWS появились раньше, а NAT Gateway для VPC – году в 2015. До этого – требовалась ручная настройка NAT на своём инстансе в публичной сети.
Собственно – это и будет задачей на сегодня. Основная цель – уменьшить расходы на инфраструктуру, ибо NAT GW тоже стоит денег.
Дальше выполним:
- создадим вручную VPC с двумя подсетями и инстансами в них
- настроим NAT трансляцию на инстансе в публичной сети
- настроим таблицу маршрутизации для приватной сети на инстанс в публичной сети
Ещё надо будет написать 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 инстанса в приватной сети:
Т.е, у нас есть две группы безопасности:
- nat-test-sg – SG для NAT-инстанса, которая разрешает:
- SSH из сети 0.0.0.0/0
- весь трафик из SG nat-test-sg-priv
- nat-test-sg-priv – SSH из сети nat-test-sg
Понятно, что если будут сервисы типа NGINX на сервере в публичной сети – то добавляем порты 80 и 443 в группу nat-test-sg, и если какая-то MySQL на инстансе в приватной сети – то добавляем 3306 для доступа из nat-test-sg.
Тут всё готово.
Настройка NAT на EC2
Логинимся на EC2 в публичной сети:
[simterm]
$ ssh [email protected] -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:~#
[/simterm]
Проверяем интернет на нём:
[simterm]
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
[/simterm]
Копируем на него ключ и логинимся на инстанс в приватной подсети:
[simterm]
root@ip-10-0-0-245:~# ssh [email protected] -i .ssh/rtfm.dev.pem ... ubuntu@ip-10-0-1-7:~$
[/simterm]
Проверяем доступ в интернет – должен сфейлится, т.к. NAT ещё не настроен:
[simterm]
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
[/simterm]
ОК, всё хорошо – доступа нет. Возвращаемся на nat-gw, проверяем таблицу nat
в IPTABLES:
[simterm]
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
[/simterm]
Настраиваем NAT:
[simterm]
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
[/simterm]
Проверяем правила таблицы ещё раз:
[simterm]
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
[/simterm]
Снова переходим на приватный инстанс – проверяем ещё раз:
[simterm]
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
[/simterm]
Всё работает.
NAT on startup
Последний штрих – добавить включение NAT при рестарте NAT-инстанса.
Создаём каталог для правил IPTABLES:
[simterm]
# mkdir /etc/iptables
[/simterm]
Сохраняем правила:
[simterm]
# iptables-save > /etc/iptables/iptables.rules
[/simterm]
Находим исполняемый файл iptables-restore
:
[simterm]
# which iptables-restore /sbin/iptables-restore
[/simterm]
Создаём systemd-сервис iptables
:
[simterm]
# mkdir /usr/lib/systemd/system # vim /usr/lib/systemd/system/iptables.service
[/simterm]
Указываем:
[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
Проверяем:
[simterm]
# systemd-analyze verify /usr/lib/systemd/system/iptables.service
[/simterm]
Добавляем в автозапуск:
[simterm]
# systemctl enable iptables.service Created symlink from /etc/systemd/system/multi-user.target.wants/iptables.service to /usr/lib/systemd/system/iptables.service.
[/simterm]
Обновляем /etc/sysctl.conf
, добавляем forwading постоянно:
... # Uncomment the next line to enable packet forwarding for IPv4 net.ipv4.ip_forward=1 ...
Сохраняем, перезагружаем машину:
[simterm]
root@ip-10-0-0-245:~# reboot Connection to 34.250.81.116 closed by remote host. Connection to 34.250.81.116 closed.
[/simterm]
После перезагрузки проверяем статус IPTABLES:
[simterm]
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.
[/simterm]
Правила:
[simterm]
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
[/simterm]
И доступ в интернет с инстанса в приватной сети:
[simterm]
ubuntu@ip-10-0-0-245:~$ ssh -t [email protected] -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.
[/simterm]
Всё работает.
P.S. не забываем удалить все тестовые ресурсы 🙂