iRules: IP Reputation based on X-Forwarded-For HTTP Header

Recently I had a customer that wanted to use the IP Reputation Database on the F5 WAF however the client IP address was being proxied by an upstream device. Luckily for us, the client IP address was being sent in the X-Forwaded-For HTTP Header and we were able to hone in on that information and apply the IP Reputation logic via iRules.

The example below allows you to extract the client IP address from the X-Forwarded-For HTTP Header, check the IP Reputation Database, and either silently drop the traffic or respond with HTTP content.

when HTTP_REQUEST {
    # LOGGING OFF=0, LOGGING ON=1
    set DEBUG_LEVEL 1
    # SLIENT DROP BAD TRAFFIC=0, FRIENDLY DROP BAD TRAFFIC=1
    set BAD_ACTOR 1
    # Make sure XFF is present and the IP matches IPI
    if { ([HTTP::header exists "X-Forwarded-For"]) and not ( [IP::reputation [HTTP::header values "X-Forwarded-For"]] =="") } {
        set ip_reputation_categories [IP::reputation [HTTP::header values "X-Forwarded-For"]]
        set is_reject 0
        switch -glob $ip_reputation_categories {
            *Spam* { set is_reject 1  }
            *Proxy* { set is_reject 1 }
            *Denial* { set is_reject 1 }
            *Attacks* { set is_reject 1 }
            *Botnets* { set is_reject 1 }
            *Scanners* { set is_reject 1 }
            *Exploits* { set is_reject 1 }

        }
        if { ($is_reject)} {
            if { $BAD_ACTOR == "1"}{
                if { $DEBUG_LEVEL == 1} { log local0. "XFF:[HTTP::header values "X-Forwarded-For"] matched IPI Category:$ip_reputation_categories and was rejected with a page."}
                HTTP::respond 403 content "
                <HTML>
                <HEAD>
                <TITLE>Rejected Request</TITLE>
                </HEAD>
                <BODY>The request was rejected. <BR>Attempted access from malicious IP address</BODY>
                </HTML>"
                return
            }
            if { $BAD_ACTOR == "0"} {
                if { $DEBUG_LEVEL == 1} { log local0. "XFF:[HTTP::header values "X-Forwarded-For"] matched IPI Category:$ip_reputation_categories and was sliently dropped."}
                drop
                return
                }
            }
        }
        if { [HTTP::header exists "X-Forwarded-For"] } {
            if { $DEBUG_LEVEL == 1} {log local0. "XFF:[HTTP::header values "X-Forwarded-For"] and did not match any categories"}
            return
        }
    if { $DEBUG_LEVEL == 1} {log local0. "No XFF Sent and nothing was dropped"} 
}

You may also download a txt version of the iRule here.

Note: You can replace X-Forwarded-For to any HTTP Header that contains the client IP address, e.g, true-client-ip.

Regards,

BD