Persistence on HTTP Response only (also DDoS and off-loading assistence)

Problem this snippet solves:

Working with web traffic I see a common issue with persistence iRules, the following is common iRule:

when HTTP_RESPONSE {
  if { [HTTP::cookie exists "JSESSIONID"] } {
    persist add uie [HTTP::cookie "JSESSIONID"]
  }
}
when HTTP_REQUEST {
  if { [HTTP::cookie exists "JSESSIONID"] } {
    persist uie [HTTP::cookie "JSESSIONID"]
  }
}

The problem with this is we only really want to add persistence records for valid traffic where this allows any HTTP Request with a JSESSIONID cookie to create a peristence record.

Think about this, if I had 1000 clients which I got to make HTTP Requests all with the same JSESSIONID cookie value then the first would create a persistence record on the F5 then the other 999 requests would all go to the same backend web server even if the JSESSIONID value is not valid on the applicaiton. Also we could end up with many more peristence enties as client request with invalid JSESSIONID values will still create enties.

This all leads to a possible DoS style attacks but a simple change can prevent.

The following iRule does a simple lookup first before using any persistence record in a HTTP Request, if the lookup fails but a JSESSIONID value exists then we can remove the JSESSIONID cookie from the request.

This second part is optional but can also be used to only send valid traffic to a back end web server.

How would we do that? We could have a list (or data group) of valid HTTP paths we accept without a valid JSESSIONID cookie (valid being in the request and has a valid persistence record) if not redirect uses to a login page or home page or some other valid location. This allows us to use persistence records as a way to apply validation to HTTP Requests and block/redirect invalid ones.

How to use this snippet:

HTTP Response is standard checking for a value, in this case the JSESSIONID cookie, and adds a persistence record. Should be applied as part of a persistence profile so you can control timeout and Match Across Virtual Server/Service/Pool outside of the iRule

when HTTP_RESPONSE {
    if { [HTTP::cookie exists "JSESSIONID"] } {
        persist add uie [HTTP::cookie "JSESSIONID"]
    }
}

The Request part does a validation check first preventing persistence records being added and only used in a Reqeust and even removing the JSESSIONID cookie from the request. See the description above about using this to provide even great blocking of invalid requests.

when HTTP_REQUEST {
    if {[HTTP::cookie "JSESSIONID"] ne "" and [persist lookup uie [HTTP::cookie "JSESSIONID"]] ne ""} {
        persist add uie [HTTP::cookie "JSESSIONID"]
    } elseif {[HTTP::cookie "JSESSIONID"] ne ""} {
        HTTP::cookie remove "JSESSIONID"
    }
}

Code :

when HTTP_RESPONSE {
    if { [HTTP::cookie exists "JSESSIONID"] } {
        persist add uie [HTTP::cookie "JSESSIONID"]
    }
}
when HTTP_REQUEST {
    if {[HTTP::cookie "JSESSIONID"] ne "" and [persist lookup uie [HTTP::cookie "JSESSIONID"]] ne ""} {
        persist add uie [HTTP::cookie "JSESSIONID"]
    } elseif {[HTTP::cookie "JSESSIONID"] ne ""} {
        HTTP::cookie remove "JSESSIONID"
    }
}
Updated Jun 06, 2023
Version 2.0
No CommentsBe the first to comment