F5のSSLアクセラレータBIG-IPで特定のディレクトリパスだけ、クライアント証明書がインストールされたPCからじゃないとアクセスができないように制御したいとの要望があったため実装した。結論:iruleを使えば可能。
環境説明
- 構成補足
- BIG-IPのSSLアクセラレータでHTTPSを終端し、サーバにはHTTPで通信を行う
- 正式に発効されたサーバ証明書のプロファイルに、クライアント証明書を追加しセキュリティを上げる
- https://hogehoge.piteki.com/
- 誰でもアクセス可
- https://hogehoge.piteki.com/secure/
- クライアント証明書のインストールされたPCのみアクセス可
BIG-IP設定(クライアント証明書認証)
- Local Traffic ›› Profiles : SSL : Client
- サーバ証明書を設定したプロファイルを選択
- Client Authentication項目
- Client Certificate : request
- クライアント証明書を利用するだけならrequireでも可能だが、今回はURIでの仕分けをiruleで実装するため、requestにする必要がある
- 参考:https://nwengblog.com/bigip-client-ssl-profile/#toc6
- Frequency : always
- 「once」にした方が、セッションが閉じられるまで維持するので、BIG-IPの負荷は下げられる。ただ、今回のiruleを利用する場合は、「always」にしておかないと正常に動作しないため注意
- Retain Certificate : ☑ Enable
- Certificate Chain Traversal Depth : 9
- Trusted Certificate Authorities : クライアント証明書のルート証明書
- Advertised Certificate Authorities : 上記と同じでOK
- Certificate Revocation List (CRL) : None
- 証明書失効リストのこと。今回は使わない。
- Client Certificate : request
ここまでで、クライアント証明書認証によるアクセス制限は完了
BIG-IP設定(クライアント証明書ごと+URIによるアクセス制限)
複数のクライアント証明書を利用してて、証明書ごとにアクセス制限を実装したい場合は下記のようなiruleで実現が可能
when RULE_INIT {
set static::subject_dn 0
}
when CLIENTSSL_CLIENTCERT {
if {[SSL::cert 0] eq ""}{
set static::subject_dn 1
} else {
set static::subject_dn [X509::subject [SSL::cert 0]]
}
}
when HTTP_REQUEST {
if { [HTTP::uri] starts_with "/secure" } {
if { !($static::subject_dn starts_with "CN=HOGEHOGE") } {
reject
}
}
}
- ポイント
- RULE_INITで「static::subject_dn」のようにグローバル変数にせず、「subject_dn」だけだと、DEBUGで変数をログ出力させると、変数を渡してるように見えるが、構文エラーが出続ける状態になった。
- クライアント証明書を利用しているかどうかの判定「[SSL::cert 0] eq “”」は、「ne」で否定文のみにすると、複数回アクセスしてるうちに判定がおかしくなるので、「else」を使って両方明文化する必要がある。
- Frequencyを「always」にしておかないと、このirule処理が正常に動作しないので注意(※理屈はわかるが、思った動作にならなかったので、詳細は割愛)
- 動作がうまくいかないなら、公式に書いてあるようなDEBUG処理を入れて、ログから情報を取得すればいい。ログは「System ›› Logs : Local Traffic」で参照できる。
- 参考文献
- Client Certificate CN Checking
- X509 Command List
- SSL::Profile
- HTTP::uri
- BIG-IPで、Hostヘッダに基づいた振り分けを行うiRule3種
- うまいぼう先輩のAPMメモ
その他(opensslでのpfx分解)
渡された証明書がpfx形式(PKCS#12証明書)だったので分解方法
分解後のファイルには不要な情報があるので、BEGINとENDで挟まれた内容以外は削除
- 秘密鍵の取り出し
- 分解ファイル名:test.pfx
- 出力秘密鍵名:test.key
- パスワード:hogehoge
# openssl pkcs12 -in test.pfx -nocerts -nodes -out test.key -passin pass:hogehoge
- 証明書の取り出し
- 分解ファイル名:test.pfx
- 出力証明書名:test.crt
- パスワード:hogehoge
# openssl pkcs12 -in test.pfx -clcerts -nokeys -out test.crt -passin pass:hogehoge
- 中間証明書の取り出し
- 分解ファイル名:test.pfx
- 出力中間証明書名:test.ca
- パスワード:hogehoge
# openssl pkcs12 -in test.pfx -cacerts -nokeys -out test.ca -passin pass:hogehoge
コメント