- Начальные настройки
- Dns aliase mode
- Dns api mode
- Playbook для получения сертификатов
- Playbook для распространения сертификатов
- Безопасность и шифрование
- Готовим оборудование для установки openvpn
- Запуск openvpn-gui
- Запуск демона openvpn
- Запуск клиента openvpn
- Инициализация протокола диффи — хеллмана на эллиптических кривых
- Использование let’s encrypt для внутренних серверов
- Компоненты сети openvpn
- Мониторинг сертификатов
- Настройка apache 2 для использования сертификатов
- Настройка аутентификации клиентов
- Немного теории
- Ответ по протоколу диффи — хеллмана на эллиптических кривых
- Полезные ссылки
- Проверка результата запуска демона openvpn
- Создание запроса на сертификат
- Создание инфраструктуры публичных ключей pki
- Установка openvpn-gui
- Установка прокси-сервера squid
- Создание списка отзывов сертификатов
Начальные настройки
Сперва заполним файл /root/.rnd, который используется как источник начальных случайных значений в генераторе псевдослучайных чисел OpenSSL. Суть использования этого файла описана на сайте OpenSSL. Нам надо заполнить свой файл случайными данными, как вариант — скопировав из /dev/urandom 32768 байт в файл .rnd таким образом:
Далее создадим сертификат для CA:
root@shpc:/opt/simple_CA# openssl req -newkey rsa:4096-keyform PEM -keyout ca.key -x509-days3650-outform PEM -out ca.cer
Опции для сертификата берутся из файла /etc/ssl/openssl.cnf. Сам файл довольно большой, мы не будем приводить здесь его содержимое. В реальности стоит создать свой конфигурационный файл с необходимыми опциями и блоками — и использовать его для генерации сертификатов.
На выходе получим два файла: ключ и сертификат.
Оба файла надо беречь. Если они попадут к злоумышленнику, он сможет использовать их для генерации сертификатов. Посмотреть сертификат можно при помощи этой команды (вывод обрезан для краткости):
root@shpc:/opt/simple_CA# openssl x509 -text-noout-in ca.cer
Далее на основе полученного сертификата (напомним, что это сертификат корневого CA) можно сгенерировать сертификат для сервера. Вначале генерируем закрытый ключ для сервера:
root@shpc:/opt/simple_CA# openssl genrsa -out server.key 4096
Теперь используем этот ключ для генерации запроса на выдачу сертификата (CSR):
root@shpc:/opt/simple_CA# openssl req -new-key server.key -out server.req -sha256
Отметим, что данные, которые вы вводите в поля, должны совпадать со значениями в тех полях, что указывались при создании сертификата корневого сервера. Теперь возьмём корневой сертификат CA и запрос — и сгенерируем на их основе сертификат для сервера:
root@shpc:/opt/simple_CA# openssl x509 -req-in server.req -CA ca.cer -CAkey ca.key -set_serial 100-extensions server -days1460-outform PEM -out server.cer -sha256
Должно получиться 5 файлов.
Файл server.req можно удалить — а при необходимости создать заново. Теперь надо перенастроить веб-сервер для работы с сертификатами.
Dns aliase mode
Это модернизированный режим DNS API.
Идея такая: Есть технический домен, через добавления TXT записей на котором мы подтверждаем владение основным доменом. т.е. acme.sh смотрит CNAME запись у основного домена, видит “перенаправление” на технический домен и идёт к нему проверять TXT запись. А дальше всё как в режиме DNS API.

Разберём последовательно. Для демонстрации я купил домен tech-domain.club, он выступает в качестве технического домена. В моём примере основной домен itdog.info располагается на namecheap, а техничский tech-domain.club я делегирую на Hetzner DNS, таким образом операции с записями будут производиться через API Hetzner’a.
В записях основного домена мы добавляем CNAME запись, которая указывает на технический домен
_acme-challenge CNAME _acme-challenge.tech-domain.clubДля провайдера с техническим доменом мы настраиваем доступ к API.
Экспортируем токен Hetzner export HETZNER_Token=”TOKEN”
Команда выглядит так (-f и –test опять же для примера)
acme.sh --issue -d *.itdog.info --challenge-alias tech-domain.club --dns dns_hetzner -f --testРаскрыть
CNAME запись удалять не нужно, она будет использоваться при каждом обновлении сертификата. Таким образом, вы можете иметь несколько доменов с настроенной CNAME записью на один технический домен и с его помощью получать сертификаты для всех.
Кстати, если вам нужно в одном файле иметь несколько сертификатов, например и itdog.info и wildcard *.itdog.info, то просто перечислите их с -d, например
acme.sh --issue --challenge-alias tech-domain.club --dns hetzner -d *.itdog.info -d itdog.infoЭто правило действует и для других методов.
И так, что даёт нам этот режим:
Если у вашего провайдера нет API или лень писать скрипт, возьмите технический домен, делегируйте его на сервис, который поддерживает acme.sh
Если у вашего провайдера нет настройки прав для доступа через API, то технический домен тоже выручает. В случае, если наш token утечёт, у злоумышленника будет доступ только к вашему техническому домену, и если вы его используете только для acme.sh, то максимум что сможет сделать злоумышленник – получить ключ и сертификат для вашего домена. Это тоже неприятно и можно использовать, но это совершенно другой уровень угрозы, по сравнению с полным доступом к доменной зоне
В ситуации с кучей доменов на одном или нескольких провайдерах, жизнь так же становится проще, когда все они просто имеют CNAME запись
Есть так же режим domain-alias, он даёт возможность использовать не _acme-challenge запись, а кастомную, подробности можно прочитать в документации
Dns api mode
Как это работает? Принцип действия тот же самый что у manual, только acme.sh сам вносит и удаляет TXT запись с помощью API вашего dns провайдера.

Под DNS хостингом и DNS провайдером я буду иметь в виду сервис, в который вносятся DNS записи. Это может быть и DNS хостинг, который есть почти у каждой компании, торгующей доменами (namecheap, beget итд) или как отдельный сервис за деньги (Amazon Route 53, ClouDNS итд), или же ваш собственный сервис развернутый с помощью BIND, PowerDNS итд.
Playbook для получения сертификатов
В vars указывается только технический домен, эта переменная используется несколько раз. Токен от API вынесен в отдельный vars файл, что бы хранить его в зашифрованном виде в git. Task “Date and time” нужен для логирования, что бы понимать когда именно что-то пошло не так.
Домены, которые должны подходить как для обычного, так и для wildcard идут по втором taks, тоже с помощью loop. Если вам нужно например wilcard вида *.*.itdog.info, то просто добавьте ещё один -d и ещё один subkey в item. Опция ignore_errors необходима, потому что exit code 0 будет только 6 раз за год при обновлении сертификата, в остальное время будут сообщения о том, что сертификат не нужно обновлять, для ansible это ошибка на которой он будет останавливаться.
Для чего плейбук на получение? Ведь в acme.sh и так уже всё настроено!
В одном плейбуке мы собираем всю нашу конфигурацию, доступы и все домены, которым необходим TLS, как минимум, это удобно – не надо копаться конфигах acme.sh. В случае изменения, например, токена, мы просто редактируем его в vars_files, а если нужно добавить ещё один доменподомен, мы просто добавляем его в loop. Ну и в случае переноса сервера, не нужно переносить ~/.acme.sh, только плейбуки с vars_files взять из git.
Playbook для распространения сертификатов
Здесь нужно писать конечно под вашу инфраструктуру, поэтому повторюсь, показываю это для примера.
Три типа серверов из моей инфраструктуры:
Первый кейс самый простой, мы сами пишем конфигурацию nginx и можем куда угодно положить сертификаты и как угодно назвать их. При обновлении сертификата, требуется сделать nginx -s reload
Во втором случае всё плюс-минус так же, но уже нужно сделать docker exec project-nginx -s reload, т.е. уже другой handler.
В третьем случае у нас помимо handler в контейнере, ещё нужно дать сертификату с ключом определённое имя, потому что оно прописано в их конфигурации, которую лучше не трогать, чтоб не было проблем при обновлении.
В моём случае доменов много, пути, по которым сертификаты с ключами хранятся, различаются. Так же есть случаи когда у одного сервера несколько доменов. Что бы была возможность настроить для каждого хоста свой путь и необходимый домен, в hosts для каждого хоста заданы переменные пути и домена.
nginx.itdog.info tls_path=/etc/letsencrypt/*.itdog.info/ DOMAIN=*.itdog.infoДля случаев, когда доменов на сервере несколько, делается два хоста с разными именами и одинаковым ansible_host (Совет, как сделать лучше, приветствуется).
Безопасность и шифрование
Безопасность и шифрование в OpenVPN обеспечивается библиотекой OpenSSL и протоколом транспортного уровня Transport Layer Security (TLS). Вместо OpenSSL в новых версиях OpenVPN можно использовать библиотеку PolarSSL. Протокол TLS представляет собой усовершенствование протокола защищенной передачи данных уровня защищенных сокетов Secure Socket Layers (SSL).
В OpenSSL может использоваться симметричная и ассиметричная криптография.
В первом случае перед началом передачи данных на все узлы сети необходимо поместить одинаковый секретный ключ. При этом возникает проблема безопасной передачи этого ключа через небезопасный Интернет.
Во втором случае у каждого участника обмена данными есть два ключа — публичный (открытый) и приватный (секретный).
Публичный ключ используется для зашифрования данных, а приватный — для расшифрования. В основе шифрования лежит довольно сложная математика. Выбранный в SSL/TLS алгоритм зашифрования публичным ключом обеспечивает возможность расшифрования только с помощью приватного ключа.
Приватный ключ секретный, и должен оставаться в пределах узла, на котором он создан. Публичный ключ должен передаваться участникам обмена данными.
Для безопасной передачи данных необходимо идентифицировать стороны, принимающие участие в обмене данными. В противном случае можно стать жертвой так называемой “атаки посредника” (Man in the Middle, MITM). В ходе такой атаки злоумышленник подключается к каналу передачи данных и прослушивает его. Он также может вмешиваться, удалять или изменять данные.
Чтобы обеспечить аутентификацию (проверку подлинности пользователя) протокол TLS использует инфраструктуру публичных ключей (Public Key Infrastructure, PKI) и асимметричную криптографию.
Нужно осознавать, что расшифрование данных без наличия приватного ключа тоже возможно, например, методом последовательного перебора. Хотя такой метод и требует больших вычислительных ресурсов, это только вопрос времени, когда данные смогут быть расшифрованы.
Хотя размер ключа влияет на сложность расшифрования, никакой ключ не дает гарантии полной безопасности данных. Кроме того, существует возможность похищения уже расшифрованных данных и ключей за счет уязвимостей и закладок в операционной системе или прикладном ПО, а также в аппаратном обеспечении серверов и рабочих станций.
Шифрование данных увеличивает трафик и замедляет обмен данными. Чем больше длина ключа, применяемого для шифрования данных, тем труднее будет его подобрать, но и тем заметнее получится замедление обмена данными.
Готовим оборудование для установки openvpn
Если вы впервые настраиваете сеть VPN, лучше всего экспериментировать на виртуальных машинах VDS. Это могут быть VDS, созданные локально на вашем компьютере или на сервере в вашей сети, либо арендованные у провайдера. Перед арендой VDS поинтересуйтесь, поддерживается ли драйвер TUN/TAP. Некоторые провайдеры требуют дополнительной оплаты для подключения TUN/TAP.
На рис. 1. мы показали схему стенда, на котором будем устанавливать компоненты и узлы OpenVPN (имена и адреса IP хостов могут быть другими).
Рис. 1. Стенд для изучения OpenVPN.
Здесь изображены три узла (хоста), для каждого из которых потребуется отдельный VDS:
Хосты клиента и сервера VPN соединены обычным, небезопасным каналом. В случае макета это может быть локальная сеть, в реальной жизни — канал сети Интернет. ПО OpenVPN создает в этой сети канал, обозначенный на рис. 1 красным цветом, внутри которого устанавливается безопасный шифрованный канал (обозначен зеленым цветом).
В макете хост удостоверяющего центра CA можно подключить к вашей локальной сети. Для реальной работы хост CA нужно отсоединить от сети, а обмен сертификатами и ключами осуществлять с помощью, например, USB флэш-диска.
Если к безопасности предъявляются повышенные требования, хост CA необходимо поместить в охраняемое помещение — расположенная на этой машине информация позволяет создавать ключи доступа к вашей сети VPN.
Мы проводили установку серверов OpenVPN в среде ОС Debian Linux и FreeBSD, клиентов OpenVPN в ОС Debian Linux, FreeBSD и Microsoft Windows.
Основная часть статьи посвящена установке компонентов OpenVPN для Debian Linux. Далее мы рассмотрим особенности установки для FreeBSD и Microsoft Windows.
По возможности на узлах сети OpenVPN используйте новые версии ОС. Перед тем как приступить к работе с OpenVPN, обновите пакеты Linux:
# apt-get update
# apt-get upgrade
Установите на всех узлах пакет пакет zip, если он не был установлен ранее:
# aptitude install zip
Этот пакет будет нужен для распаковки архива утилиты Easy-RSA, с помощью которой мы будем создавать ключи и сертификаты.
На всех узлах настройте обновление и синхронизацию времени.
# apt-get install ntpdate
# apt-get install -y ntp
# /etc/init.d/ntp stop
# ntpdate pool.ntp.org
# /etc/init.d/ntp start
Синхронизация времени необходима, т.к. сертификаты имеют период действия. Если часы, например, на хосте удостоверяющего центра CA и сервера OpenVPN не синхронны, может получиться так, что выданный удостоверяющим центром сертификат не будет действителен на узлах сети OpenVPN из-за ограничений по дате или времени.
Дальнейшие работы мы начнем с подготовки хоста удостоверяющего центра CA. Затем установим хосты сервера и клиента OpenVPN.
Запуск openvpn-gui
Запустите OpenVPN-GUI как обычное приложение Windows с помощью кнопки Пуск (существует также возможность запуска OpenVPN-GUI в качестве службы). В панели системных задач (в системном «трее», или в панели System Tray) появится значок OpenVPN-GUI в виде небольшого окна с замком.
Щелкните этот значок правой клавишей мыши и выберите имя файла конфигурации, который вы создали в каталоге C:Program FilesOpenVPNconfig. Если все настроено правильно, на экране появится окно соединения, в котором будут отображаться сообщения.
После успешного соединения изображение окна с замком станет зеленого цвета. Это означает, что канал VPN установлен. В случае возникновения проблем читайте сообщения в окне подключения, а также журнал сервера OpenVPN. В большинстве случаев проблемы связаны с ошибками при подготовке сертификатов и ключей.
Чтобы разъединить канал OpenVPN, щелкните значок OpenVPN-GUI правой клавишей мыши и выберите из меню строку Отключиться.
Запуск демона openvpn
Создайте каталог для записи журнала демона OpenVPN:
# mkdir /var/log/openvpn
Добавьте в файл /etc/rc.conf строки:
openvpn_enable="YES"
openvpn_configfile="/usr/local/etc/openvpn/server.conf"
Здесь указан путь к рабочему файлу конфигурации демона OpenVPN.
Запустите демон OpenVPN:
# /usr/local/etc/rc.d/openvpn start
При успешном запуске на сервере и клиенте OpenVPN должен появится интерфейс TUN. Убедитесь в этом с помощью команды ifconfig:
# ifconfig
...
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
options=80000<LINKSTATE>
inet6 fe80::20c:29ff:fe28:d4be%tun0 prefixlen 64 scopeid 0x3
inet 10.15.0.1 --> 10.15.0.1 netmask 0xffffff00
nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
Opened by PID 493
Проверьте, что демон сервера OpenVPN занял порт 1194:
# sockstat | grep 1194
Если при запуске возникли ошибки, изучите журнал. Путь к файлу журнала задан в файле конфигурации демона OpenVPN.
Запуск клиента openvpn
Запустите демон следующей командой:
# /etc/init.d/openvpn start
Если возникла проблема с запуском клиента, проверьте содержимое журнала /var/log/openvpn/openvpn-client.log
В том случае, когда демон клиента запустился без ошибок, проверьте наличие интерфейса TUN, аналогично тому, как мы это делали при запуске демона сервера OpenVPN.
# ifconfig
...
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.15.0.2 P-t-P:10.15.0.2 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Проверьте также, что сервер OpenVPN откликается на команду ping по адресу 10.15.0.1:
# ping 10.15.0.1
Инициализация протокола диффи — хеллмана на эллиптических кривых
Поскольку обе стороны используют один и тот же алгоритм для выбора криптографических примитивов из списка поддерживаемых, после инициализации можно немедленно начать обмен ключами. Teleport поддерживает только протокол эллиптических кривых Диффи-Хеллмана (Elliptic Curve Diffie-Hellman, ECDH), так что обмен ключами начинается с того, что клиент генерирует эфемерную пару ключей (закрытый и связанный с ним открытый ключ) и отправляет серверу свой открытый ключ в сообщении
SSH_MSG_KEX_ECDH_INIT
Стоит подчеркнуть, что эта ключевая пара эфемерна: она используется только для обмена ключами, а затем будет удалена. Это чрезвычайно затрудняет проведение класса атак, где злоумышленник пассивно записывает зашифрованный трафик с надеждой украсть закрытый ключ когда-нибудь в будущем (как предусматривает закон Яровой — прим. пер.). Очень трудно украсть то, чего больше не существует. Это свойство называется прямой секретностью (forward secrecy).
Рис. 1. Генерация сообщения инициализации обмена ключами
Использование let’s encrypt для внутренних серверов
Let’s Encrypt — это центр сертификации, который предоставляет бесплатные сертификаты в полностью автоматизированном процессе. Эти сертификаты выдаются по протоколу ACME. За последние два года в Интернете широко использовалась технология Let’s Encrypt — более 50% веб-сертификатов SSL / TLS теперь выдает Let’s Encrypt.
В этом посте описывается, как выдавать сертификаты Let’s Encrypt для внутренних серверов.
Хотя и существует множество инструментов для автоматического обновления сертификатов для общедоступных веб-серверов (certbot, simp_le, я писал о том, как это сделать), трудно найти какую-либо полезную информацию о том, как выдавать сертификаты для внутренних серверов, не подключенных к Интернету, и / или устройства с Let’s Encrypt.
В Datto мы выдали сертификат на каждую из наших 90 000 устройств BCDR, использующих именно этот механизм.
Содержание
- Как это работает?
- Пример: внутренний сервер 10.1.1.4, он же. xi8qz.example.com
2.1. Предварительные требования: назначение домена для каждой машины (шаги 1-3)
2.2. Запрос сертификата (шаги 4-14) - Рекомендации по развертыванию: ограничения скорости Let’s Encrypt.
Hello Hacker News, впервые на главной странице HN! Для меня это большая честь! Я ответил на все вопросы в разделе комментариев.
Если вы ищете реализацию этой идеи, вам может быть интересен localtls. Я сам не тестировал, но похоже, что он делает то же самое, что я здесь описываю.
Как это работает?
Чтобы выпустить сертификат с помощью Let’s Encrypt, вы должны доказать, что вы либо являетесь владельцем веб-сайта, для которого хотите выпустить сертификат, либо владеете доменом, на котором он работает. Обычно автоматизированные инструменты, такие как certbot, используют HTTP-запрос для подтверждения права собственности на сайт с использованием.well-knownкаталога. Хотя это прекрасно работает, если сайт подключен к Интернету (и Let’s Encrypt может проверять файлы HTTP-запросов с помощью простого HTTP-запроса), он не работает, если ваш сервер работает на10.1.1.4или на любом другом внутреннем адресе.DNS решает эту проблему, позволяя подтвердить право собственности на домен с помощью
TXT-записи DNS_acme-challenge.example.com. Let’s Encrypt проверит, что запись соответствует ожидаемому, и выдаст ваш сертификат, если все сложится.Итак, действительно волшебными ингредиентами для выдачи сертификатов для внутренних компьютеров, не подключенных к Интернету, являются:
Пример: внутренний сервер 10.1.1.4, он же. xi8qz.example.com
На следующей диаграмме показано, как мы реализовали интеграцию Let’s Encrypt для наших устройств резервного копирования Datto. Каждое устройство (читайте: внутренний сервер) находится за NAT и имеет собственный локальный IP-адрес.
Общий подход прост: устройство регулярно обращается к нашему серверу управления, чтобы обеспечить доступ к нему через его собственный поддомен. Если его локальный IP-адрес изменяется, он запускает обновление своего собственного поддомена. Кроме того, он регулярно проверяет, действителен ли сертификат, и запрашивает обновление, если он устарел.
Вот немного подробностей об этом процессе:

Участники этого процесса:
В этом примере предположим, что мы пытаемся выпустить сертификат для устройства с идентификатором xi8qz и локальным IP-адресом 10.1.1.4. С точки зрения этого устройства необходимо сделать два запроса:
2.1. Предварительные требования: назначение домена для каждой машины (шаги 1-3)
Как упоминалось выше, нам нужно дать каждому устройству правильное доменное имя, чтобы иметь возможность подтвердить право собственности на Let’s Encrypt, поэтому нам нужно купить домен (здесь: example.com) и делегировать его NS-записи нашему серверу DDNS:
$ dig short NS example.com
ddns1.mycompany.com.Вдобавок к этому нам нужна возможность динамически добавлять и удалять записи из него (через какой-то API). Я ранее писал о том, как развернуть собственный DDNS-сервер, если вам интересно.
После того, как все это настроено, нам нужно убедиться, что запись A машины обновляется при изменении ее IP-адреса. Для нашей внутренней машины давайте назначим xi8qz.example.com в качестве домена. Если все работает правильно, вы сможете разрешить этот домен по его IP-адресу, используя обычный DNS-запрос:
$ dig short xi8qz.example.com
10.1.1.42.2. Запрос сертификата (шаги 4-14)
Предполагая, что теперь вы полностью контролируете зону DNS для example.com и можете быстро редактировать ее динамически, у вас все готово для фактической выдачи сертификатов для вашего локального домена устройства через Let’s Encrypt.
В нашем примере устройства оно будет регулярно проверять, действителен ли существующий сертификат (шаг 4). Если сертификата нет или срок действия существующего скоро истечет, устройство сгенерирует пару ключей и запрос на подпись сертификата (CSR), используя назначенное ему имя хоста (здесь: xi8qz.example.com) в качестве CN, и оно отправит этот CSR на управляющий сервер (шаг 5).
После авторизации запроса (важный шаг, не показанный на схеме!), Управляющий сервер запрашивает DNS-запрос для данного домена из ACME API через вызов Pre-Authorization / new-authz API (шаг 6). ACME API отвечает запросом DNS (шаг 7). Если все идет хорошо, это выглядит примерно так:
{
"identifier": {
"type": "dns",
"value": "xi8qz.example.com"
},
"status": "pending",
"expires": "2021-04-15T21:26:29Z",
"challenges": [
{
"type": "dns-01",
"status": "pending",
"uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/VtjihR4X8nLAj4MDwI...",
"token": "aLptEKAeUOajkiGrx-kkbjUX4b1MC..."
},
// ...
],
// ...
}Используя этот ответ, управляющий сервер должен установить запись DNS TXT на _acme-challenge.xi8qz.example.com (шаг 8) и уведомить ACME API о том, что ответ на запрос был размещен (шаг 9).
После того, как ответ на запрос был проверен с помощью Let’s Encrypt (шаг 10-11), сертификат можно, наконец, запросить с помощью CSR (шаг 12-13).
После того, как Let’s Encrypt ответит сертификатом, вы увидите на проводе что-то вроде этого:
-----BEGIN CERTIFICATE-----
MIIGEjCCBPqgAwIBAgISAyk2izMz7OXSqHeZhg rUR5uMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
...Если декодировать с помощью openssl, мы увидим, что это настоящая сделка:
$ openssl x509 -in www.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
03:29:36:8b:33:33:ec:e5:d2:a8:77:99:86:0f:ab:51:1e:6e
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
Validity
Not Before: Jul 18 23:37:35 2021 GMT
Not After : Oct 16 23:37:35 2021 GMT
Subject: CN=xi8qz.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:be:69:df:28:04:9c:2b:e9:94:72:c3:de:a6:fd:
a4:38:93:be:43:a7:81:8b:dc:9a:be:19:0d:c0:d1:
...Этот сертификат затем возвращается в машину (шаг 14). После перезапуска веб-сервера устройства / сервера к его веб-интерфейсу можно будет получить доступ через HTTPS в браузере или из командной строки:
$ curl -v https://xi8qz.example.com/login
* Trying 10.1.1.4...
* TCP_NODELAY set
* Connected to xi8qz.example.com (10.1.1.4) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=xi8qz.example.com
* start date: Jul 18 23:37:35 2021 GMT
* expire date: Oct 16 23:37:35 2021 GMT
* subjectAltName: host "xi8qz.example.com" matched cert's "xi8qz.example.com"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
> GET /login HTTP/1.1
> Host: xi8qz.example.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 05 Aug 2021 17:38:49 GMT
< Server: Apache/2.4.18 (Ubuntu)
...Рекомендации по развертыванию: ограничения скорости Let’s Encrypt.
Важно отметить, что если вы планируете реализовать этот механизм для большого количества серверов, вы используете staging среды Let’s Encrypt для тестирования и, что более важно, учитываете лимиты выдачи сертификатов.
По умолчанию Let’s Encrypt позволяет выдавать только 20 сертификатов (в 2021 году) в неделю для одного и того же домена или одной и той же учетной записи. Чтобы увеличить это число, вы должны либо запросить более высокий лимит выдачи, либо добавить свой домен в список общедоступных суффиксов (обратите внимание: добавление вашего домена здесь имеет другие последствия!).
Из-за этих ограничений скорости жизненно важно, чтобы вы распределили начальное развертывание настолько, чтобы оставаться ниже ограничения скорости, и чтобы вы оставили достаточно места для добавления будущих серверов. Также рассмотрите возможность продления в первоначальном плане развертывания.
Резюме
Как видите, это не так уж и сложно.
Сначала мы присвоили каждому устройству (так называемому внутреннему серверу) публичное доменное имя, используя наш собственный динамический DNS-сервер и выделенную зону DNS. Используя домен, назначенный серверу (здесь:
xi8qz.example.com), мы затем использовали предложение бесплатного сертификата Let’s Encrypt и их запрос DNS, чтобы выпустить сертификат для этого сервера.
Сделав это для всех внутренних серверов, мы можем обеспечить безопасную связь в нашей внутренней ИТ-инфраструктуре без необходимости развертывания настраиваемого сертификата CA или необходимости платить за сертификаты.
Интересные Github проекты по этой теме:
https://github.com/RealTimeLogic/SharkTrust
https://github.com/joohoi/acme-dns
https://github.com/skoerfgen/CertLE
https://github.com/Corollarium/localtls
Немного рекламы: На платформе https://rotoro.cloud/ вы можете найти курсы с практическими занятиями:
Компоненты сети openvpn
Прежде чем мы перейдем от теории к практике, перечислим основные компоненты сети OpenVPN и объекты, с которыми нам придется иметь дело.
Удостоверяющий центр CA
Выдает сертификаты по запросу узлов сети VPN, подписанные сертификатом удостоверяющего центра. Предоставляет узлам сети VPN свой собственный сертификат для проверки удостоверяющей стороны. Управляет списком отзыва сертификатов CRL.
Сервер OpenVPN
ПО сервера OpenVPN создает туннель внутри незащищенной сети, например, Интернета. Этот туннель обеспечивает безопасный зашифрованный трафик между узлами — участниками обмена данными в сети OpenVPN.
Клиент OpenVPN
ПО клиента OpenVPN устанавливается на все узлы, которым необходим защищенный канал передачи данный с сервером OpenVPN. При соответствующей настройке сервера OpenVPN возможна защищенная передача данных между клиентами OpenVPN, а не только между клиентами и сервером OpenVPN.
Сертификаты (публичные ключи) X.509
Сертификаты X.509 представляют собой публичные ключи, заверенные удостоверяющим центром CA. Они используются для зашифровывания данных. Факт заверения сертификата удостоверяющим центром CA позволяет идентифицировать сторону, передающую зашифрованные данные.
Файл запроса на сертификат создается на узлах сети, затем он переносится на узел удостоверяющего центра и там подписывается. Созданный в результате подписанный сертификат переносится обратно на запросивший его узел сети OpenVPN.
Приватные ключи
Приватные ключи секретные. Они должны создаваться и храниться на каждом узле сети OpenVPN, предназначены для расшифрования данных и никогда не должны передаваться по сети.
Приватные ключи создаются на узлах сети OpenVPN одновременно с файлом запроса на получение сертификата.
Список отзыва сертификатов CRL
Содержит список сертификатов, утративших доверие. Он создается и редактируется на узле удостоверяющего центра CA. Чтобы отключить узел от сети, достаточно занести его сертификат в список CRL.
После создания и каждого изменения список CRL переносится на серверы OpenVPN.
Файл Диффи-Хелмана
Используется, чтобы в случае похищения ключей исключить расшифрование трафика, записанного еще до этого похищения. Создается на сервере OpenVPN.
Статический ключ HMAC
Служит для проверки подлинности передаваемой информации. Обеспечивает защиту от DoS-атак и флуда. Создается на сервере OpenVPN.
Мониторинг сертификатов
Надо следить за тем, что бы сертификаты на доменах обновлялись. Можно мониторить логи получения и распространения, и когда что-то идёт не так – кидать warning в системе мониторинга. Но мы пойдём с одной стороны на минималках, с другой более основательно и ещё помимо этого захватим другие исталяции, например с traefik, который живёт там сам по себе.
Я использую zabbix и скрипт от @selivanov_pavel
Проверим с его помощью мой домен локально
koala@x220 ~/t/acme.sh-test> ./ssl_cert_check.sh expire itdog.info 443
4141 день сертификат на itdog.info будет актуален. Сертификат в let’s encrypt обновляется за 30 дней до протухания. А значит, например, если ему осталось жить 10 дней, значит что-то пошло не так и надо идти смотреть.
Темплейт состоит из одного item и одного trigger. Темплейт есть так же на github
ssl_cert_check.sh["expire","{HOST.NAME}","{$TLS_PORT}"]В item две переменных, первая HOST.NAME берёт имя хоста, предполагается что у нас хост назван по доменному имени. Переменная $TLS_PORT по дефолту 443, но если нужно проверять на нестандартном порту, то записываем значение порта в macros.
Триггер тоже супер простой
{Check tls expire:ssl_cert_check.sh["expire","{HOST.NAME}","{$TLS_PORT}"].last()}<=10Если полученное значение меньше 10ти – аллерт. Таким образом, мы узнаем если у нас начнут протухать сертификаты и будет 10 дней на починку.
Настройка apache 2 для использования сертификатов
Переходим в каталог /etc/apache2:
root@shpc:/mnt# cd/etc/apache2/
Создаём каталог для хранения сертификатов:
root@shpc:/etc/apache2# mkdir ssl
Включаем модуль SSL для веб-сервера. Тестирование проводилось на ОС Ubuntu Linux, поэтому модуль достаточно просто включить:
a2enmod headers
Перезапускаем веб-сервер:
root@shpc:/etc/apache2# systemctl restart apache2Аналогично нужно включить поддержку заголовков:
Теперь создадим конфигурационный файл для модуля SSL. Пример содержимого для него можно взять на Syslink.pl. Команды такие:
root@shpc:/mnt# cd /etc/apache2/conf-available root@shpc:/etc/apache2/conf-available# nano ssl-params.conf
Сам файл будет содержать следующие параметры (чтобы было проще работать, мы отключили заголовки Strict-Transport-Securrity, X-Frame-Options и X-Content-Type-Options):
Далее созданный конфиг надо активировать:
root@shpc:/etc/apache2/conf-available# a2enconf ssl-paramsТеперь переходим в каталог /etc/apache2/sites-available:
root@shpc:/etc/apache2/conf-available# cd/etc/apache2/sites-available
И делаем на всякий случай резервные копии всех хранящихся там файлов:
root@shpc:/etc/apache2/sites-available# cp 000-default.conf 000-default.conf.bak root@shpc:/etc/apache2/sites-available# cp default-ssl.conf default-ssl.conf.bak
Теперь ещё раз проверяем подключённые модули headers и SSL:
Далее нам надо перенести созданные сертификаты (сертификат CA и сертификат сервера) в каталог /etc/ssl/certs, а ключ сертификата сервера — в каталог /etc/ssl/private:
root@shpc:/opt/simple_CA# cp ca.cer /etc/ssl/certs/ root@shpc:/opt/simple_CA# cp server.cer /etc/ssl/certs/server.crt root@shpc:/opt/simple_CA# cp server.key /etc/ssl/private/server.key
Далее откроем конфиг сайта (/etc/apache2/sites-available/000-default-ssl.conf) и добавим туда следующие опции:
SSLCertificateFile /etc/ssl/certs/server.crt SSLCertificateKeyFile /etc/ssl/private/server.key SSLCACertificateFile /etc/ssl/certs/ca.cer
Теперь перезагружаем веб-сервер:
root@shpc:/etc/apache2# a2ensite default-ssl root@shpc:/etc/apache2/sites-available# service apache2 restart
Проверяем доступность сайта:
Видим, что Firefox не может проверить сертификат сайта. Чтобы смог, надо импортировать цепочку сертификатов, подтверждающих сертификат сервера, в список доверенных. Создадим цепочку:
root@shpc:/opt/simple_CA# openssl crl2pkcs7 -nocrl-certfile ca.cer -certfile server.cer -out serve-and-ca-chain.p7c -outform der
У полученного файла не забываем сменить атрибуты на 555:
root@shpc:/opt/simple_CA# chmod555 serve-and-ca-chain.p7c
Теперь откроем в браузере менеджер сертификатов и импортируем полученную цепочку (кнопка Import):
Далее можно просмотреть сертификаты и настроить доверие — вдруг что-то упущено:
Когда сертификаты добавлены в список доверенных, можно снова зайти на сайт и увидеть, что соединение помечается как доверенное:
Сейчас время настроить аутентификацию для клиентов.
Настройка аутентификации клиентов
Веб-сервер Apache поддерживает аутентификацию клиента. Это значит, что мы можем выписать клиенту сертификат SSL, а сервер сможет его проверить. Если у пользователя не будет сертификата — аутентификация не пройдёт. Для активации такой возможности надо добавить в конфиг default-ssl.conf такие опции:
SSLCACertificateFile /opt/simple_CA/ca.cer SSLVerifyClient require SSLVerifyDepth 2
После этого к сайту сможет подключиться только тот пользователь, сертификат которого:
- установлен в браузере, если клиентом является браузер, — тогда сертификат будет предъявлен при подключении к серверу;
- подписан сертификатом доверенного УЦ.
Сначала сгенерируем сертификат для клиента. Первым делом создаём ключ:
root@shpc:/opt/simple_CA# openssl genrsa -out client.key 4096
Затем на основе ключа сгенерируем CSR:
root@shpc:/opt/simple_CA# openssl req -new-key client.key -out client.req
Теперь на базе запроса сгенерируем сам сертификат:
root@shpc:/opt/simple_CA# openssl req -new-key client.key -out client.req
И импортируем сертификат в формате p12:
root@shpc:/opt/simple_CA# openssl pkcs12 -export-inkey client.key -in client.cer -out client.p12
В итоге у нас должен получиться файл client.p12. Нужно поменять права на файл, иначе сертификат не импортируется:
root@shpc:/opt/simple_CA# chmod555 client.p12
Теперь можно импортировать его в браузер по аналогии с корневыми сертификатами:
После импорта должно получиться примерно так:
После этого перезапускаем веб-сервер и возвращаемся на сайт. Видим окно выбора сертификата того пользователя, которого мы импортировали в браузер:
Немного теории
Если раньше для создания безопасного канала передачи данных крупным компаниям и организациям приходилось прокладывать (либо арендовать) кабели и защищать их от физического доступа злоумышленников, то теперь в этом нет необходимости. С помощью VPN можно создавать защищенные виртуальные каналы, работающие через безопасный “туннель” в Интернете. Такое решение может позволить себе любая, даже очень небольшая компания.
Конечно, если предъявляются повышенные требования к защите данных, необходимо применять сертифицированные средства и обращаться к специалистам. Однако уровень защиты, обеспечиваемый OpenVPN, позволяет использовать эту технологию для многих коммерческих приложений.
Почему сеть VPN называется виртуальной и частной?
Виртуальная она потому, что узлы сети объединяются не физическими линиями, а виртуальными соединениями, которые создаются программным обеспечением (ПО) VPN.
Сеть VPN частная, так как к ней могут подключаться только узлы компании, создавшей эту сеть, а не все желающие. На каждом узле сети VPN должно работать ПО VPN. Еще там должны находиться ключи и сертификаты, обеспечивающие узлам доступ к сети VPN и криптографическую защиту передаваемых данных.
Таким образом, сеть VPN может объединять ресурсы (серверы и рабочие станции) компании в единую безопасную виртуальную сеть, созданную на базе Интернета. И теперь сотрудники, работающие удаленно (из дома или из другой страны) будут находиться как бы в общей сети своей компании. Сеть VPN подходит и для консолидации территориально разделенных офисов компании.
Ответ по протоколу диффи — хеллмана на эллиптических кривых
Сервер ждёт сообщение
SSH_MSG_KEX_ECDH_INIT
, а при получении генерирует собственную эфемерную пару ключей. С помощью открытого ключа клиента и собственной пары ключей сервер может сгенерировать общий секрет K.
Затем сервер генерирует нечто, называемое хэшем обмена H, и подписывает его, генерируя подписанный хэш HS (подробнее на рис. 3). Хэш обмена и его подпись служат нескольким целям:
Хэш обмена генерируется путём взятия хэша (SHA256, SHA384 или SHA512, в зависимости от алгоритма обмена ключами) следующих полей:
С этой информацией сервер может сконструировать сообщение
SSH_MSG_KEX_ECDH_REPLY
, применив эфемерный открытый ключа сервера
B
, открытый ключ хоста сервера
HPub
и подпись на хэше обмена
HS
. См. рис. 4 для более подробной информации.

Рис. 2. Генерация хэша обмена H
Как только клиент получил от сервера SSH_MSG_KEX_ECDH_REPLY, у него есть всё необходимое для вычисления секрета K и хэша обмена H.
В последней части обмена ключами клиент извлекает открытый ключ хоста (или сертификат) из SSH_MSG_KEX_ECDH_REPLY и проверяет подпись хэша обмена HS, подтверждающую право собственности на закрытый ключ хоста. Чтобы предотвратить атаки типа «человек в середине» (MitM), после проверки подписи открытый ключ хоста (или сертификат) проверяется по локальной базе известных хостов; если этот ключ (или сертификат) не является доверенным, соединение разрывается.
The authenticity of host 10.10.10.10 (10.10.10.10)' can't be established. ECDSA key fingerprint is SHA256:pnPn3SxExHtVGNdzbV0cRzUrtNhqZv Pwdq/qGQPZO3. Are you sure you want to continue connecting (yes/no)?
SSH-клиент предлагает добавить ключ хоста в локальную базу известных хостов. Для OpenSSH это обычно ~/.ssh/known_hosts
Такое сообщение означает, что представленного ключа нет в вашей локальной базе данных известных хостов. Хороший способ избежать таких сообщений — использовать вместо ключей сертификаты SSH (что Teleport делает по умолчанию), которые позволяют вам просто хранить сертификат удостоверяющего центра в локальной базе известных хостов, а затем проверять все хосты, подписанные этим УЦ.

Рис. 3. Генерация ответа при обмене ключами ECDH
Полезные ссылки
Протокол Диффи — Хеллмана
HMAC
Шифрование
X.509
OpenVPN: создание сервера на Windows
Центр сертификации или удостоверяющий центр (Certification authority, CA)
Проверка результата запуска демона openvpn
Если сервер OpenVPN стартовал без ошибок, убедитесь с помощью команды ifconfig в том, что появился интерфейс TUN:
# ifconfig
...
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.15.0.1 P-t-P:10.15.0.1 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Как мы уже говорили, использование TUN/TAP на арендованных VDS может потребовать дополнительной оплаты.
Если все хорошо, то в интерфейсе tun появился адрес IP 10.15.0.1. Это адрес сервера OpenVPN в нашем защищенном туннеле, заданный в файле конфигурации server.conf.
После проверки наличия интерфейса TUN убедитесь, что OpenVPN занял порт 1194:
# netstat -ltupn | grep 1194
Если демон запустился нормально и порт 1194 занят сервером OpenVPN, можно переходить к установке клиента OpenVPN, описанной в следующем разделе статьи. При возникновении ошибок проанализируйте журнал /var/log/openvpn/openvpn-server.log.
При установке OpenVPN на Linux с новыми ядрами, начиная с 2.6, интерфейс TUN может не появится. При этом в логах появляется ошибка:
Создание запроса на сертификат
Перейдем к процедуре создания запроса на сертификат.
Прежде всего, запустите консоль с правами администратора. Для удобства вместо стандартной консоли Microsoft Windows мы использовали бесплатный эмулятор консоли ConEmu-Maximus5.
Запустив консоль, перейдите в каталог Easy-RSA и выполните команды:
cd C:Program FilesOpenVPNeasy-rsa
init-config.bat
clean-all
В результате будет создан каталог C:Program FilesOpenVPNeasy-rsakeys и файл vars.bat.
Отредактируйте в файле vars.bat строки по примеру, приведенному ниже, указав код своей страны KEY_COUNTRY и региона KEY_PROVINCE, название города KEY_CITY, компании KEY_ORG, адрес электронной почты KEY_EMAIL и название отдела KEY_OU:
Создание инфраструктуры публичных ключей pki
На первом шаге создайте инфраструктуру публичных ключей (Public Key Infrastructure, PKI):
$ cd /home/ca/easy-rsa-master/easyrsa3
$ ./easyrsa init-pki
Вы увидите сообщение:
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/ca/easy-rsa-master/easyrsa3/pki
В результате выполнения команды init-pki был создан каталог /home/ca/easy-rsa-master/easyrsa3/pki, где и находится инфраструктура публичных ключей PKI.
На втором шаге с помощью команды build-ca создайте удостоверяющий центр CA:
$ ./easyrsa build-ca
В ответ на эту команду вам будет предложено ввести пароль и так называемое имя Common Name:
Установка openvpn-gui
Выберите вариант загрузки Windows Installer (64-bit) или Windows Installer (32-bit) в зависимости от разрядности вашей версии ОС Microsoft Windows. Далее запустите полученный файл и выполните установку по умолчанию. Файлы конфигурации, сертификаты и ключи необходимо записать в папку C:Program FilesOpenVPNconfig.
В папку C:Program FilesOpenVPNeasy-rsa устанавливается версия программы Easy-RSA для Windows.
Краткую инструкцию по использованию Easy-RSA для Windows вы найдете в файле C:Program FilesOpenVPNeasy-rsaREADME.txt
Мы рассмотрим вариант, при котором запрос на сертификат создается на хосте Microsoft Windows, а затем передается через USB флэш-диск на хост удостоверяющего центра CA. Там на основании запроса создается подписанный файл сертификата и, опять же, через USB флэш-диск, передается на хост Microsoft Windows.
Установка прокси-сервера squid
Итак, у нас есть сеть VPN, и сотрудники, работающие удаленно, могут подключаться к VDS сервера OpenVPN с помощью безопасного туннеля. Теперь нам нужно организовать доступ сотрудников к защищенным ресурсам компании через прокси-сервер, установленный на сервер OpenVPN.
В качестве прокси-сервера мы выбрали ПО с открытым исходным кодом Squid, который часто применяется, в частности, для кэширования Web-страниц в высоконагруженных проектах. Нам, однако, сейчас пригодится только его функция проксирования.
Установку Squid проще всего выполнить из пакета:
# apt-get install squid3
После завершения установки в каталоге /etc/squid3 будет создан файл конфигурации squid.conf внушительных размеров, который необходимо отредактировать. Впрочем, в нашем случае требуется внести лишь очень небольшие изменения.
Прежде всего, отыщите в файле squid.conf следующую строку:
Создание списка отзывов сертификатов
Если сотрудник уволился, необходимо заблокировать его доступ в сеть VPN компании. Специально для этой цели в OpenVPN предусмотрен список отзыва сертификатов CRL. Создайте его такой командой:
$ cd /home/ca/easy-rsa-master/easyrsa3
$ ./easyrsa gen-crl
У вас будет запрошен пароль доступа к приватному ключу ca.key удостоверяющего центра. Список отзыва сертификатов будет создан в файле /home/ca/easy-rsa-master/easyrsa3/pki/crl.pem.
Скопируйте этот файл на USB флэш-диск:
# cp /home/ca/easy-rsa-master/easyrsa3/pki/crl.pem /mnt/flash
Если нужно заблокировать выданный ранее сертификат, воспользуйтесь следующей командой:
$ ./easyrsa revoke developer5
Здесь мы отозвали сертификат для клиента developer5. Далее нужно скопировать новый файл CRL на сервер OpenVPN и перезапустить демон OpenVPN.
