![NGINX-loadbalancer と NGINX-reverse-ssl-terminating-proxy の間で PROXY プロトコルを使用すると SSL が機能しない](https://rvso.com/image/762114/NGINX-loadbalancer%20%E3%81%A8%20NGINX-reverse-ssl-terminating-proxy%20%E3%81%AE%E9%96%93%E3%81%A7%20PROXY%20%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E3%81%A8%20SSL%20%E3%81%8C%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%AA%E3%81%84.png)
NGINX ロード バランサー (ストリーム モジュールに基づく) とエンド ユーザーの実際のリモート IP の使用に問題があります。
状況
私たちの状況には多くのサーバーが含まれていますが、関連するサーバーは 2 つあります。
- サーバーA -> ストリームモジュールを使用してNGINXを実行するロードバランサー
- サーバーB -> SSLターミネーションを担当する関連アプリケーションへのNGINXリバースプロキシを実行する上流
サーバー 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
}
ssl
およびディレクティブを使用して、ポート 4431 をリッスンする別の例がありますproxy_protocol
。私が理解している限りでは、これは、リッスン サーバーがロード バランサーから送信される PROXY プロトコル メッセージをサポートする必要があることを意味します。
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 を使用して接続できない理由がわかりません。おそらく (あるいは、私が期待している以上に) 何か単純なことを見落としているのでしょう。私が何を間違っているのか、または何を見逃しているのか、誰かわかる人はいませんか?