iRules: Insert client certificate into HTTP Header

This iRule should be used when the back end server requires to see the client certificate presented to a VIP where SSL is being terminated and client authentication is being enforced. This iRule will do the following:

  • Check for existing HTTP Headers such as X-Forwarded-For and ssl.client_cert and remove them
  • Grab the client certificate and strip out any spaces or new lines
  • Insert the trimmed down client certificate into the HTTP Header ssl.client_cert
  • Insert the HTTP Header X-Forwarded-For with the client IP address
when HTTP_REQUEST {
	if { [HTTP::header exists "X-Forwarded-For"]} {
		HTTP::header remove X-Forwarded-For
		}
	if { [HTTP::header exists "ssl.client_cert"]} {
		HTTP::header remove ssl.client_cert
		}
	if { [SSL::cert count] > 0 } {
		set thecert [findstr [X509::whole [SSL::cert 0]] "-----BEGIN CERTIFICATE-----" 28 "-----END CERTIFICATE-----"]
		set certnospace [string map -nocase {" " "" \n "" \r ""} $thecert] 						  		
		HTTP::header insert ssl.client_cert $certnospace
		HTTP::header insert X-Forwarded-For [IP::client_addr]
	}
}

You may download a text version of the iRule here.

Regards,

BD

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