Forum Discussion

bigipjr28_13978's avatar
bigipjr28_13978
Icon for Nimbostratus rankNimbostratus
Jan 22, 2016

irule that clears and then sets header for multiple vips

Hey Guy,

 

looking for an iRule that clears and sets the HTTP Host header to the appropriate value for all VIPs on LTM.

 

Here is what I was thinking below:

 

when HTTP_REQUEST { remove any existing host header HTTP::header remove Host

 

set host header to the value associated with this VIP Get the values from the Data Group List where the name of the Data Group List matches the VIP name.

set HostValue [string tolower [class match -value Host equals [virtual name]]] HTTP::header insert “Host” $HostValue }

 

That should do it. The only simplification beyond that would be if your VIP names included the wideip hostname itself. For example if the name of the vip for the DRIS application was “xxx.yyy.com” then you could skip the data groups all together for this function. It would be something like:

 

when HTTP_REQUEST { remove any existing host header HTTP::header remove Host

 

set host header to the value associated with this VIP. Not sure [virtual name] is the correct syntax to get the name of the VIP. assumes the VIP configuration name is equivalent to the wideip host name served by the VIP. E.g. xxx.yyy.com

HTTP::header insert “Host” [virtual name] }

 

Any help is welcomed, thanks

 

7 Replies

  • Hi bigipjr28,

     

    the code wouldn't be a little tricky on the way you've described it...

     

    It would be much more effective, to have a fixed naming convention for the data_group enabled virtuals. In this case we could check if the naming convention matches and then crawl the datagroup for the given virtual name. And if the naming convention didn't match then use the virtual name as a HOST name. Would that be okay for your, too?

     

    What should happen with those virtuals that have to be matched against the datagroup, but without any result? Leave the HOST name as is? Throw an error?

     

    Cheers, Kai

     

  • Hi bigipjr28,

     

    a sample code would look like this...

     

    when HTTP_REQUEST {
        if { [set temp(virtual) [URI::basename [virtual name]]] starts_with "DC_" } then {
            if { [set temp(host) [class match -value $temp(virtual) equals DG_VIRTUAL_2_HOST]] ne "" } then {
                HTTP::header remove Host
                HTTP::header insert Host $temp(host)
            } else {
    
                 The Datagroup doesn't have a match. 
                 Add additional code here to handle those exeptions or simply let the requests pass. 
    
            }
        } else {
            HTTP::header remove Host
            HTTP::header insert Host $temp(virtual) 
        }
        unset -nocomplain temp
    }
    

    Note: I haven't had the chance to test the actual code. So please bear with me if minor syntax errors (e.g. missing braces, etc.) are left... 😉

     

    Cheers, Kai

     

  • Hi Bigipjr28,

     

    below are the requested iRules. I do think that the DataGroup approach is more suited for less TCL/iRule experienced administrators, since the daily administration would be GUI based.

     

    iRule1: Using DataGroups selection with added logging

     

    when HTTP_REQUEST {
        if { [set temp(virtual) [URI::basename [virtual name]]] starts_with "DC_" } then {
            if { [set temp(host) [class match -value $temp(virtual) equals DG_VIRTUAL_2_HOST]] ne "" } then {
                log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(host)\""
                HTTP::header remove Host
                HTTP::header insert Host $temp(host)
            } else {
    
                 The Datagroup doesn't have a match. 
                 Add additional code here to handle those exeptions or simply let the requests pass. 
    
            }
        } else {
            log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(virtual)\""
            HTTP::header remove Host
            HTTP::header insert Host $temp(virtual) 
        }
        unset -nocomplain temp
    }

    Note: The DataGroup is TYPE=STRING, KEY=YOUR_VIRTUAL_NAME, Value=www.your-site.de

     

    iRule2: Using SWITCH selection with added logging

     

    when HTTP_REQUEST {
        switch -glob -- [URI::basename [virtual name]]] "DC_Virtual_1" {
            set temp(host) "www.domain1.de"
        } "DC_Virtual_2" {
            set temp(host) "www.domain2.de"
        } "DC_Virtual_3" {
            set temp(host) "www.domain3.de"
        } "DC_Virtual_4" {
            set temp(host) "www.domain4.de"
        } "DC_Virtual_5" {
            set temp(host) "www.domain5.de"
        } "DC_Virtual_6" {
            set temp(host) "www.domain6.de"
        } "DC_Virtual_7" {
            set temp(host) "www.domain7.de"
        } "DC_Virtual_8" {
            set temp(host) "www.domain8.de"
        } "DC_Virtual_9" {
            set temp(host) "www.domain9.de"
        } "DC_Virtual_10" {
            set temp(host) "www.domain10.de"
        } "DC_*" {
             The Datagroup doesn't have a match. 
             Add additional code here to handle those exeptions or simply let the requests pass. 
        } default {
            log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(virtual)\""
            HTTP::header remove Host
            HTTP::header insert Host $temp(virtual)
            unset -nocomplain temp
            return
        }
        log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(host)\""
        HTTP::header remove Host
        HTTP::header insert Host $temp(host)
        unset -nocomplain temp
    }

    Additional Note: If you dont have clean naming convention for your Virtual Servers, then you may want to use the iRules below. Those would lookup well known Virtual Server using the DataGroup/Switch command and if this fails it would use the Virtual Server name as the new host name. But the logic is overall more error prone...

     

    iRule1

     

    when HTTP_REQUEST {
        if { [set temp(host) [class match -value [set temp(virtual) [URI::basename [virtual name]]] equals DG_VIRTUAL_2_HOST]] ne "" } then {
            log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(host)\""
            HTTP::header remove Host
            HTTP::header insert Host $temp(host)
        } else {
            log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(virtual)\""
            HTTP::header remove Host
            HTTP::header insert Host $temp(virtual) 
        }
        unset -nocomplain temp
    }

    iRule2

     

    when HTTP_REQUEST {
        switch -glob -- [set temp(virtual) [URI::basename [virtual name]]] "DC_Virtual_1" {
            set temp(host) "www.domain1.de"
        } "DC_Virtual_2" {
            set temp(host) "www.domain2.de"
        } "DC_Virtual_3" {
            set temp(host) "www.domain3.de"
        } "DC_Virtual_4" {
            set temp(host) "www.domain4.de"
        } "DC_Virtual_5" {
            set temp(host) "www.domain5.de"
        } "DC_Virtual_6" {
            set temp(host) "www.domain6.de"
        } "DC_Virtual_7" {
            set temp(host) "www.domain7.de"
        } "DC_Virtual_8" {
            set temp(host) "www.domain8.de"
        } "DC_Virtual_9" {
            set temp(host) "www.domain9.de"
        } "DC_Virtual_10" {
            set temp(host) "www.domain10.de"
        } default {
            log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(virtual)\""
            HTTP::header remove Host
            HTTP::header insert Host $temp(virtual)
            unset -nocomplain temp
            return
        }
        log -noname local0.debug "Request on Virtual \"[virtual name]\" for Host \"[HTTP::header value Host]\" changed to Host \"$temp(host)\""
        HTTP::header remove Host
        HTTP::header insert Host $temp(host)
        unset -nocomplain temp
    }

    Cheers, Kai

     

  • Thanks man, you have gone above and beyond, I will plug away at testing again and will reply of what the outcome is..thanks again!

     

    • bigipjr28_13978's avatar
      bigipjr28_13978
      Icon for Nimbostratus rankNimbostratus
      Thanks again for the help, everything complied correctly as well. Few question if you don't mind again. 1. Our virtual names are the exact as to what the url is, so virtual name of app.xxx.yyy.com is the same as going to the url app.xxx.yyy.com so would the string and value pair for the string and value be the same in the datagroup.? 2.We also redirect on 80, so would it be best to apply this irule on the redirect vip or the ssl vip? 3 Also, when using fiddler and or curl to view http traffic should I see the Host: value in the header being removed. If that's the case I do not see it being removed on the request. Thanks again
  • Hi Bigipjr28,

     

    1.) If you use one of the very last provided iRules, then you don't need a datagroup entry for a VS name of app.xxx.yyy.com if the HOST name would become app.xxx.yyy.com. You only need those data group entries if the names are different.

     

    2.) Are you providing full HTTP as well as HTTPS access to your sites, or are you just redirecting everthing from HTTP to HTTPS?

     

    3.) The HOST value is changed between your F5 and your backend server. The way youve asked for is transperent from the users. If you need to have the URL changed in the browser, then you need to HTTP redirect the browser to the new location.

     

    Cheers, Kai