XFF Header Persistence iRule

Problem this snippet solves:

Identifies XFF headers and allows the selection of which header the iRule should persist on; assuming consistent ordering of multiple XFF headers. The iRule will work for single XFF headers as well, simply select 0 for the index.

How to use this snippet:

Instructions

  1. Fill in the Contributed by, Description, and iRule Source fields below.
  2. Select "SAMPLECODE" and other approprate categories.
  3. Add a meta description
  4. Include relevant iRule commands,events,etc used in this iRule.
  5. Delete this section.
  6. Click Save.

This iRule requires LTM v10. or higher. Contributed by: saltman

Code :

when HTTP_REQUEST {
     # iRule:         XFF Persistence iRule
     # Function:      Parse X-Forwarded-For header information and generate persistence records based on the selected header value
     #
     # Configuration Parameters: 
     #    xff_debug - set to 1 to enable debug logging, set to 0 to disable logging
     #    xff_header_index - select which XFF header to use in the list; 0 is the first element in the list
     #    persistence_timeout - select the duration of the persistence record in seconds    

     set xff_debug 1
     set xff_header_index 0
     set persistence_timeout 900
     set xff ''

     # Log the value for all XFF header(s)
     if {$xff_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::method] to [HTTP::host][HTTP::uri], xff: [HTTP::header values X-Forwarded-For]"}

     if {[HTTP::header values X-Forwarded-For] ne ""}  {
           # Convert the XFF headers to a list; single items will be index 0
           set xff_list [split [HTTP::header values X-Forwarded-For] ,] 

           # Display the list elements
           for {set x 0} {$x< [llength $xff_list]} {incr x} {
                if {$xff_debug}{log local0. "XFF List Elements: Item $x [lindex $xff_list $x]"}
           }

           # Assign the preferred XFF element
           # Check to make sure the preferred index is available in the list
           if {$xff_header_index > [llength $xff_list]}{log local0. "ERROR: Preferred XFF header index is not present!"}
           
           set xff [lindex $xff_list $xff_header_index]
           if {$xff_debug}{log local0. "Preferred XFF Header Index is $xff_header_index with value of $xff"}
     
           # Log preferred XFF and show current record if one exists
           if {$xff_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Persisting on preferred XFF: $xff, existing record? [persist lookup uie $xff]"}

           # Set a persistence entry based on the preferred XFF
           persist uie $xff $persistence_timeout
     }    else {
           # No XFF header found in the payload
           if {$xff_debug}{log local0. "No XFF Header detected"}
     }
}

when SERVER_CONNECTED {
     # Log connection to identified server; show client and persistence record
     if {$xff_debug && $xff ne ""}{log local0. "[IP::client_addr]:[TCP::client_port]: Persistence record: [persist lookup uie $xff]"}
}
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment