OpenVPN: настройка OpenVPN Access Server и AWS VPC peering

Автор: | 21/02/2019
 

OpenVPN Access Server предоставляет полностью настроенный и готовый к использованию OpenVPN сервер, который требует минимальной настройки для запуска.

Бесплатная версия разрешает использовать 2 одновременных подключения, если требуется больше пользователей – за денежку.

Сейчас для доступа к нашим ресурсам, таким как Jenkins, Nexus и т.д. используются правила в Security Group-ах, в которых для каждого пользователя приходится добавлять домашний IP.

Такой подход был более-менее адекватным решением, пока команда была небольшая, но с ростом количества девелоперов/QA правил становится всё больше, управлять ими становится всё геморройнее, а потому – пришло время поднять VPN, которым могли бы пользоваться все.

Схема, которую будем строить в этом посте будет выглядет примерно так:

Ниже описывается установка и запуск OpenVPN Access Server (по документации тут>>>), создание VPC-peering-ов и маршрутов.

AWS: запуск OpenVPN AS

Запуск EC2

Находим AMI:

Лицензии можно добавить позже, сейчас используем Free-версию.

Выбираем t2.micro – пока этого достаточно:

VPC

Создаём новую VPC для VPN:

Т.к. будет создаваться VPC-пиринг – убедитесь, что блоки адресов не перекрываются.

В данном случае Jenkins VPC будет 10.0.4.0/24, а сеть для VPC VPN-а – 10.0.9.0/24:

Создаём подсеть в этой VPC:

Настраиваем сеть нового EC2:

Internet Gateway

Добавляем Internet Gateway (IGW):

Подключаем его к созданной ранее VPC:

Route table

Далее – обновляем таблицу маршрутизации (RTB), и добавляем маршрут для трафика в сеть 0.0.0.0/0 (интернет) через созданный IGW.

Переходим к подсети, открываем вкладку Route Table, кликаем на имя таблицы маршрутизации:

Добавляем новый маршрут:

Security Group

AWS предложит уже готовую группу безопасности.

Т.к. это такой себе Proof of Concept – оставим тут всё по умолчанию:

  • TCP 22 — SSH
  • TCP 943 — порт для доступа к админ-панели OpenVPN  AS сервиса
  • TCP 443 — порт для доступа к пользовательскому интерфейсу OpenVPN  AS сервиса
  • UDP 1194 — OpenVPN UDP порт, к которому будут подключаться VPN-клиенты

В нормальном варианте – доступ к админ части и SSH следует ограничить доверенными IP.

Запускаем машину, создаём ключ доступа:

Elastic IP

Добавим EIP для доступа к хосту:

Подключаем его к инстансу:

Отключение Source/Destination check

Для корректной работы NAT-а – отключаем проверку адресов (см. посты AWS: миграция RTFM 2.5 — настройка NAT на Bastion EC2 как замена NAT Gateway и AWS: миграция RTFM 2.7 — CloudFormation и Ansible — наcтройка NAT):

На этом с EC2 закончили – переходим к настройке самого OpenVPN AS.

Настройка OpenVPN AS

Подключаемся к хосту, используя логин openvpnas:

[simterm]

$ ssh -i dev-vpn-eu-west-1.pem [email protected]

[/simterm]

Читаем 🙂 лицензионное соглашение, принимаем его:

Инициализация и первичная настройка

При первом логине – OpenVPN AS сам запустит мастер настройки.

При необходимости – его можно вызвать потом с помощью ovpn-init:

[simterm]

$ sudo ovpn-init --ec2

[/simterm]

По сути – сейчас везде можно принимать значения по умолчанию:

  1. Will this be the primary Access Server node? // yes
  2. Please specify the network interface and IP address to be
    used by the Admin Web UI:
    (1) all interfaces: 0.0.0.0
    (2) eth0: 10.0.9.8
    // 2
  3. Please specify the port number for the Admin Web UI.
    // yes – 943
  4. Please specify the TCP port number for the OpenVPN Daemon
    // yes – 443
  5. Should client traffic be routed by default through the VPN?
    // no – нет – мы будем роутить толкьо трафик к нашим собственным ресурсам, на ВК пользоватли пусть ходят через свой VPN 🙂
  6. Should client DNS traffic be routed by default through the VPN?
    // no
  7. Use local authentication via internal DB?
    // yes
  8. Private subnets detected: [‘10.0.9.0/24’]
    Should private subnets be accessible to clients by default?
    // yes
  9. Do you wish to login to the Admin UI as “openvpn”?
    // yes
  10. > Please specify your OpenVPN-AS license key (or leave blank to specify later):
    // оставляем пустым, при необходимости добавим ключ потом

Задаём пароль пользоватея openvpn:

[simterm]

openvpnas@openvpnas2:~$ sudo passwd openvpn
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully

[/simterm]

Теперь можно открыть панель управления – https://52.18.110.226:943/admin.

Т.к. мы не настраивали имена хоста и прочее – соглашаемся:

Your connection is not private

Attackers might be trying to steal your information from 52.18.110.226 (for example, passwords, messages, or credit cards). Learn more

NET::ERR_CERT_AUTHORITY_INVALID

Логинимся в панель управления, используя логин openvpn и пароль, который задали чуть ранее через passwd:

Подключение VPN-клиента

Открываем страницу доступа пользователя (без /admin в конце) – https://52.18.110.226:943/?src=connect:

Кликаем на Yourself (user-locked profile) – загружаем файл настроек OpenVPN-клиента client.ovpn:

Его содержимое:

[simterm]

$ cat ~/.openvpn/client.ovpn                                                                                                                 
# Automatically generated OpenVPN client config file
# Generated on Wed Feb 20 15:19:38 2019 by openvpnas2

# Default Cipher
cipher AES-256-CBC
# Note: this config file contains inline private keys
#       and therefore should be kept confidential!
# Note: this configuration is user-locked to the username below
# OVPN_ACCESS_SERVER_USERNAME=openvpn
....

[/simterm]

Устанавливаем openvpn на локальной машине, тут установка на Arch Linux:

[simterm]

$ sudo pacman -S openvpn

[/simterm]

Запускаем его  сопцией --auth-user-pass:

[simterm]

$ sudo openvpn --config ~/.openvpn/client.ovpn --auth-user-pass
Wed Feb 20 17:22:42 2019 OpenVPN 2.4.6 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Apr 24 2018
Wed Feb 20 17:22:42 2019 library versions: OpenSSL 1.1.1a  20 Nov 2018, LZO 2.10
Enter Auth Username: openvpn
Enter Auth Password: *******
...
Wed Feb 20 17:22:51 2019 ROUTE_GATEWAY 172.16.64.1/255.255.252.0 IFACE=wlp2s0 HWADDR=10:f0:05:64:0a:73
Wed Feb 20 17:22:51 2019 TUN/TAP device tun0 opened
Wed Feb 20 17:22:51 2019 TUN/TAP TX queue length set to 100
Wed Feb 20 17:22:51 2019 do_ifconfig, tt->did_ifconfig_ipv6_setup=0
Wed Feb 20 17:22:51 2019 /usr/bin/ip link set dev tun0 up mtu 1500
Wed Feb 20 17:22:51 2019 /usr/bin/ip addr add dev tun0 172.27.232.3/21 broadcast 172.27.239.255
Wed Feb 20 17:22:56 2019 ROUTE remote_host is NOT LOCAL
Wed Feb 20 17:22:56 2019 /usr/bin/ip route add 52.18.110.226/32 via 172.16.64.1
Wed Feb 20 17:22:56 2019 /usr/bin/ip route add 10.0.9.0/24 metric 101 via 172.27.232.1
Wed Feb 20 17:22:56 2019 /usr/bin/ip route add 172.27.224.0/20 metric 101 via 172.27.232.1
Wed Feb 20 17:22:56 2019 Initialization Sequence Completed

[/simterm]

Проверяем маршрутизацию трафика.

Сначала на CloudFlare – должен пойти через офисный шлюз:

[simterm]

$ traceroute 1.1.1.1
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
 1  _gateway (172.16.64.1)  3.109 ms  3.213 ms  3.428 ms
 2  ru-german.relc.com (194.183.169.25)  4.771 ms  5.148 ms  6.039 ms
 3  * * *
 4  ex4.thinx.pl (212.91.2.13)  16.468 ms  16.778 ms  17.277 ms
 5  cloudflare.thinx.pl (212.91.0.28)  23.842 ms  24.154 ms  24.386 ms
 6  one.one.one.one (1.1.1.1)  17.787 ms  15.023 ms  15.199 ms

[/simterm]

И к хосту VPN – должен идти напрямую:

[simterm]

$ traceroute 10.0.9.8
traceroute to 10.0.9.8 (10.0.9.8), 30 hops max, 60 byte packets
 1  10.0.9.8 (10.0.9.8)  52.095 ms  52.149 ms  53.512 ms

[/simterm]

Отлично.

Маршрутизация трафика через VPN-туннель

Для теста – добавим ещё один EC2-инстанс в той же сети, где находится наш VPN:

Проверим маршруты к нему.

В логах запуска локального VPN-клиента мы видим создание нового маршрута в нашей системе:

Wed Feb 20 17:22:56 2019 /usr/bin/ip route add 172.27.224.0/20 metric 101 via 172.27.232.1

Проверяем – пробуем SSH, используя приватный IP нового инстанса:

[simterm]

$ ssh -i dev-vpn-eu-west-1.pem [email protected]
The authenticity of host '10.0.9.6 (10.0.9.6)' can't be established.
ECDSA key fingerprint is SHA256:6ldjTtHvQJviBb/9aXwFvwh7nwKjOdpePCxO6TddAJA.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.9.6' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1021-aws x86_64)
...
ubuntu@ip-10-0-9-6:~$

[/simterm]

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

VPC peering

Следующим шагом – требуется настроить VPC-пиринг и маршрутизацию трафика между рабочей машиной, VPN-сервером и VPC, в которой находится наш Jenkins.

VPC-пиринг описан тут>>>,

Создаём новый VPC peering connection:

Принимаем запрос на пиринг:

VPC-peering маршрутизация

Если попробовать подключиться к Jenkins сейчас, используя его приватный IP – ничего не получится:

[simterm]

ubuntu@ip-10-0-9-6:~$ ssh [email protected]
ssh: connect to host 10.0.4.13 port 22: Connection timed out

[/simterm]

Так как не созданы маршруты между сетями 10.0.9.0/24 (OpenVPN VPC) и 10.0.4.0/24 (Jenkins VPC).

Требуется обновить таблицы маршрутизации для двух сетей:

  1. таблица маршрутизации подсети Jenkins – 10.0.4.0/28 => 10.0.9.0/24 через созданный VPN пиринг
  2. таблица маршрутизации подсети OpenVPN  – 10.0.4.0/28 => 10.0.9.0/24 через созданный VPN пиринг

Редактируем таблицу jenkins rtb-9597e6ec | jenkins-dev-route-table:

Добавляем маршрут:

Повторяем для VPN RTB:

Проверяем из сети VPN:

[simterm]

ubuntu@ip-10-0-9-6:~$ ping 10.0.4.13
PING 10.0.4.13 (10.0.4.13) 56(84) bytes of data.
64 bytes from 10.0.4.13: icmp_seq=1 ttl=64 time=0.470 ms
64 bytes from 10.0.4.13: icmp_seq=2 ttl=64 time=0.483 ms

[/simterm]

И обратно – с Jenkins:

[simterm]

admin@jenkins-dev:~$ ping 10.0.9.6
PING 10.0.9.6 (10.0.9.6) 56(84) bytes of data.
64 bytes from 10.0.9.6: icmp_seq=1 ttl=64 time=0.437 ms
64 bytes from 10.0.9.6: icmp_seq=2 ttl=64 time=0.914 ms

[/simterm]

Помним, что у Jenkins есть своя группа безопасности – обновляем в ней правила,  и разрешаем доступ из VPN-сети.

Пробуем SSH с хоста в сети VPN:

[simterm]

ubuntu@ip-10-0-9-6:~$ ssh [email protected]
The authenticity of host '10.0.4.13 (10.0.4.13)' can't be established.
ECDSA key fingerprint is SHA256:+0LP1+neT4udq96jFLdLpjuvTrWCzlAt5GZZpfw2rKI.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.4.13' (ECDSA) to the list of known hosts.
[email protected]: Permission denied (publickey).

[/simterm]

И обратно:

[simterm]

admin@jenkins-dev:~$ ssh 10.0.9.6
The authenticity of host '10.0.9.6 (10.0.9.6)' can't be established.
ECDSA key fingerprint is SHA256:6ldjTtHvQJviBb/9aXwFvwh7nwKjOdpePCxO6TddAJA.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.9.6' (ECDSA) to the list of known hosts.
Permission denied (publickey).

[/simterm]

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

VPN маршруты

Возвращаемся к нашей рабочей машинке, проверяем – как пойдёт трафик к хосту Jenkins, используя приватный IP:

[simterm]

$ traceroute 10.0.4.13
traceroute to 10.0.4.13 (10.0.4.13), 30 hops max, 60 byte packets
 1  _gateway (172.16.64.1)  3.243 ms  3.453 ms  3.656 ms
 2  ru-german.relc.com (194.183.169.25)  3.962 ms  4.221 ms  4.642 ms
...

[/simterm]

Идёт через шлюз офиса, что нам не подходит.

Переходим в VPN admin => VPN Settingshttps://52.18.110.226:943/admin/vpn_settings:

Добавляем NAT-правило для 10.0.4.0/24:

Сохраняем, жмём Update Running Server:

Перезапускаем локальный клиент:

[simterm]

$ sudo openvpn --config ~/.openvpn/client.ovpn --auth-user-pass
...
Wed Feb 20 18:25:37 2019 ROUTE remote_host is NOT LOCAL
Wed Feb 20 18:25:37 2019 /usr/bin/ip route add 52.18.110.226/32 via 172.16.64.1
Wed Feb 20 18:25:37 2019 /usr/bin/ip route add 10.0.4.0/24 metric 101 via 172.27.232.1
Wed Feb 20 18:25:37 2019 /usr/bin/ip route add 10.0.9.0/24 metric 101 via 172.27.232.1
Wed Feb 20 18:25:37 2019 /usr/bin/ip route add 172.27.224.0/20 metric 101 via 172.27.232.1
Wed Feb 20 18:25:37 2019 Initialization Sequence Completed

[/simterm]

Вот новый маршрут – 10.0.4.0/24 metric 101 via 172.27.232.1.

Проверяем локальную таблицу маршрутизации:

[simterm]

18:26:28 [setevoy@setevoy-arch-work ~]  $ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.64.1     0.0.0.0         UG    303    0        0 wlp2s0
10.0.4.0        172.27.232.1    255.255.255.0   UG    101    0        0 tun0
10.0.9.0        172.27.232.1    255.255.255.0   UG    101    0        0 tun0
52.18.110.226   172.16.64.1     255.255.255.255 UGH   0      0        0 wlp2s0

[/simterm]

Проверяем трассу:

[simterm]

$ traceroute 10.0.4.13
traceroute to 10.0.4.13 (10.0.4.13), 30 hops max, 60 byte packets
 1  172.27.232.1 (172.27.232.1)  55.090 ms  55.207 ms  55.399 ms
...

[/simterm]

Трафик пошёл через шлюз самого OpenVPN.

Проверяем SSH, используя приватный IP:

[simterm]

18:27:41 [setevoy@setevoy-arch-work ~]  $ ssh -i jenkins-dev-eu-west-1.pem [email protected]
...
admin@jenkins-dev:~$

[/simterm]

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

DNS

Последний момент – это настройки DNS.

Т.к. наш Jenkins доступен и из мира по публичному IP, и через VPN – по приватному, то возникает вопрос с резолвом имени.

См. пост OpenVPN: настройки DNS и dnsmasq.