このブログ記事では、SSL 暗号化された Web サイトをホストするときに NGINX が使用する SSL 秘密鍵を安全に配布するいくつかの方法について説明します。 それは次のように説明しています:
多くの展開では、標準的なアプローチで十分です。 この投稿で説明する 2 つのより洗練されたアプローチは、攻撃者が SSL 秘密鍵を取得できる他の方法をブロックします。 後続の投稿では、さらにいくつかのテクニックについても見ていきます。
この記事で紹介したアプローチは、独自のキーを管理し、独自の安全なキー配布戦略を作成する必要があるユーザーに適用されます。 Kubernetesなどのシークレット ストアとすでに統合されている環境で NGINX を実行しているユーザーには、これらは必要ありません。
この投稿は、NGINX Open Source と NGINX Plus の両方に適用されます。 読みやすくするために、全体を通じてNGINXを参照します。
編集者 – この投稿は、NGINX で SSL 秘密鍵を保護する方法に関するシリーズの最初の投稿です。シリーズの他の投稿もご覧ください。
SSL/TLS は、ネットワーク トランザクションの認証、暗号化、整合性の検証に使用されます。 ウェブサイトは、証明機関 (CA) によって署名された公開証明書を使用して自身を認証し、対応する秘密鍵(秘密に保持する必要がある) を使用して計算を実行することで、証明書を所有していることを証明します。
秘密鍵が侵害された場合(別のエンティティに開示された場合)、主に 2 つのリスクがあります。
秘密鍵が侵害された場合、唯一の手段は CA に連絡して証明書の失効を要求することです。その後は、クライアントに頼って失効ステータスを確認してもらいます。
さらに、有効期限が短い証明書を使用することをお勧めします (たとえば、 Let's Encrypt証明書は 90 日後に有効期限が切れます)。 証明書の有効期限が切れる直前に、新しい秘密キーを生成し、CA から新しい証明書を取得する必要があります。 これにより、秘密鍵が侵害された場合のリスクが軽減されます。
NGINX の SSL 秘密鍵にアクセスできるのはどのユーザーとプロセスですか?
まず、NGINX を実行しているサーバーにルート
アクセス権を取得したユーザーは、NGINX 自体が使用するすべてのリソースを読み取って使用できます。 たとえば、実行中のプロセスのメモリから SSL 秘密キーを抽出する方法が知られています。
したがって、秘密鍵がどのように保存および配布されたとしても、ホスト サーバーのルート
権限を持つ攻撃者から秘密鍵を保護することはできません。
次に、NGINX 設定を変更してコミットできるユーザーは、内部サービスへのプロキシ アクセスを開いたり、認証手段をバイパスしたりなど、さまざまな方法でその権限を使用できます。 NGINX の設定を変更して、サーバーへのルート
アクセス (または同等のアクセス) を取得することもできますが、 SELinuxやAppArmorなどのツールを使用すると、その可能性を軽減できます。
したがって、通常、NGINX 構成を変更してコミットできる攻撃者から秘密鍵を保護することはできません。
幸いなことに、有能な組織であれば、攻撃者がルート
権限を取得したり、NGINX 構成を変更したりすることを困難にする健全なセキュリティ プロセスを備えています。
ただし、権限の低い攻撃者が秘密鍵にアクセスできる方法は他に 2 つあります。
このドキュメントで説明するプロセスは、これら 2 つの攻撃方法を封じ込めます。
まず、SSL/TLS を使用した一般的な NGINX 構成がどのようなものかを確認します。
server { listen 443 ssl; server_name a.dev0; ssl_certificate ssl/a.dev0.crt; ssl_certificate_key ssl/a.dev0.key; location / { return 200 "Hello from service A\n"; } }
SSL 公開証明書 ( a.dev0.crt ) と秘密鍵 ( a.dev0.key ) は、ファイルシステムの/etc/nginx/ssl/に保存されます。 秘密鍵は、通常はroot
として実行される NGINX マスター プロセスによってのみ読み取られるため、可能な限り厳しいアクセス権限を設定できます。
root@web1:/etc/nginx/ssl# ls -l a.dev0.key -r-------- 1 root root 1766 8月15日 16:32 a.dev0.key
秘密鍵は常に使用可能である必要があります。NGINX マスター プロセスは、NGINX ソフトウェアの起動時、構成の再読み込み時、または構文チェックの実行時 ( nginx
-t
) に必ず秘密鍵を読み取ります。
SSL/TLS の設定の詳細については、 NGINX Plus 管理者ガイドを参照してください。
前述のように、SSL 秘密キーは、NGINX ソフトウェアを実行している実行中のコンテナ、仮想マシン、またはサーバーへのルート
アクセス権を取得した攻撃者によって読み取られる可能性があります。
NGINX は、AES256 などの安全なアルゴリズムを使用して暗号化された秘密鍵をサポートします。
root@web1:/etc/nginx/ssl# mv a.dev0.key a.dev0.key.plain root@web1:/etc/nginx/ssl# openssl rsa -aes256 -in a.dev0.key.plain -out a.dev0.key RSA キーの書き込み PEM パスフレーズを入力してください:安全なパスワード確認中 - PEM パスフレーズを入力してください:安全なパスワードをもう一度
その後、NGINX を起動するか、NGINX 設定を再読み込みまたはテストすると、NGINX は対話的に復号化パスワードを要求します。
root@web1:/etc/nginx# nginx -t PEM パスフレーズを入力:安全なパスワードnginx: 設定ファイル /etc/nginx/nginx.conf の構文は正常です nginx: 設定ファイル /etc/nginx/nginx.conf のテストが成功しました
パスワードを対話的に入力するのは不便で自動化も困難ですが、 ssl_password_file
ディレクティブで指定された別のファイルに保存されているパスワードのリストを使用するように NGINX を設定できます。 NGINX は秘密鍵を読み取る必要がある場合、ファイル内の各パスワードを順番に使用して鍵の復号化を試みます。 いずれのパスワードも有効でない場合、NGINX は起動を拒否します。
ssl_password_file /var/lib/nginx/ssl_passwords.txt;
ssl_password_file は
構成とは別に配布され、 root
ユーザーのみが読み取り可能である必要があります。 これは、信頼できるサーバーに配置される認証トークンと見なすことができます。 NGINX は、認証トークンを持つサーバー上で実行されている場合にのみ、秘密鍵を復号化できます。
この方法では、NGINX 構成のみを攻撃者にとって役に立たないものにすることで、攻撃対象領域を減らします。 攻撃者はssl_password_file
の内容も取得する必要があります。
攻撃者がssl_password_file
が保存されているファイルシステムへのルート
アクセスを取得した場合 (たとえば、バックアップから、またはホスト システムを通じて)、そのファイルを読み取り、パスワードを使用して SSL 秘密キーを復号化できます。
ssl_password_file を
RAM ディスクまたはtmpfsに保存することで、このリスクを軽減できます。 このストレージは、通常、外部の攻撃者によるアクセスが困難であり (たとえば、サーバーを再起動するとクリアされます)、システム バックアップから除外できます。 システムの起動時にパスワード ファイルが初期化されていることを確認する必要があります。
以下のプロセスでは、中央の配布ポイントから SSL パスワードのリストを配布するより安全な方法について説明します。
NGINX は SSL キーを復号化する必要があるときはいつでも、中央配布ポイントにクエリを実行し、パスワードをローカル ディスクに保存せずに使用します。 NGINX インスタンスは、中央パスワード サーバーで自身を認証するためにトークンを使用します。このトークンはいつでも取り消して、パスワードへのアクセスを遮断できます。
まず、パスワード配布ポイント (PDP) を作成します。 このシンプルな実装では、ユーザー名とパスワードで認証されたパスワード リストを配信するために HTTPS サービスを使用しています。
$ curl -u dev0:mypassword https://pdpserver.local/ssl_passwords.txtパスワード1 パスワード2 ...
必要に応じて、PDP で認証トークンを追加または削除することで、アクセスを有効化または取り消すことができます。 NGINX などの Web サーバーを使用してパスワード配布サーバーを実装し、適切な種類の認証トークンを使用できます。
次に、PDP からパスワードを取得するために NGINX を設定する必要があります。 まず、次の内容のconnector.shというシェル スクリプトを作成します。
#!/bin/sh
# 使用方法: connector.sh
CONNECTOR=$1
CREDS=$2
PDP_URL=$3
[ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR
mkfifo $CONNECTOR; chmod 600 $CONNECTOR
while true; do
curl -s -u $CREDS -k $PDP_URL -o $CONNECTOR
done
スクリプトは、次のように呼び出されてバックグラウンド プロセスとして実行する必要があります。
root@web1:~# ./connector.sh /var/run/nginx/ssl_passwords \dev0:mypassword https://pdpserver.local/ssl_passwords.txt &
コネクタは指定されたローカル パス ( /var/run/nginx/ssl_passwords ) に接続され、 ssl_password_file
ディレクティブを使用して NGINX がそのパスにアクセスするように構成します。
ssl_password_file /var/run/nginx/ssl_passwords;
コネクタ パスから読み取ってコネクタをテストします。
root@web1:~# cat /var/run/nginx/ssl_passwordsパスワード1 パスワード2 ...
NGINX がパスワードを読み取り、SSL キーを復号化できることを確認します。
root@web1:~# nginx -t nginx: 設定ファイル /etc/nginx/nginx.conf の構文は正常です nginx: 設定ファイル /etc/nginx/nginx.conf のテストは成功しました
集中型 PDP アプローチを使用すると、個々の秘密鍵やその他の機密データなど、NGINX が通常ディスクから読み取るリソースを安全に配布できます。
このソリューションには、SSL パスワードをディスクに保存する場合と比べていくつかの利点があります。
ファイルシステムにアクセスできるユーザーは、PDP へのアクセスに使用される資格情報を抽出できる可能性があることに注意してください。 これらの資格情報は、不要になったときに取り消すことが重要です。
SSL 秘密鍵の漏洩を防ぐ方法は数多くあり、セキュリティと複雑さのレベルが高まっています。
ルート
アクセスを取得したり、NGINX 構成を確認したりできないように、NGINX を実行している環境へのアクセスを制限するだけで十分です。このシリーズの他の投稿では、SSL キーを保護するために実行できる追加の手順について説明します。
NGINX Plus をぜひお試しください。今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、ユースケースについてご相談ください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"