Nginxでクライアント証明書認証を行う方法です。
前提条件
今回は下記の設定が終わっていることを前提としています。
- Nginxでhttps接続ができる
- クライアント証明書を作成済み
- クライアント証明をwebブラウザに登録済み
上記の設定手順は下記のページで説明していますので、未設定の場合は参考にしてみてください。
Let's Encryptを使ってSSL/TLS証明書を取得する方法はこちら。
クライアント証明書の作成方法はこちら。
webブラウザに証明書を登録する方法はこちら。
設定内容
Nginxでクライアント証明書認証を行う設定を、下記の2通りについて説明していきます。
- Webサイト全体に設定
- 特定のページに設定
Webサイト全体に設定
Nginxでクライアント証明認証をWebサイト全体行うには、serverディレクティブにssl_client_certificateでCA証明書の場所を指定し、ssl_verify_client onでクライアント証明書認証を有効にする設定を追加します。
ssl_client_certificate "CA証明書の場所"; ssl_verify_client on;
CAの証明書は、クライアント証明書に署名を行った物を指定します。
特定のページに設定
特定のページに設定を行いたい場合は、serverディレクティブ内にssl_client_certificateとssl_verify_client optionalを設定します。
ssl_verify_client optional
ssl_verify_client optionalを設定すると、クライアント証明書を持っていない場合は$ssl_client_verify変数にNONEという値が格納され、認証が通った場合$ssl_client_verify変数にSUCCESSという値が格納されます。
locationディレクティブでクライアント証明書認証を設定したいページを指定し、if文で$ssl_client_verify変数にSUCCESS以外の値が格納されている場合は403のステータスコードを返すという設定を行うことで、特定のページのみクライアント証明書によるアクセス制限を行うことができるようになります。
ssl_client_certificate "CA証明書の場所"; ssl_verify_client optional; location 設定をかける場所 { if ($ssl_client_verify != SUCCESS) { return 403; } }
設定反映
どちらの場合も、設定を行った後にnginxの再起動を行って設定を反映してください。
$ sudo systemctl restart nginx
設定例
下記内容のwebサーバにおいて、サイトの全体に認証を設定する場合と、特定のページに認証を設定する場合についての設定例を説明していきます。
- Let's EncryptでSSL/TLS証明書を取得
- サイト名 ex.server-memo.net
- CA証明書 /etc/nginx/ca.crt
Webサイト全体に設定
webサイト全体にクライアント認証を設定したい場合の設定例です。
赤文字部分がクライアント証明認証に関わる設定になります。
server { server_name ex.server-memo.net; root /usr/share/nginx/ex; index index.html; listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/ex.server-memo.net/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/ex.server-memo.net/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_client_certificate "/etc/nginx/ca.crt"; ssl_verify_client on; }
動作確認
実際にWebブラウザでアクセスして認証が機能しているか確認してください。
クライアント証明書がない場合は400 Bad Requestの画面が表示されます。
クライアント証明書を持っている場合は、認証に使用する証明書を選択する画面が表示されるので、認証に使用する証明書を選択します。
正しい証明書を選択すると認証に成功して、ページが正常に表示されます。
特定のページに設定
「https://ex.server-memo.net/private」といったような特定のページにクライアント証明書認証をかけたい場合の設定例です。
serverディレクティブにssl_client_certificateとssl_verify_client optionalの設定を行い、locationディレクティブにifを使って認証が通ったかの判別設定を記述します。
赤文字部分がクライアント証明認証に関わる設定になります。
server { server_name ex.server-memo.net; root /usr/share/nginx/ex; index index.html; listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/ex.server-memo.net/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/ex.server-memo.net/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_client_certificate "/etc/nginx/ca.crt"; ssl_verify_client optional; location /private { if ($ssl_client_verify != SUCCESS) { return 403; } } }
serverディレクティブでssl_verify_client optionalと設定しているため、locationディレクティブで設定されている以外ページにアクセスした場合も、クライアント証明書を持っている場合は証明書の選択画面が表示されます。
クライアント証明書がwebブラウザに登録されていな場合は、証明書の選択画面は表示されません。
クライアント証明書がない場合や間違った証明書を選択すると、locationディレクティブで設定した通り、403のエラー画面が表示されます。
クライアント証明書の選択を間違った場合
クライアント証明書の選択を間違ってしまった場合等で、正しい証明書を持っているにも関わらず認証失敗してしまう場合は下記の手順を試してみてください。
クライアント証明書を削除する前に、インポートする際に使用した証明書が存在していることを確認しておいてください。
証明書が無い場合は先に証明書をエクスポートしてから、Webブラウザから削除してください。
- Webブラウザからクライアント証明書を削除
- 該当ページにアクセス
- クライアント証明書をWebブラウザに再インポート
コメント