Forum Discussion

Joe_5599_134300's avatar
Joe_5599_134300
Icon for Nimbostratus rankNimbostratus
May 03, 2016

How can you block/reject subdirectories only, with an irule?

I want to block only the subdirectory and not the default or parent.

 

This irule I found on Dev Central and some others I have been testing with will also apply the reject to anything before the sub directory. /app/appsite1 or /*/appsite1

 

I want to only reject when the /appsite1 is called www.xyz.com/app/appsite1

 

when HTTP_REQUEST { switch -glob [string tolower [HTTP::uri]] { "/appsite1_" { reject } "/test_" { reject } default { return } } }

 

21 Replies

  • Hello,

    This irule should works for you :

    when HTTP_REQUEST { 
        switch -glob [string tolower [HTTP::path]] { 
            "*/appsite1" { reject } 
            default {  do nothing } 
        } 
    }
    
    • Joe_5599_134300's avatar
      Joe_5599_134300
      Icon for Nimbostratus rankNimbostratus
      I believe that will still block any uri after www.xyz.com/ I only want to block the subdirectory appsite1. www.xyz.com/app/appsite1
    • Yann_Desmarest_'s avatar
      Yann_Desmarest_
      Icon for Nacreous rankNacreous
      just tested on my own lab the above irule and it works : /test is not rejected and /test/appsite1 respond with a TCP reset.
  • Hello,

    This irule should works for you :

    when HTTP_REQUEST { 
        switch -glob [string tolower [HTTP::path]] { 
            "*/appsite1" { reject } 
            default {  do nothing } 
        } 
    }
    
    • Joe_5599_134300's avatar
      Joe_5599_134300
      Icon for Nimbostratus rankNimbostratus
      I believe that will still block any uri after www.xyz.com/ I only want to block the subdirectory appsite1. www.xyz.com/app/appsite1
    • Yann_Desmarest's avatar
      Yann_Desmarest
      Icon for Cirrus rankCirrus
      just tested on my own lab the above irule and it works : /test is not rejected and /test/appsite1 respond with a TCP reset.
  • @Yann's use of the

    switch
    is an absolutely sensible approach. I would like to highlight two minor things, however. Firstly, unless your underlying filesystem or the encoded URI-path elements are really case-insensitive, I would advise omitting the
    string tolower
    . RFC 3986 says (of URIs in general):

    When a URI uses components of the generic syntax, the component
    syntax equivalence rules always apply; namely, that the scheme and
    host are case-insensitive and therefore should be normalized to
    lowercase.  For example, the URI  is
    equivalent to .  The other generic syntax
    components are assumed to be case-sensitive unless specifically
    defined otherwise by the scheme (see Section 6.2.3).
    

    So, unless the filesystem is case-insensitive or the HTTP server provides virtual paths that it handles in a case-insensitive fashion, the

    string tolower
    is extra processing without advantage. Ordinarily, with software, this is fine (and can even be considered good defensive coding) but with iRules, it's generally best to optimize for performance.

    I mention this here only because I very often see this pattern. For matching against, say,

    HTTP::host
    , it is needed (as the RFC reference above notes), but for
    HTTP::path
    , it often is not.

    Secondly, the

    default
    branch in this case is unnecessary (unless you really need to do something in the default case). The extra overhead is very probably negligible (and may even be optimized away). I point it out only to make clear that an explicit default branch is not required for a
    switch
    .

  • Hello,

    Taken into account the remarks from Vernon and your issue, why not responding with a 403 status and content instead of rejecting the connection. Rejecting the connection may impact subsequent requests when there is some pipelining features activated or if you go through a web proxy or multiple reverse proxies before reaching the bigip.

    when HTTP_REQUEST { 
        switch -glob [HTTP::path] { 
            "*/appsite1" { HTTP::respond 403 content "some html content explaining that the request is not allowed" } 
        } 
    }
    

    If you have only this check to do, You may use of the "if" condition instead of switch.

    • Joe_5599_134300's avatar
      Joe_5599_134300
      Icon for Nimbostratus rankNimbostratus
      I only want the irule to fire when it sees the /appsite1 but not when it sees the /app. www.xyz.com/app/appsite1
  • Hello,

    Taken into account the remarks from Vernon and your issue, why not responding with a 403 status and content instead of rejecting the connection. Rejecting the connection may impact subsequent requests when there is some pipelining features activated or if you go through a web proxy or multiple reverse proxies before reaching the bigip.

    when HTTP_REQUEST { 
        switch -glob [HTTP::path] { 
            "*/appsite1" { HTTP::respond 403 content "some html content explaining that the request is not allowed" } 
        } 
    }
    

    If you have only this check to do, You may use of the "if" condition instead of switch.

    • Joe_5599_134300's avatar
      Joe_5599_134300
      Icon for Nimbostratus rankNimbostratus
      I only want the irule to fire when it sees the /appsite1 but not when it sees the /app. www.xyz.com/app/appsite1
  • Hello,

    Ok, you just need to replace "*/appsite1" by "/appsite1" to make it works your way.

    when HTTP_REQUEST { 
        switch -glob [HTTP::path] { 
            "/appsite1" { HTTP::respond 403 content "some html content explaining that the request is not allowed" } 
        } 
    }
    

    and if you don't plan to add exceptions, you can use a simple if condition

    when HTTP_REQUEST { 
        if { [HTTP::path] equals "/appsite1" } { 
            HTTP::respond 403 content "some html content explaining that the request is not allowed"
        } 
    }
    
    • Yann_Desmarest's avatar
      Yann_Desmarest
      Icon for Cirrus rankCirrus
      The provided irules works fine. Can you elaborate your needs ? I think I'm missing something
    • Joe_5599_134300's avatar
      Joe_5599_134300
      Icon for Nimbostratus rankNimbostratus
      I'm trying to only block, reject or provide message when connecting to the www.xyz.com/app/appsite1, keyword (appsite1) and don't want to block anything when users connecting to www.xyz.com/app/* .
  • Hello,

    Ok, you just need to replace "*/appsite1" by "/appsite1" to make it works your way.

    when HTTP_REQUEST { 
        switch -glob [HTTP::path] { 
            "/appsite1" { HTTP::respond 403 content "some html content explaining that the request is not allowed" } 
        } 
    }
    

    and if you don't plan to add exceptions, you can use a simple if condition

    when HTTP_REQUEST { 
        if { [HTTP::path] equals "/appsite1" } { 
            HTTP::respond 403 content "some html content explaining that the request is not allowed"
        } 
    }
    
    • Yann_Desmarest_'s avatar
      Yann_Desmarest_
      Icon for Nacreous rankNacreous
      The provided irules works fine. Can you elaborate your needs ? I think I'm missing something
    • Joe_5599_134300's avatar
      Joe_5599_134300
      Icon for Nimbostratus rankNimbostratus
      I'm trying to only block, reject or provide message when connecting to the www.xyz.com/app/appsite1, keyword (appsite1) and don't want to block anything when users connecting to www.xyz.com/app/* .
  • when HTTP_REQUEST { 
        if { [HTTP::path] equals "/app/appsite1" } { 
            HTTP::respond 403 content "some html content explaining that the request is not allowed"
        } 
    }
    
  • Hi,

    if you want to block all sub-directory, you can use irule provided by Yann, but with

    starts_with
    instead of
    equals
    :

    when HTTP_REQUEST { 
        if { [HTTP::path] starts_with "/app/appsite1" } { 
            HTTP::respond 403 content "some html content explaining that the request is not allowed"
        } 
    }