Forum Discussion

Darrell_Kesti_5's avatar
Darrell_Kesti_5
Historic F5 Account
Aug 27, 2008

Stream iRule

Hello. I am working on an iRule to solve a specific problem with a Sharepoint java script. Basically, I am doing SSL Client side termination on the Big-IP LTM 9.4.5 box. However, a few scripts located in the /_wpresources directory from the SharePoint servers are hard coding an http://intranet address when I need all of it to be an https://intranet address. Here is a way I think I can solve it by using a stream profile and replacing http:// with https://. The kicker is I only want to do this when I see a response from the /_wpresources directory.

 

 

Here is what I have....will this work?

 

 

when HTTP_RESPONSE {

 

 

Check if the URI contains the /_wpresources or equivalent. If it does replace http:// with https:// within the data stream.

 

 

if {[HTTP::header value uri] contains "_wpresources"}{

 

STREAM::expression "@http://@https://@"

 

STREAM::enable

 

}

 

 

Disable the stream filter by default. We are doing this as the steam profile is enabled within the http profile. It will be re-enabled if needed later.

 

STREAM::disable

 

}

 

 

Thanks.

7 Replies

  • Hello,

    The URI isn't available by default in server side events, so you'll have to check for it in the HTTP_REQUEST event. Can you give this a try?

      
      when HTTP_REQUEST {  
        
          Don't rewrite the response by default  
         set rewrite_response 0  
        
          Check if we want to rewrite the response based on the requested URI  
         if {[string tolower [HTTP::path]] contains "/_wpresources"}{  
            set rewrite_response 1  
         }  
      }  
      when HTTP_RESPONSE {  
        
          Disable the stream filter by default  
         STREAM::disable  
        
          Check if we're rewriting the response  
         if {$rewrite_response==1}{  
        
             Match any http:// instance and replace it with https://  
            STREAM::expression {@http://@https://@}  
           
             Enable the stream filter for this response only    
            STREAM::enable  
         }  
      }  
      

    I didn't add logging, but you can do so following the examples on the STREAM::expression wiki page (Click here).

    Aaron
  • Darrell_Kesti_5's avatar
    Darrell_Kesti_5
    Historic F5 Account
    Thanks Aaron,

     

     

    actually, I just found out that there are some scripts involved so you never see the directory in the http request. The biggest issue here is when we use the generic streaming profile we are modifying word documents, excel, power point, etc that has http:// in it and replacing it with https://. The issue is if anything sneaks through that are links and they are not properly set to https, our redirect iRule on port 80 seems to kill it. Here is my latest thought. Enable streaming everywhere, but check if the Content-Type of the HTTP Response is either word, excel, powerpoint. if it is disable it. Here is what I have...what do you think.

     

     

    when HTTP_RESPONSE {

     

     

    check if the response is a word file and disable streaming.

     

    if {[HTTP::header value Content-Type] contains "msword"}{

     

    STREAM::disable

     

    }

     

     

    check if the response is an excel file and disable streaming.

     

    if {[HTTP::header value Content-Type] contains "vnd.excel"}{

     

    STREAM::disable

     

    }

     

     

    check if the response is a powerpoint file and disable streaming.

     

    if {[HTTP::header value Content-Type] contains "ms-powerpoint"}{

     

    STREAM::disable

     

    }

     

     

    Otherwise stream if there is an expression match for http and replace it with https.

     

    STREAM::expression "@http://@https://@"

     

    STREAM::enable

     

    }

     

     

    when STREAM_MATCHED {

     

     

    This will log when the stream is matched. This should help with any future troubleshooting as well.

     

     

    log local0. "[IP::client_addr]:[TCP::local_port]: matched: [STREAM::match], replaced with: [string map {http:// https://} [STREAM::match]]"

     

    STREAM::replace "[string map {http:// https://} [STREAM::match]]"

     

    }
  • If you're only rewriting based on the content-type header value, you can look for the string "text" instead of enumerating every content-type you don't want to rewrite to https. This means you don't have to include image types and every other binary filetype. The msword, excel and powerpoint content-types should typically be "application/msword", etc (Click here). They should not contain the word text.

    Here is an example which implements the logic you suggested, followed by one that only rewrites text.

     
     when HTTP_RESPONSE {   
      
         Disable the stream filter by default   
        STREAM::disable 
      
         Check if we're rewriting the response   
        switch -glob [string tolower [HTTP::header value Content-Type]] { 
           "*msword*" - 
           "*vnd.excel*" - 
           "*ms-powerpoint*" { 
               Response isn't one we want to rewrite.  Do nothing. 
              log local0. "[IP::client_addr]:[TCP::client_port]: Not modifying response for response type [HTTP::header value Content-Type]" 
           } 
           default { 
               For all other responses, match any http:// instance and replace it with https:// in the response payload 
              STREAM::expression {@http://@https://@}   
      
               Enable the stream filter for this response only     
              STREAM::enable 
      
              log local0. "[IP::client_addr]:[TCP::client_port]: Modifying response for response type [HTTP::header value Content-Type]" 
           } 
        } 
     } 
     

     
     when HTTP_RESPONSE {   
      
         Disable the stream filter by default   
        STREAM::disable 
      
         Check if we're rewriting the response   
        if {[HTTP::header value Content-Type] contains "text"}{ 
      
            Match any http:// instance and replace it with https://   
           STREAM::expression {@http://@https://@}   
      
            Enable the stream filter for this response only     
           STREAM::enable 
      
           log local0. "[IP::client_addr]:[TCP::client_port]: Modifying response for response type [HTTP::header value Content-Type]" 
           } 
        } 
     } 
     

    Aaron
  • Darrell_Kesti_5's avatar
    Darrell_Kesti_5
    Historic F5 Account
    Thanks for the information. I am getting very close. The word documents and other files are now properly being handled and the content is being written to https://. However, there is one concern. I just found out that the sharepoint portal also uses some external links to other sites that are called from the client machine, so we are replacing the http:// links in these sites to be https://, and it is breaking some of the reporting metrics because of this. Here is a variant of the rule I created. I only want to change the http content to https if it is part of the intranet.mydomain.com site, which is what the VIP is front ending, and not for any other links that may stream by in the page content.

     

     

    Here is the rule I am thinking will do this. Does this look correct to anyone, or do you have any ideas? Do I need any wild carding as the paths will be http://intranet.mydomain.com/etc/etc

     

     

    when HTTP_RESPONSE {

     

     

    disable stream replacement by default

     

    STREAM::disable

     

     

    enable for text docs only

     

    if {[HTTP::header value Content-Type] contains "text"}{

     

     

    Replace any http:// instance with https:// only if the original string is http://intranet.mydomain.com.

     

    STREAM::expression {@http://intranet.mydomain.com@https://intranet.mydomain.com@}

     

    STREAM::enable

     

    }

     

    }

     

     

    when STREAM_MATCHED {

     

     

    This will log when the stream is matched in /var/log/ltm. This should help with any future troubleshooting as well.

     

     

    log local0. "[IP::client_addr]:[TCP::local_port]: matched: [STREAM::match], replaced with: [string map {http:// https://}

     

     

    [STREAM::match]]"

     

    STREAM::replace "[string map {http:// https://} [STREAM::match]]"

     

    }

     

     

     

    Thank you for looking at this.

     

  • That looks fine. You don't need to include anything for the paths if you want to just replace all instances of http://intranet.mydomain.com with https://intranet.mydomain.com. irrespective of the path.

     

     

    Aaron
  • Darrell_Kesti_5's avatar
    Darrell_Kesti_5
    Historic F5 Account
    Thanks Aaron. This new rule did the trick...looks like we are good. Thanks for the help.