F5 irule Extracting data from the HTTP post payload
In the realm of application delivery, iRules offer a powerful mechanism for customizing traffic management and shaping user experiences. Today, we'll explore a practical iRule that seamlessly extracts valuable information from HTTP POST payloads, like form fields,jason payload also extract IP from the HTTP header X-Forwarded-For
Description:
Below is the specific irule i wrote for a client where he needs to validate the client ip geo location and validate a parameter and its value in HTTP Post request body . The request is proxied via another Load balancer with X-Forwarded-For enabled.
Journey
Initially i started with the below irule to extract the parameter "transid" and its value from the HTTP Post payload.
when HTTP_REQUEST {if { [HTTP::method] eq "POST" } {# Get the POST payload dataset post_payload [HTTP::payload]foreach x [split [string tolower $post_payload] "&"] {if { $x starts_with "transid=" } {set transid [lindex [split $x "="] 1]}}log local0. "MY Transactin id number is $transid"}}
when HTTP_REQUEST {if { [HTTP::header exists "X-Forwarded-For"] } {set client_ip [HTTP::header value "X-Forwarded-For"]set fromCountry [whereis $client_ip country]if { ( [class match $fromCountry equals example_datagroup]) }{log local0. "Attacker IP in XFF [HTTP::header X-Forwarded-For] and from $fromCountry"}}}
Final irule
when HTTP_REQUEST {if { [HTTP::method] eq "POST" && [class match [HTTP::path] equals myurl-DG] } {if { [HTTP::header exists "X-Forwarded-For"] } {set client_ip [HTTP::header value "X-Forwarded-For"]set fromCountry [whereis $client_ip country]if { ![class match $fromCountry equals geo-DG] }{set post_payload [HTTP::payload]foreach x [split [string tolower $post_payload] "&"] {if { $x starts_with "tranid=" } {set tranid [lindex [split $x "="] 1]if { ![class match $mid equals tranvalue-DG] } {local0. "DROPPING Request from country $fromCountry with TransID value $tranid"drop}}}}}}}
Using HTTP collect
For some reason the above irule didnt work for some traffic so i used below irule
when HTTP_REQUEST {
set client_ip [IP::client_addr]
set country [whereis $client_ip country]
if { [HTTP::method] eq "POST" && [class match [HTTP::path] eq url_dg] && $country ne "IN" } {
HTTP::collect [HTTP::header Content-Length]
}
}
when HTTP_REQUEST_DATA {
set mid "unknown"
foreach x [split [string tolower [HTTP::payload]] "&"] {
if { $x starts_with "mid=" } {
set mid [lindex [split $x "="] 1]
if { ![class match $mid equals mid_value] } {
log local0. "DROPPING Request from country $country with MID value $mid"
drop
}
}
}
}
Consultion: