Technical Article Attributeを見てRADIUSサーバの負荷分散を行うiRule はじめに: RADIUSは大変成熟したプロトコルで、AAAすなわちAuthentication(認証)、 Authorization(承 認)、Accounting(アカウンティング)のために広く利用されています。 RADIUSは比較的シンプルなトランザクション型のプロトコルです。RASサーバ、FirePass、BIG IPのようなクライアントがRADIUSリクエスト(例えばユーザ名+パスワードによる認証など)を出し RADIUSサーバからの応答を待ちます。 RADIUSクライアントとサーバ間の情報は属性(attribute)の形でやりとりされます。ユーザ名、ユー ザパスワード、IPアドレス、ポート、セッション状態等は全て属性の一種です。属性は、テキスト、 文字列、IPアドレス、整数、タイムスタンプのデータ型を採ることができます。可変長の属性もあれ ば、固定長のものもあります。 ■ RADIUSプロトコルに特化したサポートをすることの利点 特定のプロトコルに特化しないUDP一般のロードバランシングには共通の課題があります。クライ アントがいつも同じソースポートからリクエストを送ってきた場合、複数のサーバにパケットを分散す ることができないのです。この挙動はUDPプロファイルのデフォルトの動作となります。 このような状況で負荷分散を可能にするには、一般的には「データグラム・ロードバランシング」を 行うか、即時にセッションタイムアウトを行う事が推奨されます。データグラム・ロードバランシングを 行えば確かに個々のパケットは分散されますが、あるリクエストに対するサーバからの応答が返る 前に新規のリクエストが入って来ると、設定によってはBIGIPは新規のリスエストのソースポートを 書き換えてからサーバに転送します。この結果アプリケーションがきちんと動かない場合に は”immediate timeout”を設定することになります。あわせて、サーバからクライアントへの戻りのト ラフィックを通すためのバーチャルサーバを追加する必要も生じるでしょう。 同一のIPアドレス/ポートから送られてくるRADIUSのトラフィックを負荷分散するには、データグラ ム・ロードバランシングまたはimmediate timeoutを用いればほぼ問題ありません。しかし、もしトラ ンザクションあたり2パケット (リクエストに1パケット、応答に1パケット) より多いやり取りがある場 合、BIGIP LTMの更なる機能が必要となります。 該当するケースとしてRADIUSのチャレンジ/レスポンスによるハンドシェイクが挙げられます。下記の ように4パケットがやりとりされます。 * Client アクセス要求 > Server * Client < アクセスチャレンジ Server * Client アクセス要求> Server * Client < アクセス許可 Server この処理が成功するには、ひとつのトランザクションに属するパケットが全て同じサーバに振り分けら れる必要があります。そのためには、カスタマイズされたL7パーシステンスが必要となります。 iRuleがそれを実現します。RADIUSプロトコルを理解できるiRuleを用いることで、BIGIP LTMは クライアントから送られた属性に基づいて振り分け先のサーバを選定することができ、また、クライア ント/サーバ双方いずれから送られた属性に基づいてセッションをパーシストすることができます。セッ ション管理をBIGIPにオフロードできますので、サーバ側の設定をよりシンプルにできます。iRuleに よりmd5の再計算、ユーザ名の変更レルムの検出等々を行う事ができますので、BIGIPは更に ichiro クライアントから送られた属性に基づいて振り分け先のサーバを選定することができ、また、クライア ント/サーバ双方いずれから送られた属性に基づいてセッションをパーシストすることができます。セッ ション管理をBIGIPにオフロードできますので、サーバ側の設定をよりシンプルにできます。iRuleに よりmd5の再計算、ユーザ名の変更レルムの検出等々を行う事ができますので、BIGIPは更に 高度な処理を行うこともできます。BIGIP LTMはまた、RADIUSプロトコルにアプリケーションレベ ルでのセキュリティを追加することも可能です。改変されたトラフィックのrejectや、DoS攻撃などへ の対策をiRuleにて行えます。 ■ ソリューション クライアントからのリクエストが常に同じIPアドレス/ポートから行われる場合は、データグラム・ロード バランシングまたはimmediate timeoutを用いれば、たいていは事足ります。 immediate timeoutを使用する場合、サーバからクライアントへのパケットを転送するために追加の バーチャルサーバおよび適切なSNAT(VIPと同じIPでクライアントに返すための)を設定します。 属性をもってUIE(Universal Inspection Engine)パーシステンスを行います。 immediate timeoutとクライアント/サーバそれぞれのために2つのバーチャルサーバを作成する場合 は、セッションコマンドに"any"オプションを付けます。 タイトル: Attributeを見てRADIUSサーバの負荷分散を行うiRule メリット: RADIUSサーバの負荷分散を行えるようになり、 システム全体として処理能力をあげられる サービスを止めずに個々のRADIUSサーバのメンテナンスができる レイヤ7でRADIUSの属性やレルムを見て転送先のRADIUSサーバを選択することができる 設定概要: CLIENT_ACCEPTEDおよびSERVER_DATAイベントにてUDPパケットのペイロードをbinary scanし、RADIUS attributeとその値を抽出します。 【iRule定 義 】 1. 下記のサンプルiRuleはデコードおよび属性情報のロギングのみを行います。iRuleを用いて RADIUSをどのように取り扱えるかをつかむための良いサンプルです。特定の値を抽出して利用す るので、目的により様々な用途に用いることができます。例えば、特定の属性やレルムの値を取 得し振り分け先サーバの選定に用いる等です。 when RULE_INIT { array set ::attr_code2name { 1 User-Name 2 User-Password 3 CHAP-Password 4 NAS-IP-Address 5 NAS-Port 6 Service-Type 7 Framed-Protocol 8 Framed-IP-Address 9 Framed-IP-Netmask 10 Framed-Routing 11 Filter-Id 12 Framed-MTU 13 Framed-Compression 14 Login-IP-Host 15 Login-Service 16 Login-TCP-Port 13 Framed-Compression 14 Login-IP-Host 15 Login-Service 16 Login-TCP-Port 17 (unassigned) 18 Reply-Message 19 Callback-Number 20 Callback-Id 21 (unassigned) 22 Framed-Route 23 Framed-IPX-Network 24 State 25 Class 26 Vendor-Specific 27 Session-Timeout 28 Idle-Timeout 29 Termination-Action 30 Called-Station-Id 31 Calling-Station-Id 32 NAS-Identifier 33 Proxy-State 34 Login-LAT-Service 35 Login-LAT-Node 36 Login-LAT-Group 37 Framed-AppleTalk-Link 38 Framed-AppleTalk-Network 39 Framed-AppleTalk-Zone 60 CHAP-Challenge 61 NAS-Port-Type 62 Port-Limit 63 Login-LAT-Port } } when CLIENT_ACCEPTED { binary scan [UDP::payload] cH2SH32cc code ident len auth \ attr_code1 attr_len1 log local0. "code = $code" log local0. "ident = $ident" log local0. "len = $len" log local0. "auth = $auth" set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] switch $attr_code1 { 11 1 { binary scan [UDP::payload] @${index}a[expr $attr_len1 - 2]cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } 9 8 4 { binary scan [UDP::payload] @${index}a4cc rawip \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) =\ [IP::addr $rawip mask 255.255.255.255]" } binary scan [UDP::payload] @${index}a4cc rawip \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) =\ [IP::addr $rawip mask 255.255.255.255]" } 13 12 10 7 6 5 { binary scan [UDP::payload] @${index}Icc attr_value \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } default { binary scan [UDP::payload] @${index}H${hsize}cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } when SERVER_DATA { binary scan [UDP::payload] cH2SH32cc code ident len auth \ attr_code1 attr_len1 log local0. "code = $code" log local0. "ident = $ident" log local0. "len = $len" log local0. "auth = $auth" set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] switch $attr_code1 { 11 1 { binary scan [UDP::payload] @${index}a[expr $attr_len1 - 2]cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } 9 8 4 { binary scan [UDP::payload] @${index}a4cc rawip \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) =\ [IP::addr $rawip mask 255.255.255.255]" } 13 12 10 7 6 5 { binary scan [UDP::payload] @${index}Icc attr_value \ 7 6 5 { binary scan [UDP::payload] @${index}Icc attr_value \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } default { binary scan [UDP::payload] @${index}H${hsize}cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } 2. 次のiRuleはUDPデータグラム・ロードバランシングが2要素認証でも機能するようにします。この iRule中のパーシステンスは”State”属性(value=24)に基づいています。iRuleがどれほどプロトコル の内部まで掘り下げることができるかの好例です。 when CLIENT_ACCEPTED { binary scan [UDP::payload] ccSH32cc code ident len auth \ attr_code1 attr_len1 set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] binary scan [UDP::payload] @${index}H${hsize}cc attr_value \ attr_code2 attr_len2 # If it is State(24) attribute... if { $attr_code1 == 24 } { persist uie $attr_value 30 return } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } when SERVER_DATA { binary scan [UDP::payload] ccSH32cc code ident len auth \ attr_code1 attr_len1 # If it is Access-Challenge(11)... if { $code == 11 } { set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] binary scan [UDP::payload] @${index}H${hsize}cc attr_value \ attr_code2 attr_len2 if { $attr_code1 == 24 } { persist add uie $attr_value 30 return } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 return } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } } ※ F5ネットワークスジャパンでは、サンプルコードについて検証を実施していますが、お客様の使用環境における動作を保証 するものではありません。実際の使用にあたっては、必ず事前にテストを実施することを推奨します。 Document Created: 2014.6.23
© Copyright 2024 ExpyDoc