Расширенная настройка обратного прокси на Nginx подразумевает шифрование трафика, корректную обработку исходного адреса клиента и некоторые другие моменты.
Если вам интересна тематика Debian и связанных с ним приложений, рекомендую обратиться к тегу Debian на моем блоге
Настройка обратного прокси на Nginx
В предыдущей статье – Обратный прокси на Nginx – я затронул лишь базовые нюансы настройки проксирования. Теперь же я хочу сильнее углубиться в тему и рассказать о рабочих моментах, без которых в настоящее время не обойтись.
Предлагаю ознакомиться с другими статьями про Nginx на моем блоге:
Приятного чтения!
Реальный адрес клиента
Разместив свой сервер за обратным прокси, вскоре вы можете обнаружить, что как минимум с вашими логами что-то не так, например:
1 2 |
172.16.0.5 - - [07/Apr/2018:14:04:35 +0300] "GET /favicon.ico HTTP/1.0" 200 201 "http://bissquit.com/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" 172.16.0.5 - - [07/Apr/2018:14:07:11 +0300] "GET / HTTP/1.0" 200 13566 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1" |
Казалось бы, ничего особенного – одна запись свидетельствует о входе с обычного браузера ПК, а вторая – с iPhone, но адрес устройств почему-то везде одинаковый и он совпадает с адресом вашего обратного прокси.
Почему так произошло? Как я и упоминал в предыдущей статье, обратный прокси общается с серверами бэкэнда от имени клиентов, перенаправляя их запросы. Значит исходный адрес клиента будет соответствовать адресу прокси, что мы и видим в логах.
Единственный способ исправить эту ситуацию – как-то передавать реальный адрес клиента в других http-заголовках (X-Real-IP, X-Forwarded-For), а также дополнительную информацию (например прокси-хост, протокол и др.).
Секция server в базовом варианте примет следующий вид:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto http; proxy_set_header Host $host; server_name site.tld blog.site.tld; location / { proxy_pass http://blog; } } |
Подробнее о каждой директиве, заголовках и переменных читайте в официальной документации 1.
Не стоит забывать, что на стороне бэкэнда необходимо также изменить поведение и извлекать нужную информацию из определенных заголовков. Если нужны только “правильные” логи, то достаточно немного переписать их формат, например (см. книгу Администрирование сервера NGINX):
1 |
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer} i\" \"%{User-Agent}i\"" combined |
Для изменения заголовка REMOTE_ADDR, чтобы php-скрипты видели реальные адреса клиентов, нужно установить дополнительный модуль – mod-rpaf (или ему подобные) 2:
1 |
apt-get install libapache2-mod-rpaf |
По умолчанию после установки он уже активирован и остается лишь настроить его. Если модуль не активен, выполните команду:
1 |
a2enmod rpaf |
Затираем содержимое файла:
1 |
> /etc/apache2/mods-available/rpaf.conf |
Открываем его для редактирования, вставляем:
1 2 3 4 5 6 |
<IfModule rpaf_module> RPAFenable On RPAFsethostname On RPAFproxy_ips 172.16.0.5 RPAFheader X-Forwarded-For </IfModule> |
Перезапускаем Apache:
1 |
service apache2 restart |
На этом настройка закончена. Не забывайте, что обратный прокси и серверы бэкэнда могут по-разному обрабатывать и выдавать заголовки. При этом неправильная настройка может быть причиной проблем с безопасностью 3 4.
SSL
Без SSL сегодня никуда, а потому займемся настройкой шифрования между клиентами и нашим nginx.
Важной особенностью является тот факт, что обратный прокси у нас будет выполнять функцию разгрузки SSL (SSL offload). Это означает, что накладные расходы шифрования/дешифрования ложатся именно на обратный прокси, но не на серверы бэкэнда. Это позволит снять с них действительно ресурсоемкую задачу.
Добавляем нужные директивы и получаем конфиг (c учетом настроек из предыдущей главы):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
server { listen 443 ssl; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_certificate /etc/ssl/certs/certificate.crt; ssl_certificate_key /etc/ssl/private/private.key; ssl_ciphers HIGH:!aNULL:!MD5; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Host $host; server_name site.tld blog.site.tld; location / { proxy_pass http://blog; } } |
Модуль ngx_http_ssl_module имеет значительно больше параметров, не поленитесь почитать документацию 5.
Надо отметить, что многие параметры ssl по умолчанию находятся в основной секции конфигурации (http). В зависимости от ситуации решите где именно вы их оставите.
Редирект
Следующим логичным шагом после реализации SSL может быть настройка перенаправления 7 с 80 на 443 порт. Делается это очень просто, но важно учесть best practic 8.
Нам понадобится отдельная секция server, которая будет отвечать за прослушку 80 порта и перенаправление на 443:
1 2 3 4 5 |
server { listen 80; server_name site.tld blog.site.tld; return 301 https://$server_name$request_uri; } |
Перезапустите демона. Думаю, что на этой ноте настройка обратного прокси на Nginx завершена.