Forum Discussion

tatmotiv's avatar
tatmotiv
Icon for Cirrostratus rankCirrostratus
Jul 03, 2018

Modify HTTP response from ICAP server on BigIP

Hi all,

 

I'm facing the following problem with an ICAP setup: What we want is AV scanning of file uploads to a web page using ICAP on the BigIP. This is done by using a request adapt profile in conjunction with an internal virtual with ICAP profile. We want all POST requests to a specific upload path to be sent to an ICAP server that performs AV scanning. When finding an infected upload, the ICAP server will respond with an ICAP result "respond" (instead of "modify") and return an http 403 error page (we cannot change that behaviour). The upload (POST request) will not reach the webserver in that case. Up to that point, we could get all of this working properly.

 

Unfortunately, the client application (third party product) will throw an unexpected and undefined error upon receiving an http 403 status code. In order to display a meaningful error message to the end user, the application expects an http status code 901 instead. As already mentioned, we can neither change the http 403 error returned by the ICAP server (third party product), nor the need/expectation for an http 901 status by the web application (also third party product). Hence, we plan to rewrite the http 403 reply (of the ICAP server) into an http 901 status on the bigip, resulting in the following setup: click here

 

I tried to address this issue with the following iRule:

 

   when HTTP_REQUEST {
      if { [HTTP::uri] starts_with "/some/path/to/file/uploads" } {
         log local0. "Upload detected - activating ICAP"
         ADAPT::enable request true
         set icap_enabled 1
         set icap_respond 0
      } else {
         ADAPT::enable request false
         set icap_enabled 0
         set icap_respond 0
      }
   }

   when ADAPT_REQUEST_RESULT {
      set result [ADAPT::result]
      log local0. "ICAP RESULT received. Result: $result"
      if { $result == "respond" } {
         set icap_respond 1
         log local0. "ICAP MATCH respond"
      }
   }

   when HTTP_RESPONSE {
      if { $icap_enabled == 1 } {
         if { $icap_respond == 1 } {
            HTTP::respond 901
            log local0. "Upload ICAP response detected - sending http 901 to client."
         }
      }
   }

Unfortunately, this does not work, since the HTTP_RESPONSE event will not be triggered by the ICAP response, because it is not coming from a server as the wiki page states:

 

HTTP_RESPONSE is specific to a server response passing through the load balancer, and is not triggered for locally-generated responses

 

HTTP_RESPONSE_RELEASE is also not a suitable event, because it does not allow HTTP::respond actions.

 

Trying to do the HTTP::respond action within the ADAPT_REQUEST_RESULT event block will result in TCL errors during execution and break down the whole virtual.

 

Does anybody have ideas on how to address this issue properly? I'm running out of ideas.

 

Many thanks in advance!

 

Martin

 

2 Replies

  • Since nobody else seems willingly to answer me, I'll provide the answer myself ;-)

     

    Short version: it currently works flawlessly when using HTTP_RESPONSE_RELEASE as event in the last part of the iRule.

     

    Long version: I have doubts whether this can be deployed in production or not, because according to the official iRule API documentation, HTTP::respond is disallowed under an HTTP_RESPONSE_RELEASE event. That's also the reason why I haven't even tried this at first, although it came to my mind before. The big question now is: is there any guarantee that this will continue to work, let's say for example after an upgrade from (currently) 12.1.3 to 13.x or maybe someday 14.x? I'm trying to get an official statement from f5 concerning this.

     

    • Nikoolayy1's avatar
      Nikoolayy1
      Icon for MVP rankMVP

      As I used your post for ideas I know that 4 years have passed but  with ASM/Advanced WAF this can be done  under "ASM_REQUEST_BLOCKING" event as shown in the below link:

      https://clouddocs.f5.com/api/irules/ASM_REQUEST_BLOCKING.html

       

      You can trigger a custom ASM violation based the ADAPT result to then match and trigger the ASM event.

       

      Or to bypass the ADAPT_REQUEST_RESULT but better to trigger HTTP response before contacting te backend server and uploading a malware for example. Maybe at "HTTP_REQUEST_SEND" event as it seems valid but I will have to test this https://clouddocs.f5.com/api/irules/HTTP__respond.html .

       

      	when ADAPT_REQUEST_RESULT {
      	    if {[ADAPT::result] == "respond"} {
      		 # Force ADAPT to ignore any direct response from IVS
      		 # (contrived example, probably not useful as-is).
      		 ADAPT::result bypass
      	    }
      	}