Forum Discussion

Daniel_Abrahams's avatar
Daniel_Abrahams
Icon for Nimbostratus rankNimbostratus
Feb 18, 2021

Require host header

Hi,

 

Is there a setting/iRule that makes it so that host header is required for clients to be able to connect to server.

For example

User enters https://www.test.com he will be able to connect.

But if user enters https://10.10.10.10 they should be rejected

 

Best regards

Daniel

  • Hi  ,

    I have a bit more general approach than  . It will use a regex instead of hard coded IP address.

    Tested on 15.2 and seems to do what it is supposed to do.

    when HTTP_REQUEST {
        if { [scan [HTTP::host] %d.%d.%d.%d a b c d] == 4 && 0 <= $a && $a <= 255 && 0 <= $b && $b <= 255 && 0 <= $c && $c <= 255 && 0 <= $d && $d <= 255} {
            #log local0. "Invalid hostname: [HTTP::host]"
            drop
        } else {
            #log local0. "Valid hostname: [HTTP::host]"
            return
        }
    }

    The regex I simply stole from here: wiki.tcl-lang.org >> Regular Expression Examples

    It is supposed to check whether the string in HTTP::host matches the syntax of an IP address.

  • Hello  ,

    You can use below iRule to achieve your requirement.

    iRule1 - This will allow only www.test.com and rest all will be dropped on the VS.

    when HTTP_REQUEST {
     
    if {([HTTP::host] contains "www.test.com") 
     
    } {
     
            log local0. "Allowed Hostname:[HTTP::host]"
    } else {
     
        drop
        log local0. "“Invalid hostname: [HTTP::host]"
    }
    }

    iRule - 2 - This will allow the required given host and will drop request coming for IP.

    when HTTP_REQUEST {
     
     
    if {([HTTP::host] contains "www.test.com") } {
     
        log local0. "Allowed Hostname:[HTTP::host]"
        
    } elseif {([HTTP::host] contains "10.10.10.10") }
    {
        drop
        log local0. "“Invalid hostname: [HTTP::host]"
    } 
     
    }

    Additionally both irules will log each request and you can see logged requests under ltm files.

    Hope it helps!

  • Hi,

     

    I´ve tested both and they work.

     Is there a way that you can make the iRule match the hostheader with the one set in iapp/virtual server so it can be reused instead of creating one for each? Its been created with iapp "

    f5.http.v1.2.0"

     Your suggestion only says that if its a IP it should be rejected, but it doesnt match the hostheader. Do you have any other suggestion how to do it? The best being that it matches hostheader set in iapp/virtual server and that it rejects if you use IP

     

    Best regards

    Daniel

     

     

  • ,

     

    I am not sure if i fully understood you. Do you mean you have multiple virtual servers created using iApp and you want to allow specific hosts using iRule on each vServers. In that case, you need to attach iRule on each Vserver to work it. Or are you looking for the iRule where it should allow multiple hosts and block required ones? Please confirm! If my understanding is incorrect, please correct me!

     

    Thanks

    • Daniel_Abrahams's avatar
      Daniel_Abrahams
      Icon for Nimbostratus rankNimbostratus

       

       

      I would prefer only one iRule that matches the hostheader with the associated iapp/virtual server.

      So if you take my previous example the iRule fetches the hostheader from the iapp/virtual server and then enters www.test.com as the host variable to be allowed and the IP 10.10.10.10 as the one to be rejected.

       

      So you dont have to manually create one iRule per virtual server. and everything is done dynamically

       

      Best regards

      Daniel

       

       

       

       

  • Would it be ok to go with 1 Irule & 1 Datagroup, but your datagroup entries has to be updated as & when you start applying this Irule to your required VS.

    Logic:

    Create a datagroup with records matching the VS name & its values with urls with comma separated in case multiple SAN's.

    virtual_1 {
    	data www.google.com
    }
    virtual_2 {
    	data www.facebook.com,www.messenger.com
    }

    Create an irule to capture the host header & VS name.

    set virtual [findstr [virtual name] "" 8 ]

    Then use class match to lookup the VS & get the values of it & set to a variable, this would tell what all values are whitelisted for that virtual.

    Now do a if condition & check if the host header matches to the variable, if yes allow. else drop.

    In case of multiple values, use foreach cmd & do your condition check.

    This Irule can be applied as generic Irule. But make sure you add the right records before applying.

    Let me know what you think.

    • Daniel_Wolf's avatar
      Daniel_Wolf
      Icon for MVP rankMVP

      I second this suggestion. One ring iRule to rule them all and a datagroup to match VS name to (any possible) host headers. Other alternative I had in mind was to match the virtual server IP to the host header, but again - using a datagroup.

      • jaikumar_f5's avatar
        jaikumar_f5
        Icon for MVP rankMVP

        Well yeah, thats much simpler. Dont have to worry about URL's. Great one  😎