Forum Discussion

dragonflymr's avatar
dragonflymr
Icon for Cirrostratus rankCirrostratus
Nov 20, 2015

iRule to store cookie in table

Hi,

 

I am really iRule novice and so any advice, pointing in right direction will be of great help for me. I am short on time and have to create iRule with following logic:

 

  • Service behind F5 is doing kind of authentication
  • If user succeed cookie is created
  • iRule should monitor HTTP_RESPONSE for presence of this cookie for specific URI
  • When detected in Set-Cookie header entry in session table should be created (with set lifetime like 2400s - counter updates should not extend lifetime of this entry) storing cookie value
  • HTTP_REQUEST should be monitored for presence of above cookie
  • When detected lookup in table should be performed (using cookie value?)
  • If found:
    • Entry should be checked if it is first occurrence of given cookie value (so this value is detected for first time)
      • If yes - values from few headers should be added - like User-Agent, first IP from X-Forwarded-For (the one that should be real user IP that initiated connection from Internet), maybe some more, counter should be set to 1
      • If not just counter should be incremented
  • If not found lookup in separate subtable (like false_cookie, indefinite lifetime) should be performed
    • If entry found counter should be incremented
    • If not found new entry should be created using cookie value as a key?
    • Connection should be dropped. Optionally sorry page displayed

Well, that is my idea but maybe I am missing something or there is better way. Main goal is to drop all HTTP request (POST operation using specific URI) that do not contain valid cookie. Plus collecting stats about how many illegitimate attempts to perform POST to this UIR were issued.

 

Hope it makes sense, will appreciate a lot any help,

 

Piotr

 

  • I would suggest using APM for this rather than an LTM iRule. APM should be able to provide all of your request out of the box.

     

  • Hi,

     

    Unfortunately APM is not an option right now. Maybe in the future but time frame is to tight :-(

     

    I started some work but it's going quite slow :-(

     

    Piotr

     

  • The part about your proposed rule that may be challenging is all the additional info you want to store in the table. What will you do with that info? If you don't plan on using it or logging it, its really a waste of memory space. Also, remember the table command is just a hash table(key value pair) so saving all that additional info about the user won't be in the same record that you want to increment. I would suggest the storage of all the info be done with High Speed Logging off box and just use the logic of deciding if a users has the required cookie to hit the URI to block connections. That may help much more with historical research while at the same time lessening the memory and CPU load of the iRule.

     

  • You can try with this irule (not tested) to begin...

    when HTTP_REQUEST {
        switch [HTTP::path] {
            "/img/logo.png" -
            "every-file-used-in-auth-page" -
            "/login.php" {
                return
            }
            default {
                if {([HTTP::cookie exists "mycookie"]) && ([table lookup -subtable "authent" [HTTP::cookie value mycookie]] != "")} {
                    return
                } else {reject}
            }
        }
    }
    
    when HTTP_RESPONSE {
      if { [HTTP::cookie exists "mycookie"] } { table add -subtable "authent" [HTTP::cookie value mycookie] "logged" indef 2400
     }
    }
    
  • Hi,

     

    Thanks a lot for help. Good point about difficulty of storing multiple values in table. Maybe if I explain issue better you can advice some better solution.

     

    Authentication cookie is set by another system than session cookie. I need to find efficient way to glue together such values:

     

    User-Agent X-Forwarded-For (real client IP should be extracted in case there were few intermediary proxies on the path to BIG-IP) ASP.NET_SessionId

     

    So in the end when specific URI will be requested (or optionally when POST to specific URI will be performed) it can be easy to verify if for given authentication cookie all above variables are identical as the ones when authentication cookie was send.

     

    So when request to authentication URI is issued by new client I am collecting: User-Agent X-Forwarded-For ASP.NET_SessionId (already set during previous requests by application server)

     

    Then when response after successful authentication is send with Set-Cookie setting my auth cookie it's recorded along mentioned variables.

     

    Then when request to URI that can only be accessed by request with valid auth cookie arrives I can easily lookup if auth cookie and all mentioned varaibles are identical as at the time when auth cookie was issued.

     

    I suspect that it can be done creating key that is composed from all those elements (with no stored)?

     

    Or maybe it's better to use my auth cookie as key and store mentioned variables (as one string) in value

     

    Then I am doing lookup, if entry exist I am comparing request provided values with ones stored in value?

     

    Piotr

     

  • I found such iRule:

     Limit each client IP address to 20 concurrent connections
    
    when CLIENT_ACCEPTED {
     Check if the subtable has over 20 entries
        if { [table keys -subtable connlimit:[IP::client_addr] -count] >= 20 } {
            reject
        } else {
             Add the client IP:port to the client IP-specific subtable 
             with a max lifetime of 180 seconds
            table set -subtable connlimit:[IP::client_addr] [TCP::client_port] "" 180
        }
    }
    
    when CLIENT_CLOSED {
         When the client connection is closed, remove the table entry
        table delete -subtable connlimit:[IP::client_addr] [TCP::client_port]
    }
    

    What I don't get is

    [table keys -subtable connlimit:[IP::client_addr] -count] >= 20

    and

    table set -subtable connlimit:[IP::client_addr] [TCP::client_port] "" 180

    Counting seems to be performed on subtable named connlimit:[IP::client_addr] but adding keys is performed on subtable that seems to be named connlimit:[IP::client_addr] [TCP::client_port].

    What's going on here?

    Piotr