先日、**nginxでクライアント証明書を検証して失敗した際に、外部サーバに用意しているカスタムエラーページにプロキシしたいという要件が発生し、**四苦八苦しながらnginx.confを書いていました。
既に忘れ始めているため、備忘録としてその際の構文を残しておきます。
nginx.conf
server {
ssl_verify_client optional;
location / {
if ($ssl_client_verify != SUCCESS) {
proxy_pass https://hoge.com/error.html;
}
}
}
※ 一部構文を抜粋しているため完全には動作しません
ssl_verify_clinet
ssl_verify_clientでクライアント証明書の検証を行います。証明書失敗時は、400ステータスコードが返されます。また、on、off、optional、optional_no_caの4つのsyntaxを設定できます。
onに設定した場合、検証に失敗した時点で終了し、**nginxサーバ内の400ページに強制的にreturnされます。**ですが、今回は、内部ではなく、外部にプロキシしたいため、optionalに設定します。
**optionalに設定すると、$ssl_client_verifyに検証結果が格納され、強制returnがなくなるため、後述でプロキシ設定を追加することができます。**ですが、裏を返せば、自前で検証結果に応じてどう処理するか追加する必要性もあります。また、ssl_verify_clinetと$ssl_client_verifyが似ており、注意が必要です。
$ssl_client_verify
returns the result of client certificate verification: “SUCCESS”, “FAILED:reason”, and “NONE” if a certificate was not present;
証明書検証の結果には、SUCCESSとFAILED:reason、NONEが含まれ、今回はSUCCESSをもとにifディレクティブで検証結果を判別するように記述しています。また、ifは、location、serverディレクティブ内でしか記述できないため注意が必要です。
proxy_pass
プロキシしたいサーバ先のURLで、今回はここにカスタムエラーページのURLを記述しています。
おわりに
なんて事のない設定なのですが、アプリケーションコードと違って、デバックがしづらく、書いてみないとどう動くか?どこがダメなのか?が私には捉えづらく、nginxやapachなどのサーバ設定はまた違う難しさがあるなと改めて感じました。