У меня возникла проблема с нашим балансировщиком нагрузки NGINX (на основе потокового модуля) и использованием реальных удаленных IP-адресов наших конечных пользователей.
Ситуация
В нашей ситуации задействовано много серверов, но есть два важных сервера:
- Сервер A -> Балансировщик нагрузки, работающий под управлением NGINX с модулем stream-module
- Сервер B -> вышестоящий, на котором запущен обратный прокси-сервер NGINX для нашего соответствующего приложения, отвечающий за SSL-терминацию
Сервер A использует SNI для маршрутизации к различным восходящим потокам (используя ssl_preread on
).
Я думаю, мы хотим добиться следующей ситуации:
Client ---[HTTPS]---> NGINX LB ---[PROXY PROTOCOL]---> NGINX Reverse proxy incl. SSL-termination ---[HTTP]---> PHP-container
Конфигурация
Для этой конкретной ситуации я добавил дополнительный блок сервера в наш поток с другим портом, чтобы иметь возможность протестировать это вместе с некоторыми другими проектами. Соответствующая часть конфигурации на сервере A:
stream {
server {
listen 4431;
listen [::]:4431;
ssl_preread on;
proxy_pass 172.16.25.4:4431;
proxy_protocol on;
}
}
Как можно заметить, порт 4431 перенаправляется на наш восходящий порт 4431, поэтому proxy_protocol on
здесь следует использовать прокси-протокол.
На нашем сервере B (вышестоящий 172.16.25.4
) у меня есть еще один экземпляр NGINX со следующей конфигурацией:
server {
server_name <REDACTED>;
location / {
proxy_pass http://127.0.0.1:8000/;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header x-forwarded-proto https;
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
proxy_set_header X-Real-IP $proxy_protocol_addr;
}
listen 4431 ssl proxy_protocol;
ssl_certificate /etc/letsencrypt/live/<REDACTED>/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/<REDACTED>/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
Вы видите еще один прослушиваемый порт 4431 с директивами ssl
и proxy_protocol
. Насколько я понял, это означает, что прослушивающий сервер должен поддерживать сообщения PROXY-protocol-messages, поступающие от нашего балансировщика нагрузки.
Проблема с SSL-соединением
Однако я не могу установить SSL-соединение. Я понимаю, что это невозможно с сервера B (так как клиент не использует протокол PROXY), но я думаю, что это должно быть возможно с сервера A. Если я попытаюсь подключиться, то получу следующий ответ:
user@ServerA $ openssl s_client -connect 127.0.0.1:4431 -servername <REDACTED>
CONNECTED(00000003)
write:errno=0
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 320 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Я не понимаю, почему я не могу подключиться с помощью SSL из нашего балансировщика нагрузки, я полагаю (или, может быть, я надеюсь), что это что-то очень простое, что я упускаю. Есть ли у кого-нибудь идеи, что я делаю неправильно или что я упускаю?