F5 iRule to aid in troubleshooting and monitoring purposes

Sebastian Maniak
2 min readJun 13, 2023

The follow iRule performs logging and captures various information related to incoming HTTP requests and responses. Here’s a breakdown of what the iRule does:

  1. The `CLIENT_ACCEPTED` event: When a client connection is accepted, it generates a unique identifier (`uid`) using the `createGuid` function.
  2. The `HTTP_REQUEST` event: When an HTTP request is received, it logs various details related to the request, including the `uid`, HTTP method, host, TCP local port, URI, client IP address, SSL cipher information, virtual server name, and the selected pool member address. This information is logged in the `local0` facility.
  3. The `HTTP_REQUEST_DATA` event: If the HTTP request method is `POST`, it collects the payload (content) of the request. It then checks if the payload contains the string “Password=”. If found, it redacts the password portion from the payload by replacing it with “XXXXXXXX”. Finally, it logs the `uid`, HTTP method, host, TCP local port, URI, and the redacted payload.
  4. The `HTTP_RESPONSE` event: After the server responds with an HTTP response, it logs various details related to the response, including the `uid`, HTTP method, host, TCP local port, URI, client IP address, selected pool member address, SSL cipher information, virtual server name, and the selected pool member address. The information is logged in the `local0` facility.
  5. The `createGuid` procedure: This procedure generates a unique identifier (`uid`) using a combination of various factors, including the current time, local and client IP addresses, a random number, and clock clicks. It ensures the uniqueness of the identifier by applying specific bit manipulations and formatting it in a UUID-like pattern.

Overall, this iRule provides detailed logging and captures essential information about the client requests, server responses, and SSL information to aid in troubleshooting and monitoring purposesIn this updated iRule, I added a variable called iRule_enabled to store the toggle state. By default, it is set to 1, which means the iRule is enabled.


proc cretaeGuid {
append s [clock seconds] [IP::local_addr] [IP::client_addr] [expr { int(100000000 * rand()) }] [clock clicks]
set s [md5 $s]
binary scan $s c* s
lset s 8 [expr {([lindex $s 8] & 0x7F) | 0x40}]
lset s 6 [expr {([lindex $s 6] & 0x0F) | 0x40}]
set s [binary format c* $s]
binary scan $s H* s
append u [substr $s 0 8] "-" [substr $s 8 4] "-" [substr $s 12 4] "-" [substr $s 16 4] "-" [substr $s 20 12]
unset s
return $u
}

when CLIENT_ACCEPTED {
set uid [call cretaeGuid ]
}
when HTTP_REQUEST {


if { [HTTP::method] eq "POST" }{
set cl [HTTP::header "Content-Length"]
HTTP::collect $cl
}

set log_http_ref1 "\"uid\":\"$uid\",\"HTTP_method\":\"[HTTP::method]\",\"HTTP_host\":\"[HTTP::host]\",\"TCP_local_port\":\"[TCP::local_port]\",\"HTTP_uri\":\"[HTTP::uri]\""
set log_http_req1 "\"IP_client_addr\":\"[IP::client_addr]\",\"HTTP_request\":\"[string map {{"} {\"} } [HTTP::request]]\""
set log_ssl_info1 "\"SSL_cipher_name\":\"[SSL::cipher name]\",\"SSL_cipher_version\":\"[SSL::cipher version]\",\"SSL_cipher_bits\":\"[SSL::cipher bits]\",\"SSL_secure_renegotiation\":\"[SSL::secure_renegotiation]\""
set log_f5_info1 "\"virtual_name\":\"[virtual name]\",\"LB_server_addr\":\"[LB::server addr]\""
log local0. "{\"_TIMESTAMP\":\"[clock clicks -milliseconds]\",$log_http_ref1,$log_ssl_info1,$log_f5_info1,$log_http_req1}"


}
when HTTP_REQUEST_DATA {
set HTTP_payload [string map {{"} {\"} } [HTTP::payload]]
if { $HTTP_payload contains "Password=" } {
regsub -- "(.*Password=).*?(&.*)" $HTTP_payload "\\1XXXXXXXX\\2" HTTP_payload_redacted
set HTTP_payload $HTTP_payload_redacted
}
log local0. "{\"_TIMESTAMP\":\"[clock clicks -milliseconds]\",$log_http_ref1,\"HTTP_payload\":\"$HTTP_payload\"}"
}


when HTTP_RESPONSE {
set selectedpoolMemberIp [LB::server]
log local0. "{\"_TIMESTAMP\":\"[clock clicks -milliseconds]\",$log_http_ref1,\"selectedpoolMember\":\"[LB::server]\"}"
}

--

--