Big-IP APM memo

参考:
hogem.hatenablog.com
www.f5networks.co.jp

SSL - Client Profile

証明書によるクライアント認証を行いたい場合、
普通はclientssl profile でClient Authenticationにrequireにする。
かつ、OCSP レスポンダを使う場合はvirtualserverでAuthentication Profilesを選択する。

が、big-ip APMを使う場合、Client Authenticationはignoreかrequestにしないと
(requireを選ぶと)、ログイン後でネットワークアクセスを選択した場合に
"コンフィグレーションをダウンロードできませんでした"とエラーになった。

ただ、OCSP Responderを使う場合はrequestにしないと証明書チェックで失敗した。

https://support.f5.com/kb/en-us/products/big-ip_apm/manuals/product/apm-authentication-single-sign-on-11-6-0/14.html

From the Client Certificate list, select the option that is applicable to the item you selected when you edited the access policy.
Select request if the Client Cert Inspection agent is used in the access policy.
Select ignore if the On-Demand Cert Auth agent is used.

OCSPレスポンダはaccess policyでしなくて、
virtualserver の時点でチェックしてもどっちでも出来た。

APM単体で考えたら、他でも色々な認証とか制御をするならaccess policyで統一しておくほうが良いかも?

一方、他のvirtualserverSSLクライアント認証をやっていて、OCSP Responders Profileを使っている場合、
virtualserver側でOCSP Respondersやっても良い気がする。
つまりどっちでもいい。

WindowsMac + Safari/ChromeではどちらでOCSP 認証をしても問題はなかったけど、
Mac + FirefoxでのみvirtualserverOCSP認証をするとSSLエラーで接続できなかった。
(Compatibility Matrixにないfirefox versionだったのも関係あるかも)

AAA Server (認証方式)

いろいろあるけど、個人的に扱いやすいかなと思ったのは
Local Database (big-ipに認証情報持つ)
RADIUS
HTTP
にくわえて証明書失効チェックをする場合はOCSP Responderも併用


何となくの雰囲気だけど、あまり認証などの仕事をbig-ipでさせたくないので、
数10ユーザぐらいの規模: Local Database
それ以上になったら外部の認証サーバ使いたい。

  • HTTP

Form Basedな認証(user,passをPOST)やbasic認証がある。

他webアプリケーションと連携するなどで、DBにuser/passをもたせてformで認証したり、
単純にbasic認証使ったりできる。

Form Basedの場合

Start URL: FormのURL
Form Action: POST先のURL

Successful Logon Detection Match Type:
リダイレクトするURL(By Resulting Redirect URL)、応答文字列(By Specific String in Response)など。
Successful Logon Detection Match Value: 判別する文字列

status codeでは判別できないぽい。
文字列で"200 OK"で設定してログイン成功した場合のみに200 OK を返すアプリ書いてみたけど認証失敗しても通ってしまった。
たぶんStart URLのFormを見に行ったときにもレスポンスヘッダが200 OKになるからだと思う。

なんか微妙な気がするけど、手取り早く認証が通ったときだけ特定の文字列を応答するようにして、
それをSuccessful Logon Detection Match Valueに設定しておいた。

グループの判別
  • local Database

あらかじめデータベースに設定しておいて
Session Variable:session.localdb.groups
DB Property: groups
を選んであとはBranch Rulesで分岐を作っていく

  • HTTP

devcentral.f5.com

例えばwebアプリケーション側でX-GROUP: hogehoge などとヘッダでグループを返すようにしておいて、
variable assignで

session.custom.groupname = regexp {X-GROUP: (\w*)} [mcget {session.http.last.response_header.0}] 1 group; return $group

とやれば、session.custom.groupname でグループを取ってこれる。

groupだけの分岐条件を作るならGeneral Purpose - Emptyあたりから作れば良い。

expr { [mcget {session.custom.groupname}] eq "group1" }

適当なアトリビュートでグループの情報を返す。
例えばReply-Messageに設定した場合は
session.radius.last.attr.reply-message
で取ってこれる。

OCSP Responder

上記参照
clientssl profileのClient Certificateでrequestを選ぶこと。

OCSP Responderの設定は Profiles - Authentication - OCSP Respondersで設定するときと同じで、
OCSP ResponderのURLとCertificate Authority Fileの認証局を選ぶ。

route domain

default 以外のroute domainを割り当てる場合は各種認証が終わって、resource assignする直前で、
Route Domain and SNAT Selection を割り当てればよさげ。
(認証の手前でやってもいいけど、各種リソースの割り当ての分岐を考えるとリソースアサインの直前がわかりやすそう)

access policy内でroute domainを割り当てるため、
split tunnelingを使う場合でもNetwork Access - Network Settingsで
192.168.0.0%1/255.255.255.0 などのようにroute domainのIDで設定する必要なく、
普通に192.168.0.0/255.255.255.0 とすれば良い。

接続方式(Resouce Assign)

webブラウザ or Edge Client から接続
初回に管理者権限が必要

natしていたらsource ipはbig-ipのself ipになる (floating ipではない)
(snat poolで他のIPに割り当てることも可能)
big-ip 自身のvirtualserver宛に通信する場合は
source ipはnatされずにdhcpで払い出した(lease poolで設定)IPから来る?

natしなかったらクライアントに払い出す仮想IPアドレスになるのでサーバ側でroutingが必要になる
(default gatewayがbig-ipに向いてたら不要?)

nat について追記
https://support.f5.com/kb/en-us/products/big-ip_apm/manuals/product/apm-visual-policy-editor-11-5-0/3.html#unique_728503150
Network AccessでSNATがnone以外に設定されている場合は常にそれが適用される。
(access policy内でRoute Domain and SNAT SelectionによるSNAT変更は不可能)
ちなみにnetwork accessのSNAT automapの場合、floating ip ではなくnon-floatingのself ipでnatされる。

VirtualServerでSource Address TranslationでSNAT automapでもnatできる。
こちらの場合はfloating ipでnatされる。

  • application access (app tunnel)

network accessの簡易版?
特定のIP、portのみをトンネルする
sshの-L のport forward のようなもの

app tunnel接続時に、remote desktopを起動して自動的に目的のhostに接続、というようなことができる。
Application Path: C:¥windows¥system32¥mstsc.exe
Parameters: /v:%HOST%:%PORT%

webアプリケーションのみに利用可能
big-ipがリバースプロキシになる
clientはブラウザだけあれば良い

リンク先はbig-ipが書き換える
(なのでvirtual serverにrewrite profileを当てる必要がある)

big-ipがリバースプロキシになるので、NATは不要だと思ってたけど、動作/パケットキャプチャを見ている限り、
VirtualServerのSource Address TranslationでNATするか、
access policyのどこかでRoute Domain and SNAT Selectionを適用してNATする必要ある。

webtop

とりあえずFullを割り当てておくのが無難。
単一のリソースしか割り当てない&ログイン時に自動的に目的のリソースへアクセスさせたい、
ということであればfullではなくそれぞれの接続方式にあったものを選ぶと良い。

  • Full

ログイン時に任意のリソース(接続方式)を選べる。
Resource Assingで複数のportal accessを設定しておけば、
複数のwebアプリケーション、network accessへアクセス可能。

1つのwebアプリケーションだけ指定可能
クライアントはapmにログインした瞬間にwebtopで設定したURLにアクセス
=> Resource Assignで指定したportal accessのURLは無視される

1つのnetwork accessのみ利用可能
resource assignで複数のnetwork accessをアサインしていても
webtopがnetwork accessにしていると自動的に1つのみが選ばれてしまう

ややこしいのは/var/log/apmには

notice apd[12278]: 01490008:5: 2a35b42c: Connectivity resource '/Common/network_access1' assigned
notice apd[12278]: 01490008:5: 2a35b42c: Connectivity resource '/Common/network_access2' assigned

と2つアサインされて見えるが、実際にはnetwork_access1 のルーティングしか追加されていなかった。

iphoneから証明書必須ででログインする際のaccess policy

Logon PageをOn-Demand Cert Authより前に持ってこないとEdge Clientから接続できなかった。
証明書インストールしてアクセスして、ログインしても
tail -f /var/log/apm して見てるとなぜかUsername が空白で処理されている。
PCの場合はOn-Demand Cert Authが始めでも大丈夫。

まあログインできればどっちでもいいんだけど、
On-Demand Cert Authを一番初めにもってくる利点としては
1. Logon Pageの前にVariable Assignを持ってきて

session.logon.last.username = expr { "[lindex [split [lindex [split [mcget {session.ssl.cert.subject}] ,] 0] =] 1]" }

などとすれば、証明書からusernameを自動入力させられる。
かつLogon PageでusernameをReadonly yes にしておけば変更もできなくなる。


補足
正確に言うとLogon Page をOn-Demand Certの前に持ってきたとしても、
On-Demand Certの直後にvariable assignをつかって
↑のsession.logon.last.username を証明書から読み取れるので
Logon Pageでusername はnoneにしてても良い。


2. 証明書がインストールされていない時点でtlsの接続を拒否するので、
ログインページすら表示させないでよくなる。

もちろんOn-Demand Cert Authが後ろの場合でも証明書を持ってなければ
ログインできないからそない気にしなくても良いけど。

ログ

big-ipのlocalには/var/log/apm で出力される。syslog-ngの設定覗き見したところ、facilityはlocal1みたいなので、
外部のsyslog serverでfilterしたい場合はlocal1 だけをapm.log で出力しとけばいい。