LoginSignup
5
2

More than 5 years have passed since last update.

BIG-IPで、Virtual ServerにBASIC認証を仕掛ける

Posted at

はじめに

このページでは、BIG-IPで、Virtual Server(HTTP or HTTPS)へのアクセスにBASIC認証を仕掛けるための方法について記載します。BASIC認証は、セキュリティ的にどうだろうかと思わなくもありませんが、調べてみると、まだまだ需要はあるようです。少なくとも通信経路は必ず暗号化しましょう。

BASIC認証は、Apacheやnginxならばconfファイルで簡単にできることですが、BIG-IPではiRuleが必要です。また、ユーザ名とパスワードの保管のために、Data Group Listも使います。

参考情報

環境

このページに記載のiRuleはv12.1.2で動作を確認してます。

iRule

動作

このiRuleは、以下のような動作を行います。わざわざ箇条書きにしていますが、ごく普通のBASIC認証です。

  1. BIG-IPのVirtual Serverの、特定のディレクトリ配下(ここでは/mgmt/)へのアクセス時に、BASIC認証を行う
  2. BIG-IPには、認証に必要なユーザ名とパスワード(パスワードをsha256でハッシュした後の文字列)をあらかじめData Group Listとして登録しておく
  3. BIG-IPは、/mgmt/で開始するURLへのアクセス時に対して、BASIC認証の情報(ユーザ名とパスワード)が含まれていない場合、401 Unauthorizedを応答する
  4. BASIC認証の情報がBIG-IPのData Group Listに登録されているユーザ名とパスワードに一致する場合は、Poolへ通信を振り分ける

本ページのサンプルでは、認証用のユーザ名とパスワードは「ユーザ名:admin、パスワード:admin」としています。

コード

proc basic_auth {} {
    binary scan [ sha256 [HTTP::password]] H* password
    if { [class lookup [HTTP::username] authorized_users] ne $password } {
        log local0. "User [HTTP::username], has been denied access to virtual server [virtual name]."
        HTTP::respond 401 WWW-Authenticate "Basic realm=\"Secured Area\""
    }
}

when HTTP_REQUEST {
    if {[HTTP::uri] starts_with "/mgmt/"} {
        call basic_auth
    }
}

Data Group List

Data Group list名"authorized_users"を作成して、ユーザ名と、パスワード”admin"をsha256でハッシュ化した値を保存します。

GUI画面(Configuration Utility)では、このような画面になります。
basic_auth_dgl_sha256.png

複数のユーザを登録する場合は、このData Group Listにレコードを追加します。

パスワードのSHA256ハッシュ変換は、BIG-IPのbashを使う場合、以下のようなコマンドで可能です。

$ echo -n "admin" | sha256sum 
8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918  -

Virtual Server

このiRuleをVirtual Serverに適用します。これについては特に書くべきことはありません。

動作確認

まず、通常のページ(/index.html)にアクセスした場合。

$ curl -i http://203.0.113.1/index.html

HTTP/1.1 200 OK
Content-Type: text/html
Accept-Ranges: bytes
Content-Length: 23
Server: lighttpd/1.4.45

This is a test server.

認証なく、問題なくアクセスができています。

次に、BASIC認証が必要なディレクトリ配下(/mgmt/index.html)に、認証なしでアクセスした場合。

$ curl -i http://203.0.113.1/mgmt/index.html

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Secured Area"
Server: BigIP
Connection: Keep-Alive
Content-Length: 0

BIG-IPが応答して、401を応答してます。

次は認証用のユーザ名とパスワードを入れますが、間違ったパスワードでアクセスした場合。

$ curl -i -u admin:admin2 http://203.0.113.1/mgmt/index.html

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Secured Area"
Server: BigIP
Connection: Keep-Alive
Content-Length: 0

依然、401が応答し続けます。ちなみに上記2回のアクセスは、BIG-IPの/var/log/ltmに、次のような感じで記録されます。

info tmm[17378]: Rule /Common/Sample_Basic_Auth <HTTP_REQUEST>: User , has been denied access to virtual server /Common/vs_public.
info tmm[17378]: Rule /Common/Sample_Basic_Auth <HTTP_REQUEST>: User admin, has been denied access to virtual server /Common/vs_public.

Sample_Basic_AuthはiRuleの名前で、vs_publicはVirtual Serverの名前です。

最後に、正しいユーザ名とパスワードでアクセスした場合。

$ curl -i -u admin:admin http://203.0.113.1/mgmt/index.html

HTTP/1.1 200 OK
Content-Type: text/html
Accept-Ranges: bytes
Content-Length: 32
Server: lighttpd/1.4.45

This page needs authentication.

BIG-IPでの認証が通り、サーバからのレスポンスが得られました。

解説

procについて

procは、tclでサブルーチン(関数)を作るコマンドです。tclではサブルーチンのことを「プロシジャ」と呼ぶそうなので、ここではプロシジャと呼ぶことにします。

プロシジャは次のような文法となります。

proc プロシジャ名 {引数1 引数2 ...} {
    プロシジャ内の処理...

    # 特定の値を返したい場合はreturnを使う
}

# プロシジャを実行する際はcallを使う
call プロシジャ名 引数1 引数2 ...

一般的なプログラミング言語の関数と同様に、引数や戻り値が利用できますが、今回使用しているプロシジャでは不要なので、使用していません。returnを使わない場合、プロシジャの終了時、プロシジャ内で最後に実行したコマンドの戻り値が、プロシジャの戻り値になります。

引数が0個の時、プロシジャの定義時に"proc プロシジャ名 {} {"と、引数に空のリスト{}をつけるべきなのか気になりましたが、このページ(wiki.tcl.tk)を参考にして、空のリストをつけることにしました。ただし、DevCentralのページには、引数のないプロシジャ(単に {}を書かないだけ)のサンプルコードが普通にあるので、少なくともiRuleでは空リストは書かなくとも良さそうです。

procの面白いのは、これがBIG-IPに実装されたのは、案外最近(v11.4以降)ということです。参照情報にあげたprocの解説ページには"Ladies and gentlemen, procs are now supported in iRules!"とデカデカと書かれていて、それまでどれだけ待ち望まれていたのかと思います。プログラミング言語では、サブルーチンを作れるのは当然のことのように思いますが、iRuleにそれを実装するのは、簡単なことではなかったようです。

procで作成したプロシジャは、同一iRule内からだけでなく、外部のiRuleからもcallすることができます。procについては、いずれ別ページを作成したいと思います。

[HTTP::username] と [HTTP::password]について

これらのコマンドにより、HTTP Basic認証のユーザ名とパスワードを取得できます。詳細はDevCentralを参照してください。

HTTP Basic認証では、これらの情報はクライアントからサーバへの通信時、BASE64でエンコードされていますが、[HTTP::username] と [HTTP::password]はデコードした値を返すので、デコード処理を作成する必要はありません。

パスワードをハッシュ化した値で保存する意味

Data Group Listにはパスワードをハッシュ化した値を保存してますが、そもそも、Basic認証ではパスワードは単にBase64エンコードされた文字列に過ぎず、通信経路での傍受については、ハッシュ化は何の意味もありません。通信経路での安全性は、HTTPS化で対応すべきと思います。

Apacheやnginxでは、パスワード情報は一般的にハッシュ化してるので、このiRuleでもハッシュ化するようにしてます。

「パスワード情報(Apacheで言うところの.htpasswd)が漏洩したらどうするんだ」という点で、ハッシュ化する意味は確かにあるのですが、そもそもこのData Group Listが保存されるのは、bigipの設定ファイルであるbigip.confであり、このファイルが外部に漏れたら、Basic認証のパスワードどころの騒ぎではないような気もします。が、それでもやらないよりはマシかと思います。

Data Group Listを外部ファイル参照(external)にするようなケースでは、ハッシュする価値はよりあるのではないでしょうか。

DevCentralにあるサンプルコードではmd5でハッシュしていましたが、時代の流れと思ってsha256でハッシュ化することにしました。これについては、サンプルコードの"md5"を"sha256"に置き換えただけです。

免責事項

本ページの内容に誤り等があり、参考にされた方がなんらかの損害を被った場合、一切の責任は負いません。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2