Forum Discussion

Brian_102810's avatar
Brian_102810
Icon for Nimbostratus rankNimbostratus
Feb 29, 2012

Can F5 LTM replace http with https?

I'm fairly new to F5 LTM, and am having some issues with SSL offload and SSL client profiles. Previously I had multiple server mirrors that were running SSL directly, and Apache was configured to return https URLs to SSL requests and return regular http URLs to clear text requests. Now that LTM is proxying for SSL, Apache is only returning http URLs since it is no longer running SSL. This is fine for the domain that is actually being proxied for, however there are other assets that Apache is calling on pages, for example Amazon S3 links, that get returned as clear text http regardless of whether the F5 receives an http or https request.

 

 

 

I found this KB article http://support.f5.com/kb/en-us/solutions/public/7000/000/sol7027.html that talks about editing the payload of client or server requests. Unless there is an easier solution that I’ve overlooked, what I’d like to do is configure LTM with some sort of rule to replace the string “http:” with “https:” in responses that are received back from servers that are in the SSL offload pool.

 

 

 

The article states that “When applied to a virtual server, the following example Stream profile will search all data streams (the data a virtual server receives on its client and server sides) for the strings 123 and abc. If found, the Stream profile replaces the string 123 with 456 and the string abc with xyz.” I interpret this that client to server HTTP GETs will be replaced with https, which is not what I want, since Apache is only running clear text http now.

 

 

 

It also says that “An iRule can perform the same function of a custom Stream profile. However, in this example the Stream profile is only enabled when an HTTP response is received from the server.” This is basically what I want to accomplish, but I tried the example syntax and couldn’t get it to actually change anything.

 

 

 

I created and iRule that says:

 

when HTTP_RESPONSE {

 

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

 

STREAM::enable

 

}

 

 

 

I then applied the default HTTP profile, default Stream profile, and the iRule to the virtual server pool that is for the SSL offload. Looking at the source of pages returned from the server still has the http: URLs in it though.

 

 

 

Is this the correct way to implement this, or is there some easier alternate way? If this is the correct way how can I tell if the iRule is actually matching my string and the traffic?

 

 

 

 

 

3 Replies

  • Also I wasn't sure if I need to escape the ":" with "\:" or something as well.
  • While you wait for an official answer check this thread, it sounds like I had a very similar problem to yours.

     

     

     

    https://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/50/aft/1184873/showtab/groupforums/Default.aspx
  • We are actually doing the same thing here on DevCentral since we made the flip to full-SSL last Friday. We've used the stream profile for other things like analytics injection previously, but when we switched to SSL, we had to replace all the internal references with https:// links.

     

     

    Before we had the stream profile, the process would be to do a HTTP::collect and buffer up the whole HTTP::payload and from there do string manipulation on that value and then assign it back. In some cases, that's still the best option if you need to more than a simple search and replace.

     

     

    But, with the stream profile, you can specify muliple search/replace strings and have the core code handle the conversion for you. And, for your situation, that seems most appropriate.

     

     

    What you have coded looks good to me. As long as you have a stream profile assigned to the virtual in question it should work. Keep in mind that you might need to close and restart a new browser session as connections are sometimes reused by browsers and any changes you make to the virtual may not take hold until a new connect occurs.

     

     

    If you have verified the config settings are correct and still aren't seeing the content modified, here's how I would debug it. You can use the STREAM_MATCHED event to log out any and all match strings for a given request. Something like this

     

     

    when HTTP_RESPONSE {
      STREAM::expression "@http:@https:@"
      STREAM::enable
    }
    when STREAM_MATCHED {
      log local0. "FOUND STREAM MATCH '[STREAM::match]'"
    }

     

     

    And then you can monitor your /var/log/ltm file for the log output. If you aren't seeing any output, then either the VIP isn't configured properly or something else is a problem. You could try changing the search/replace strings with something else like "@a@A@". Odds are that there will be an 'a' character in the response stream.

     

     

    Once you do get it working, I would warn against doing a blanket "http:" to "https:" conversion. That will change ALL "http:" strings and in most cases that isn't warranted. What we've done for DevCentral is something like this:

     

     

    when HTTP_REQUEST {
      set host [HTTP::host]
    }
    when HTTP_RESPONSE {
       Support local domains
      set stream_expression "@http://$host@@"
       SSL domain2.com
      append stream_expression "@http://domain2.com@@"
       SSL domain3.com
      append stream_expression "@http://domain3.com@@"
       External embeds
      append stream_expression "@embed src=\"http://@@
       Enable stream
      STREAM::expression $stream_expression
      STREAM::enable
    }
    when STREAM_MATCHED {
      switch [STREAM::match] {
        "http://$host" {
          STREAM::replace "https://$host"
        }
        "http://domain2.com" {
          STREAM::replace "https://domain2.com"
        }
        "http://domain3.com" {
          STREAM::replace "https://domain3.com"
        }
        "embed src=\"https://" {
          STREAM::replace "embed src=\"https://"
        }
      }
    }

     

     

    You'll notice I didn't include a replace string but specified it in the STREAM_MATCHED event with the STREAM::replace command. In this case you could have specified them in the stream_expression variable without the switch case. But, for us, we have a analytics replacement that we only want to happen once. This way we can keep track of multiple replacements of that given token (ie "").

     

     

    Hope this helps out a bit and please let us know if things are still not working after some debugging.

     

     

    -Joe