Как настроить балансировку нагрузки Nginx с терминацией SSL
Введение
В этой статье показано, как настроить балансировку нагрузки Nginx с завершением SSL с помощью всего одного SSL-сертификата в балансировщике нагрузки. Это уменьшит ваши накладные расходы на управление SSL, поскольку обновлениями OpenSSL, а также ключами и сертификатами теперь можно управлять из самого балансировщика нагрузки.
О терминации SSL
Nginx можно настроить как балансировщик нагрузки для распределения входящего трафика между несколькими внутренними серверами. Завершение SSL — это процесс, происходящий в балансировщике нагрузки, который обрабатывает шифрование/дешифрование SSL, поэтому трафик между балансировщиком нагрузки и внутренними серверами передается по протоколу HTTP. Серверные части должны быть защищены путем ограничения доступа к IP-адресу балансировщика нагрузки, что объясняется далее в этой статье.
Предпосылки
В этом руководстве команды должны выполняться от имени пользователя root или пользователя с привилегиями sudo. Вы можете увидеть, как настроить это в Учебнике для пользователей.
В качестве справочных материалов можно использовать следующие руководства:
- Настройка сервера LAMP в Ubuntu 14.04
- Настройка SSL на Nginx
- Настройка балансировки нагрузки в Nginx
Сервер LAMP не требуется, но мы будем использовать его в качестве примера в этом руководстве.
Настраивать
В этом руководстве используются следующие 3 капли:
Капля 1 (интерфейс)
- Изображение: Ubuntu 14.04
- Имя хоста: loadbalancer
- Частный IP-адрес: 10.130.227.33
Капля 2 (Бэкенд)
- Изображение: Ubuntu 14.04
- Имя хоста: web1
- Частный IP-адрес: 10.130.227.11
Капля 3 (Бэкенд)
- Изображение: Ubuntu 14.04
- Имя хоста: web2
- Частный IP-адрес: 10.130.227.22
Доменное имя — example.com
Все эти капли должны иметь включенную частную сеть.
Обновите и обновите программное обеспечение на всех трех серверах:
apt-get update && apt-get upgrade -y
Перезагрузите каждый сервер, чтобы применить обновления. Это важно, так как OpenSSL должен быть в последней версии, чтобы быть безопасным.
Мы настроим новый виртуальный хост Nginx для доменного имени с восходящим модулем, балансирующим нагрузку на серверные части.
Перед настройкой балансировки нагрузки Nginx на вашем VPS должен быть установлен Nginx. Вы можете быстро установить его с помощью apt-get
:
apt-get install nginx
На двух внутренних серверах обновите свои репозитории и установите Apache:
apt-get install apache2
Установите PHP на оба внутренних сервера:
apt-get install php5 libapache2-mod-php5 php5-mcrypt
Дополнительные сведения см. в этой статье.
Сгенерируйте ключи и создайте SSL-сертификат
В этом разделе вы выполните шаги, необходимые для создания SSL-сертификата. В этой статье подробно рассказывается о SSL-сертификатах в Nginx.
Создайте каталог SSL-сертификата и переключитесь на него.
mkdir -p /etc/nginx/ssl/example.com
cd /etc/nginx/ssl/example.com
Создайте закрытый ключ:
openssl genrsa -des3 -out server.key 2048
Удалите его парольную фразу:
openssl rsa -in server.key -out server.key
Создайте CSR (запрос на подпись сертификата):
openssl req -new -key server.key -out server.csr
Используйте этот CSR для получения действительного сертификата от центра сертификации или создания самозаверяющего сертификата с помощью следующей команды.
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Как только это будет сделано, этот каталог будет содержать следующие файлы:
- server.key — закрытый ключ
- ca-certs.pem — набор корневых и промежуточных сертификатов ЦС. Присутствует только в том случае, если вы получили действительный сертификат от ЦС.
- server.crt – SSL-сертификат для вашего доменного имени.
Файл виртуального хоста и восходящий модуль
Создайте файл виртуальных хостов в каталоге Nginx.
nano /etc/nginx/sites-available/example.com
Добавьте восходящий модуль, содержащий частные IP-адреса внутренних серверов.
upstream mywebapp1 {
server 10.130.227.11;
server 10.130.227.22;
}
Начните блок сервера после этой строки. Этот блок содержит имя домена, ссылки на вышестоящие серверы и заголовки, которые должны быть переданы на серверную часть.
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://mywebapp1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Директива proxy_set_header
используется для передачи важной информации о запросе вышестоящим серверам.
Сохраните этот файл и создайте символическую ссылку на каталог sites-enabled
.
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
Выполните тест конфигурации, чтобы проверить наличие ошибок.
service nginx configtest
Если ошибки не отображаются, перезагрузите службу nginx.
service nginx reload
Балансировка нагрузки теперь настроена для HTTP.
Включить SSL
Добавьте следующие директивы в файл виртуальных хостов (/etc/nginx/sites-available/example.com) внутри блока server{}
. Эти строки будут показаны в контексте в следующем примере.
listen 443 ssl;
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
Игнорируйте директиву ssl_trusted_certificate
, если вы используете самозаверяющие сертификаты. Теперь блок server
должен выглядеть так:
server {
listen 80;
listen 443 ssl;
server_name example.com www.example.com;
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
location / {
proxy_pass http://mywebapp1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Проверьте наличие ошибок конфигурации и перезагрузите службу Nginx.
service nginx configtest && service nginx reload
Защита внутренних серверов
В настоящее время к веб-сайту, размещенному на внутренних серверах, может получить прямой доступ любой, кто знает его общедоступный IP-адрес. Этого можно избежать, настроив веб-серверы на внутренних серверах так, чтобы они прослушивали только частный интерфейс. Шаги, чтобы сделать это в Apache, следующие.
Отредактируйте файл ports.conf
.
nano /etc/apache2/ports.conf
Найдите следующую строку:
Listen 80
Замените его на собственный частный IP-адрес внутреннего сервера:
Listen 10.130.227.22:80
Сделайте это на всех внутренних серверах и перезапустите Apache.
service apache2 restart
Следующим шагом является ограничение HTTP-доступа к частному IP-адресу балансировщика нагрузки. Следующее правило брандмауэра достигает этого.
iptables -I INPUT -m state --state NEW -p tcp --dport 80 ! -s 10.130.227.33 -j DROP
Замените пример на частный IP-адрес балансировщика нагрузки и выполните это правило на всех внутренних серверах.
Тестирование установки
Создайте файл PHP на всех внутренних серверах (web1 и web2 в этом примере). Это для тестирования и может быть удалено после завершения установки.
nano /var/www/html/test.php
Он должен печатать доступное доменное имя, IP-адрес сервера, IP-адрес пользователя и доступный порт.
<?php
header( 'Content-Type: text/plain' );
echo 'Host: ' . $_SERVER['HTTP_HOST'] . "\n";
echo 'Remote Address: ' . $_SERVER['REMOTE_ADDR'] . "\n";
echo 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'] . "\n";
echo 'X-Forwarded-Proto: ' . $_SERVER['HTTP_X_FORWARDED_PROTO'] . "\n";
echo 'Server Address: ' . $_SERVER['SERVER_ADDR'] . "\n";
echo 'Server Port: ' . $_SERVER['SERVER_PORT'] . "\n\n";
?>
Откройте этот файл несколько раз в браузере или с помощью curl
. Используйте curl -k
в настройках самозаверяющих сертификатов, чтобы curl игнорировал ошибки SSL.
curl https://example.com/test.php https://example.com/test.php https://example.com/test.php
Вывод будет похож на следующий.
Host: example.com
Remote Address: 10.130.245.116
X-Forwarded-For: 117.193.105.174
X-Forwarded-Proto: https
Server Address: 10.130.227.11
Server Port: 80
Host: example.com
Remote Address: 10.130.245.116
X-Forwarded-For: 117.193.105.174
X-Forwarded-Proto: https
Server Address: 10.130.227.22
Server Port: 80
Host: example.com
Remote Address: 10.130.245.116
X-Forwarded-For: 117.193.105.174
X-Forwarded-Proto: https
Server Address: 10.130.227.11
Server Port: 80
Обратите внимание, что адрес сервера меняется при каждом запросе, указывая на то, что на каждый запрос отвечает другой сервер.
Усиление SSL-конфигурации
В этом разделе объясняется, как настроить SSL в соответствии с рекомендациями по устранению уязвимостей старых шифров и протоколов. В этом разделе показаны отдельные строки, а полный файл конфигурации показан в последнем разделе этого руководства.
Включение кэширования сеанса SSL повышает производительность веб-сайтов HTTPS. Следующие директивы должны быть размещены после ssl_trusted_certificate
. Они обеспечивают совместное кэширование размером 20 МБ со временем жизни кэша 10 минут.
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
Укажите протоколы и шифры, которые будут использоваться в соединении SSL. Здесь мы пропустили SSLv2 и отключили небезопасные шифры, такие как MD5 и DSS.
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
Строгая транспортная безопасность предписывает всем поддерживающим веб-браузерам использовать только HTTPS. Включите его с помощью директивы add_header
.
add_header Strict-Transport-Security "max-age=31536000";
Проверьте наличие ошибок конфигурации и перезагрузите службу Nginx.
service nginx configtest && service nginx reload
Полная конфигурация
После настройки и усиления терминации SSL полный файл конфигурации будет выглядеть следующим образом:
/etc/nginx/sites-available/example.com
upstream mywebapp1 {
server 10.130.227.11;
server 10.130.227.22;
}
server {
listen 80;
listen 443 ssl;
server_name example.com www.emxaple.com;
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
add_header Strict-Transport-Security "max-age=31536000";
location / {
proxy_pass http://mywebapp1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Проведите тест SSL-сервера, и эта установка должна получить оценку A+. Запустите тест curl еще раз, чтобы проверить, все ли работает правильно.
curl https://example.com/test.php https://example.com/test.php https://example.com/test.php
Дальнейшее чтение
Чтобы узнать больше об алгоритмах балансировки нагрузки, прочитайте эту статью.