はじめに
OCIのFLB(フレキシブル・ロードバランサ)は、サーバ証明書に加えクライアント証明書にも対応しています。
リスナーの設定で証明書情報を設定した後、「ピア証明書の検証」を有効にし「深さの検証」を指定することで実現できます。
「ロード・バランサ管理対象証明書」の場合は、以下のようになります。
また、「証明書サービス管理対象証明書」で認証局を使用する場合は、以下のようになります。
ただ、これだけの設定では、クライアント証明書の情報はFLBで終端してしまい、バックエンドサーバには送られずに、アプリケーション側で証明書に含まれるサブジェクト情報等を参照したいケースでは問題が生じてしまいます。
(FLBでもTCPリスナーを使用した場合、またはNLB(ネットワーク・ロードバランサ)を使用する場合は、FLBに証明書情報を設定できず、バックエンドサーバで証明書や秘密鍵の情報を設定することになるので、このような懸念が生じませんが、複数のバックエンドサーバで証明書の情報を管理したり、WAFを使用できないといった制限を受けることとなってしまいます。)
このような問題の回避策として、FLBではクライアント証明書の情報をHTTPリクエストヘッダに追加して、バックエンドサーバへ送ることができるようになっています。
手順
HTTPリクエストヘッダにクライアント証明書の情報を追加する為には、ルール・セットを使用します。
具体的な手順は以下のリファレンスに記載があるので、ご確認下さい。
上記リファレンスでは、HTTPリクエストヘッダに追加する値として3通りの方法が選択できることが分かります。
ヘッダ値 | 説明 |
---|---|
{oci_lb_client_cert} | 証明書情報の先頭行を除く行頭にタブコードを付与した情報を転送します。 |
{oci_lb_client_cert_apache_compatible} | 証明書情報の改行(\n)を削除した情報を転送します。 |
{oci_lb_client_cert_url_encoded} | 証明書情報をURLエンコードした情報を転送します。 |
それぞれの設定値に従って、実際にどのようなヘッダが送信されているか確認してみます。
ヘッダ値:{oci_lb_client_cert}
まずは、ヘッダを「client_cert」として、 ヘッダ値に {oci_lb_client_cert}
を設定したルール・セットを作成し、その後、リスナーに作成したルール・セットを適用します。
設定後、クライアント証明書をインポートしたブラウザからリクエストを送信し、バックエンドのサーバで tcpdump でリクエストをキャプチャしてみました。
タブコードが肝となる為、16進数も出力してますが、改行コード(0a)のあとに、水平タブコード(09)が付与されていることが分かります。
つまり、証明書の先頭行を除いては、全て行の先頭に水平タブコードが付与されています。
但し、Apache では、リクエストヘッダの1つが複数行に跨ってしまう為か、以下のようにブラウザへは「Bad Request」が返されました。
ヘッダ値:{oci_lb_client_cert_apache_compatible}
今度は、ヘッダ値を {oci_lb_client_cert_apache_compatible}
に変更して確認してみます。
変更後に、ブラウザからリクエストを送信してバックエンドサーバでリクエストを確認してみます。
「client_cert」ヘッダには、クライアント証明書の改行(\n)が削除されたものが設定されていることが分かります。
ヘッダ値:{oci_lb_client_cert_url_encoded}
今度は、ヘッダ値を {oci_lb_client_cert_url_encoded}
に変更して確認してみます。
変更後に、再度ブラウザからリクエストを送信してバックエンドサーバでリクエストを確認してみます。
証明書情報のURLエンコードした状態のものが設定されています。
まとめ
ルール・セットを使用してクライアント証明書情報をバックエンドのサーバに転送する方法について確認しました。
HTTPヘッダに追加する方法としては、今回ご紹介した3種類ありますが、{oci_lb_client_cert}
と {oci_lb_client_cert_apache_compatible}
については、行の先頭にタブコードが付与されたり、改行コードが削除されたりしますので、アプリケーション側でパースできない場合もあるかと思います。
証明書情報をそのままにバックエンドサーバに転送したい場合は、 {oci_lb_client_cert_url_encoded}
を設定して、アプリケーション側でURLデコードするとよいでしょう。