はじめに:
今月は、Virtual Server(またはVirtual IP)でTCPコネクション数(同時接続)を制限した時、コネクションリミットを超えた場合の、BIG-IP LTMの挙動を改善するiRuleを紹介します。

LTMではVirtual Serverの最大TCPコネクション数(同時接続)が異なりますが、その管理者がコネクション数を制限することが可能です。
そこで、セキュリティ向上のためVirtual Serverの同時接続数に制限(リミット)をかけるLTM管理者は少なくありません。
設定した接続数を超えるとVirtual Serverが新規コネクションを受けずにクライアントにリセットを返します。
その場合、ユーザにとってそのサイトへのアクセスが遅くなったり、エラーメッセージが表示されることがよくあります。
その状況が発生しないように、このiRuleでコネクションリミットの機能と、リミットを超えた場合あらかじめ設されたstatic HTMLのレスポンス/ページを返すことが可能です。

以下でも詳細をご確認いただけます。
http://devcentral.f5.com/wiki/default.aspx/iRules/virtual_server_connection_limit_with_HTTP_response.html

タイトル:
Virtual Server同時接続数の制限を超えるとStatic HTTP RESPONSEを返すiRule

メリット:
コネクションリミットを超えた場合 404エラーメッセージを表示せずユーザを"sorry page"に誘導することで、
再接続要求によるアクセス遅延を防ぐ

機能解説:
このiRuleはグローバル変数によってアクティブ接続をカウントしており、カウントが0から始まる前提で書かれています。
Virtual Serverにアクティブ接続がない時に、カウンターが0からスタートされるようにiRuleを設定することを推奨します。

when RULE_INIT のイベントではグローバル変数に最大コネクション数を代入し、そのコネクションリミットを超えると
クライアントに返されるstatic HTML レスポンス/ページを定義します。
グローバル変数=max_connections

また、ここでアクティブ接続のカウンター変数を0に初期化します。
カウンター変数=active_connections

when HTTP_REQUESTのイベントでは最大コネクション数条件を定義し、新規コネクションがきた場合、カウンターを増加させます。

when CLIENT_CLOSEDのイベントでは既存のコネクション(アクティブコネクション)がクローズされた場合、カウンターを減少させます。

【iRule定義】

when RULE_INIT {

   # Set a global max for number of concurrent TCP connections
   set ::max_connections 2

   # Set an HTML response to sent to clients who make a request while the VIP is over the max connection count
   set ::html_content "<html>over limit</html>"

   # Print debug messages to /var/log/ltm?  1=yes, 0=no
   set ::debug 1

   # Initialize a counter for active connections (don't modify this)
   set ::active_connections 0
}
when HTTP_REQUEST {

   # If we're over the limit for this connection, send a response
   if {$::active_connections >= $::max_connections}{

      # Send a response
      HTTP::respond 200 content $::html_content

      # Close the connection
      TCP::close

      # Log a message to /var/log/ltm if debug is enabled
      if {$::debug}{log local0. "Over limit (current/max: $::active_connections/$::max_connections). Sent response to [IP::client_addr]"}

   # We're not over the limit, so check if this is the first HTTP request on the TCP connection. 
   } elseif {[HTTP::request_num] == 1}{

      # Increment the TCP connection count.
      incr ::active_connections 1
   }
}

when CLIENT_CLOSED {
   # A connection was closed, so decrement the global counter
   incr ::active_connections -1
}

※F5ネットワークスジャパンでは、サンプルコードについて検証を実施していますが、お客様の使用環境における動作を保証するものではありません。実際の使用にあたっては、必ず事前にテストを実施することを推奨します。