Защита HAProxy при помощи Let’s Encrypt на сервере Ubuntu

Let’s Encrypt – это новый центр сертификации (ЦС, или Certificate Authority, CA), который предоставляет простой способ создания сертификатов TLS/SSL, тем самым позволяя шифровать HTTPS на веб-серверах. Этот ЦС упрощает процесс создания сертификатов путём автоматизации большинства необходимых действий при помощи клиентского ПО. На данный момент Let’s Encrypt ещё находится в открытом бета-тестировании; пока что процесс получения и установки сертификата полностью автоматизирован только на веб-серверах Apache. Тем не менее, Let’s Encrypt позволяет получить бесплатный сертификат SSL, который можно установить вручную независимо от программного обеспечения веб-сервера.

Данное руководство поможет установить Let’s Encrypt и получить SSL-сертификат для HAProxy в системе Ubuntu 14.04 и покажет, как обновлять этот сертификат.

Требования

  • Настроенный сервер Ubuntu 14.04.
  • Не-root пользователь с доступом к sudo (инструкции по начальной настройке сервера и созданию пользователя можно найти в этом руководстве).
  • Доменное имя, которое можно использовать в сертификате (в руководстве используется условные домены example.com и www.example.com).
  • Запись А, связывающая домен с внешним IP-адресом сервера. Она необходима для того, чтобы Let’s Encrypt мог проверить доменное имя. (в руководстве используется два домена, нужно создать запись А для каждого из них).

1: Установка клиента Let’s Encrypt

Чтобы получить SSL-сертификат от Let’s Encrypt, нужно сначала установить клиентскую программу letsencrypt. Клонируйте официальный репозиторий проекта на GitHub.

Примечание: Вероятно, в дальнейшем программа будет доступна в пакетах.

Установка Git и bc

Чтобы клонировать необходимый репозиторий, сначала нужно установить Git и bc.

Для этого можно использовать пакетный менеджер системы; предварительно нужно обновить список пакетов:

sudo apt-get update
sudo apt-get -y install git bc

Клонирование репозитория Let’s Encrypt

Теперь можно клонировать репозиторий Let’s Encrypt с GitHub в каталог /opt:

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

2: Получение сертификата

Let’s Encrypt предлагает несколько способов получения сертификата при помощи разных плагинов. На данный момент плагины позволяют только получить сертификат, а настройку сервера для использования этого сертификата нужно выполнить вручную; исключением является плагин для Apache, работа с которым описана здесь.

Примечание: Плагины, которые помогают получить сертификат, но не устанавливают его, называются аутентификаторами.

В данном руководстве для создания SSL-сертификата используется плагин Standalone.

Проверка порта 80

Плагин Standalone позволяет быстро получить сертификат SSL. Он временно запускает отдельный веб-сервер на порт 80, к которому подключается Let’s Encrypt CA и подтверждает сертификат. Следовательно, для работы плагина необходим порт 80, потому нужно временно отключить обычный веб-сервер, если он занимает этот порт.

К примеру, при использовании HAProxy нужно ввести:

sudo service haproxy stop

Чтобы узнать, занят ли порт 80, введите:

netstat -na | grep ':80.*LISTEN'

Если команда не вернула никакого результата, значит, порт свободен, и можно запускать плагин Standalone.

Запуск Let’s Encrypt

Перейдите в каталог letsencrypt

cd /opt/letsencrypt

Затем используйте плагин Standalone:

./letsencrypt-auto certonly --standalone

Примечание: Программное обеспечение Let’s Encrypt требует привилегий суперпользователя. Программа может запросить пароль.

После запуска letsencrypt запросит некоторые данные.

Примечание: Вопросы, задаваемые при первом запуске программы, отличаются от вопросов, задаваемых при дальнейшем её использовании. В руководстве предполагается, что программа запущена впервые.

Укажите адрес электронной почты, который будет использоваться для отправки извещений и восстановления утерянных ключей.

После этого нужно принять условия соглашения подписчика Let’s Encrypt.

Затем программа запросит доменное имя (или имена). Если вы хотите использовать один сертификат для нескольких доменных имен, укажите их в предложенном поле:

Please enter in your domain name(s) (comma and/r space separated):
example.com www.example.com

Если запуск прошел успешно, на экране появится сообщение:

IMPORTANT NOTES:
- If you lose your account credentials, you can recover through
e-mails sent to name@8host.com
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/example.com/fullchain.pem. Your
cert will expire on 2016-03-15. To obtain a new version of the
certificate in the future, simply run Let's Encrypt again.
- Your account credentials have been saved in your Let's Encrypt
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Let's
Encrypt so making regular backups of this folder is ideal.
- If like Let's Encrypt, please consider supporting our work by:
Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le

Выпишите или запомните путь и срок действия сертификата (в примере они выделены красным).

Файлы сертификата

После получения сертификата на сервере появятся следующие файлы:

  • cert.pem: сертификат домена.
  • chain.pem: сертификат цепочки Let’s Encrypt.
  • fullchain.pem: комбинация cert.pem и chain.pem.
  • privkey.pem: закрытый ключ сертификата.

Важно знать место хранения сертификата, так как его нужно будет указать в конфигурации веб-сервера. Файлы хранятся в подкаталоге /etc/letsencrypt/archive, также Let’s Encrypt создаёт символьную ссылку на наиболее актуальный сертификат в каталог /etc/letsencrypt/live/your_domain_name.

Чтобы убедиться, что все файлы существуют, нужно выполнить такую команду:

sudo ls /etc/letsencrypt/live/your_domain_name

Команда покажет список существующих файлов.

Объединение Fullchain.pem и Privkey.pem

Чтобы HAProxy поддерживал терминацию SSL и смог шифровать трафик, нужно объединить fullchain.pem и privkey.pem в один файл.

Создайте каталог для хранения файла, который получится в результате объединения.

sudo mkdir -p /etc/haproxy/certs

Затем объедините файлы при помощи следующей команды:

DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'

Заблокируйте доступ к получившемуся файлу при помощи команды:

sudo chmod -R go-rwx /etc/haproxy/certs

Теперь можно использовать сертификат SSL и закрытый ключ с HAProxy.

3: Установка HAProxy

Примечание: Если HAProxy уже установлен, пропустите этот раздел.

В руководстве используется версия HAProxy 1.6, которой нет в стандартных репозиториях Ubuntu. Однако эту версию все же можно установить при помощи менеджера пакетов, предварительно добавив репозиторий PPA.

sudo add-apt-repository ppa:vbernat/haproxy-1.6

После этого обновите список пакетов системы и установите HAProxy.

sudo apt-get update
sudo apt-get install haproxy

4: Настройка HAProxy

Этот раздел покажет, как выполнить базовую настройку HAProxy для поддержки и обновления сертификата Let’s Encrypt.

Откройте haproxy.cfg в текстовом редакторе:

sudo nano /etc/haproxy/haproxy.cfg

Глобальные настройки

Сначала нужно отладить раздел global.

Директива maxconn определяет число одновременных подключений, поддерживаемых HAProxy. Нужно выбрать для неё разумное значение, поскольку она влияет на качество работы приложения; если установить слишком большое количество подключений, может случиться сбой сервера из-за чрезмерного количества запросов. Подберите оптимальное для вашего сервера количество подключений и добавьте в раздел global такую строку:

maxconn 2048

Примечание: Вместо 2048 укажите оптимальное количество одновременных подключений для вашего сервера.

После этого нужно добавить строку, которая задаёт максимальный размер временных DHE-ключей:

tune.ssl.default-dh-param 2048

Раздел defaults

Добавьте в раздел defaults следующие строки:

option forwardfor
option http-server-close

Опция forwardfor добавляет в запросы заголовок X-Forwarded-For, а опция http-server-close уменьшает время ожидания.

Настройка фронтэнда

Найдите раздел frontend.

Для начала нужно настроить обработку подключений HTTP и передачу их на бэкенд (его нужно настроить немного позже). Добавьте фронтэнд www-http в конце файла.

frontend www-http
bind haproxy_www_public_IP:80
reqadd X-Forwarded-Proto:\ http
default_backend www-backend

Примечание: Замените haproxy_public_IP внешним IP сервера HAProxy.

После этого нужно добавить фронтэнд для обработки входящих соединений HTTPS. В конец файла внесите фронтэнд www-https.

Примечание: Замените haproxy_public_IP внешним IP сервера HAProxy. Вместо example.com укажите свой домен.

frontend www-https
bind haproxy_www_public_IP:443 ssl crt /etc/haproxy/certs/example.com.pem
reqadd X-Forwarded-Proto:\ https
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
default_backend www-backend

Этот фронтенд использует ACL (letsencrypt-acl). Отправьте запрос на подтверждение Let’s Encrypt (/.well-known/acme-challenge) бэкенду letsencrypt-backend, который будет обновлять сертификат, не останавливая сервис HAProxy.

Все остальные запросы будут передаваться на бэкенд www-backend, который обслуживает сайт или приложение.

Настройки бэкенда

Добавьте бэкенд www-backend в конец файла.

Примечание: Замените условные данные в коде своими данными. Откорректируйте количество строк server согласно вашему количеству бэкендов.

backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 www_1_private_IP:80 check
server www-2 www_2_private_IP:80 check

Весь трафик, поступающий на этот бэкенд, будет распределяться между записями server по HTTP (порт 80).

В завершение добавьте бэкенд letsencrypt-backend.

backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321

Этот бэкенд обрабатывает только вызовы ACME для Let’s Encrypt, необходимые для обновления и запроса сертификата, а затем отправляет трафик локальному хосту через порт 54321. Используйте этот порт вместо 80 и 443 для обновления сертификата.

Теперь можно запустить HAProxy:

sudo service haproxy restart

Примечание: Дополнительную информацию файле haproxy.cfg можно получить здесь.

Теперь сертификат TLS/SSL от Let’s Encrypt работает. Можно переходит к настройке автоматического обновления.

5: Автоматическое обновление сертификата

Сертификаты Let’s Encrypt действительны в течение 90 дней, но во избежание ошибок их рекомендуется обновлять каждые 60 дней. На момент написания статьи клиент не оборудован функцией автоматического обновления сертификатов. Этот процесс можно выполнить вручную, просто запустив клиент Let’s Encrypt с использованными ранее параметрами.

Для этого можно использовать cron.

Используйте Standalone и настройте его для использования порта 54321 (во избежание конфликтов с HAProxy, который слушает порты 80 и 4433). Используйте команду:

cd /opt/letsencrypt
./letsencrypt-auto certonly --agree-tos --renew-by-default --standalone-supported-challenges http-01 --http-01-port 54321 -d example.com -d www.example.com

После успешного выполнения команды нужно создать новый сертификат и объединить его файлы.

DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'

После этого перезапустите HAProxy:

sudo service haproxy reload

Определив команды, которые нужны для обновления сертификата, можно автоматизировать их запуск при помощи cron.

Конфигурационный файл Let’s Encrypt

Чтобы упростить процесс обновления Let’s Encrypt, создайте конфигурационный файл:

sudo cp /opt/letsencrypt/examples/cli.ini /usr/local/etc/le-renew-haproxy.ini

Откройте файл для редактирования:

sudo nano /usr/local/etc/le-renew-haproxy.ini

Раскомментируйте строки email и domains, а затем укажите в них свои данные.

Файл должен выглядеть так (закомментированные строки опущены):

rsa-key-size = 4096
email = you@example.com
domains = example.com, www.example.com

После этого раскомментируйте строку standalone-supported-challenges и замените её значение на http-01.

standalone-supported-challenges = http-01

Можно не указывать домен в команде, а просто использовать конфигурационный файл Let’s Encrypt для автоматического внесения домена в команду. Для обновления сертификата можно использовать следующую команду:

cd /opt/letsencrypt
./letsencrypt-auto certonly --renew-by-default --config /usr/local/etc/le-renew-haproxy.ini --http-01-port 54321

Примечание: Подробнее о файле le-renew-haproxy.ini – здесь.

Скрипт для обновления сертификата

Чтобы автоматизировать процесс обновления сертификата, используйте скрипт оболочки, который будет отслеживать срок действия сертификата и обновлять его за 30 дней до истечения этого срока. Скрипт будет запускаться раз в неделю. Таким образом, в случае сбоя cron у вас будет в запасе 30 дней, чтобы снова попытаться обновить сертификат.

Загрузите скрипт и сделайте его исполняемым; предварительно можно просмотреть его содержимое.

sudo curl -L -o /usr/local/sbin/le-renew-haproxy https://gist.githubusercontent.com/thisismitch/7c91e9b2b63f837a0c4b/raw/700cfe953e5d5e71e528baf20337198195606630/le-renew-haproxy
sudo chmod +x /usr/local/sbin/le-renew-haproxy

Скрипт le-renew использует домен в качестве аргумента. Если в обновлении сертификата нет необходимости, скрипт просто сообщит, сколько дней осталось до истечения срока действия сертификата.

Примечание: Скрипт не запустится, если файла /usr/local/etc/le-renew-haproxy.ini не существует. Также нужно убедиться, что в начале конфигурационного файла и в начале сертификата (при его создании) был указан один и тот же домен.

Поскольку текущий сертификат был создан только что, у скрипта нет необходимости обновлять его и он просто сообщит, сколько дней осталось до истечения срока действия сертификата:

sudo le-renew-haproxy
Checking expiration date for example.com...
The certificate is up to date, no need for renewal (89 days left).

После этого нужно отредактировать crontab и добавить в таблицу новую команду, которая будет запускаться раз в неделю.

sudo crontab -e

Затем добавьте следующую строку:

30 2 * * 1 /usr/local/sbin/le-renew-haproxy >> /var/log/le-renewal.log

Сохраните и закройте файл. Теперь cron будет запускать команду le-renew каждый понедельник в 2:30 ночи, а вывод команды будет помещён в лог /var/log/le-renewal.log.

Примечание: Больше информации о работе cron можно получить в статье «Автоматизация задач с помощью cron».

Заключение

Теперь HAProxy защищен при помощи SSL-сертификата Let’s Encrypt. Не забывайте о том, что клиент Let’s Encrypt до сих пор находится в бета-версии, потому очень важно следить за выходом обновлений и своевременно устанавливать их.

Tags: , , ,

Добавить комментарий