For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

izac_189977's avatar
izac_189977
Icon for Nimbostratus rankNimbostratus
Mar 11, 2015

iRule catches /

Hi all,

I'm trying to achieve the following

If a client requests a uri that is listed in the data group denied_uris and the client ip is not from data group trusted_net send a 403

Here is my iRule

when HTTP_REQUEST {
  if { ![class match [string tolower [HTTP::uri]] equals denied_uris] } {
      if { not ([class match [IP::client_addr] equals private_net])}{
     Block request
     HTTP::respond 403 content "URL Blocked"
    return
 }
}
}

denied_uris is a string data group with entries like TCAdmin:=/manager

Basically the iRule works, if i hit /manager from outside I get "URL Blocked" but it seems to catch also / a hit on www.domain.com results in a "URL Blocked" if I hit www.domain.com/entry/index.html it works

In the denied_uris data group there is no / defined

Any suggestions?

Thanks Chris

11 Replies

  • if { ![class match [string tolower [HTTP::uri]] equals denied_uris] } {

    is not (!) here correct?

    shouldn't it be something like this?

     configuration
    
    root@(ve11c)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:80
        ip-protocol tcp
        mask 255.255.255.255
        pool foo
        profiles {
            http { }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        vs-index 12
    }
    root@(ve11c)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm rule qux
    ltm rule qux {
        when HTTP_REQUEST {
      if { [class match [string tolower [HTTP::uri]] starts_with denied_uris] } {
        if { not ([class match [IP::client_addr] equals private_net]) } {
          HTTP::respond 403 content "URL Blocked"
          return
        }
      }
    }
    }
    root@(ve11c)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm data-group internal denied_uris
    ltm data-group internal denied_uris {
        records {
            /manager { }
        }
        type string
    }
    
     test
    
    [root@ve11c:Active:In Sync] config  curl -I http://172.28.24.10/
    HTTP/1.1 200 OK
    Date: Wed, 11 Mar 2015 14:47:24 GMT
    Server: Apache/2.2.3 (CentOS)
    Last-Modified: Sun, 09 Feb 2014 08:39:51 GMT
    ETag: "41879c-59-2a9c23c0"
    Accept-Ranges: bytes
    Content-Length: 89
    Content-Type: text/html; charset=UTF-8
    
    [root@ve11c:Active:In Sync] config  curl -I http://172.28.24.10/manager/something
    HTTP/1.0 403 Forbidden
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 11
    
    
  • nathe's avatar
    nathe
    Icon for Cirrocumulus rankCirrocumulus

    Chris - how come you have the ! in the first if statement? Basically this is saying if the uri isn't in the denied_urls datagroup. From your explanation you want if it is and then if it's not a private IP address then block.

     

    I would hope that removing ! will sort.

     

    Hope this helps,

     

    N

     

  • Sorry guys the "!" in the first if was a left over, forgotten by me...

    I corrected the rule

    when HTTP_REQUEST {
      if { [class match [string tolower [HTTP::uri]] starts_with denied_uris] } {
        if { not ([class match [IP::client_addr] equals private_net]) } {
          HTTP::respond 403 content "URL Blocked"
          return
        }
      }
    }
    

    Now I can access www.domain.com and I get redirected by the webserver to www.domain.com/entry/index.html that's fine.

    But now all uris in the denied_uris data group work from external

    I tried your config @nitass, you're using starts_with I tried it in my setup and switched from equals but the denied_uris are reachable from external.

    This is the only iRule applied to the the VS

  • can you list denied_uris data group?

     tmsh list ltm data-group internal denied_uris
    

    and are you using route domain?

  • of course

    [root@ltm:Active:Standalone] config  tmsh list ltm data-group
    ltm data-group internal denied_uris {
        records {
            GeoAdmin {
                data /geo/web
            }
            Jolokia {
                data /jolokia
            }
            TomcatAdmin {
                data /manager
            }
            TomcatAdminHost {
                data /host-manager
            }
        }
        type string
    }
    

    hope it helps, we don't use route domains

    thank you chris

  • Ok I think I got it

     

    I created a new data group test_ui and added /geo/web* and /manager, only the string no value now the urls get blocked as desired

     

    Is this the correct way?

     

    thanks chris

     

  • Ok now it's getting strange. I rebooted the ltm and after the the reboot it doesn't work anymore

    iRule

    when HTTP_REQUEST {
      if { [class match [string tolower [HTTP::uri]] starts_with url_test] } {
         if { not ([class match [IP::client_addr] equals private_net])}{
         Block request
         HTTP::respond 403 content "URL Blocked"
        return
     }
    }
    }
    

    data group url_test

    ltm data-group internal url_test {
        records {
            /geo/web\* { }
            /manager { }
        }
        type string
    }
    

    Both url's are accessible from external, it worked before the reboot

    Thanks Chris

  • nathe's avatar
    nathe
    Icon for Cirrocumulus rankCirrocumulus

    Chris,

    Don't think it likes the string geo/web*

    Here's my example that works (esp as you're doing starts_with):

    ltm data-group internal url_test {
        records {
            /geo/web/ { }
            /manager { }
        }
        type string
    }
    

    See if that works.

    Not sure why it would stop working after a reboot though, unless you made the changes in the CLI and then you need to do a

    tmsh save sys config

    Rgds

    N

  • it doesn't work on my side :( I deleted all uris except one from the data group

    data group

    ltm data-group internal url_test {
        records {
            /geo/web { }
        }
        type string
    }
    

    the iRule

    when HTTP_REQUEST {
      if { [class match [string tolower [HTTP::uri]] starts_with url_test] } {
         if { not ([class match [IP::client_addr] equals private_net])}{
         Block request
         HTTP::respond 403 content "URL Blocked"
        return
     }
    }
    }
    

    I have no idea why it is not working, it's a pretty simple iRule Maybe I should open a support ticket...

    Thanks Chris

    • nathe's avatar
      nathe
      Icon for Cirrocumulus rankCirrocumulus
      Perhaps add some logging e.g. log local0. "Request: [HTTP::uri]" under HTTP_REQUEST
    • nathe's avatar
      nathe
      Icon for Cirrocumulus rankCirrocumulus
      And perhaps after ur if statements eg log local0. URI match