Forum Discussion

Village_Idiot's avatar
Village_Idiot
Icon for Nimbostratus rankNimbostratus
Aug 09, 2021

Pool selection based on X-Forwarded-For header

We have moved our on-prem WAF out to a cloud solution and need to modify an iRule that is used to do pool selection based on client IP. Private IP's directed to an internal pool and public IP's direc...
  • spalande's avatar
    Aug 10, 2021

    Hi, if WAF is adding XFF header, shouldn't that contain original IP of client and it can be anything in the world if site is public? Not sure, why you want to read XFF header instead of IP from WAF itself?

    since your current iRule is checking for client IP from the internal network (private_net) to send to internal pool and everything else is being sent to the external pool, you won't need any modification. It would anyway send the traffic from external WAF to the external pool. You can apply whitelist on the FW to only accept the traffic from WAF IP addresses.

    But still you are looking for sending traffic based on XFF header, you can use something like below.

    when HTTP_REQUEST {
       if { [HTTP::header exists X-Forwarded-For] } {
       set xff [HTTP::header X-Forwarded-For]
       return
       }
      set fqdn_name [HTTP::host]
    	if { [class match [HTTP::host] equals DomainsToRedirect] } {
    		HTTP::redirect  "http://$fqdn_name"
        } elseif { [HTTP::uri] starts_with  "/someuri" } {
        if { [lsearch {"CONNECT" "OPTIONS" "HEAD" "TRACE"} [HTTP::method]] > 0 } {
            reject
        } else {
    	  set xlateuri [string map {"/someuri" "/"} [HTTP::uri]]
    		HTTP::header replace HOST "host.domain.com"
    		HTTP::uri "$xlateuri"
    		if { [class match [IP::client_addr] equals private_net] } {
    			pool Prod-Internal-Pool
    		} elseif { ([info exists xff]) and ([class match $xff equals xff_net]) } { 
    			pool Prod-External-Pool
    		 } else {
    		   reject
    		 }	
    		}
    	} elseif { [lsearch {"CONNECT" "DELETE" "HEAD" "PUT" "TRACE"} [HTTP::method]] > 0 } {
    		reject
    	} elseif { [class match [IP::client_addr] equals private_net] }{
    		pool Web-Internal-Pool
    	}  elseif { ([info exists xff]) and ([class match $xff equals xff_net]) } { 
    	   pool Prod-External-Pool
    	 } else {
    		   reject
    		 }	
     }