To logically negate something you need a binary value. If you don't use parentheses to enforce the precedence. the first thing that is evaluated is logically:
not [HTTP::header values "X-Forwarded-For"]
If there was valid output from that evaluation, it would then be compared against the "X.X.X.X" string.
Here is an example of using parentheses to fix this:
when HTTP_REQUEST {
if { not ([HTTP::header values "X-Forwarded-For"] contains "X.X.X.X" or [HTTP::header values "X-Forwarded-For"] contains "X.X.X.X")}{
HTTP::respond 200 content "Apology Page - External BlockedWe are sorry, but the site you are looking for is temporarily out of service Please try again later ."
}
}
Or you could use a switch statement:
when HTTP_REQUEST {
switch -glob [HTTP::header values "X-Forwarded-For"] {
"*1.1.1.1*" -
"*2.2.2.2*" {
Do nothing
}
default {
Send the block page content
HTTP::respond 200 content "Apology Page - External BlockedWe are sorry, but the site you are looking for is temporarily out of service Please try again later ."
}
}
}
But if you're depending on an HTTP header for security information, you should ideally have the firewall strip out any existing instances of the header value before inserting its own version. This ensures that a client can't inject its own X-Forwarded-For header in requests to bypass the iRule logic. If the upstream firewall doesn't provide the option to remove existing XFF headers, you might try to use a more unique header name. This would be security through obscurity which is never ideal; but at least it's a bit better than just using XFF without removing prior instances.
Aaron