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

JP_42120's avatar
JP_42120
Icon for Nimbostratus rankNimbostratus
Dec 02, 2014

Trying to add more restrictions to exiting iRule with flags

Hi, we are trying to additional restrictions based on new IP and URL to existing rule... Below is an example of our current and also NEW iRule. does this look right? is there a better way to do this?

requirement: only source IP can access current allowed URI's and this new URI. We are adding new IP to both "allow_IP" list

current iRule

when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } {

    set show_flag 0
    set allow_flag 0
Set the allow flag as required for each URI below
    if { [HTTP::uri] starts_with "/gel/" } {
        set allow_flag 1
    } elseif { [HTTP::uri] equals "/water/" } {
        set allow_flag 1
    }
the below filters the URI by IP
    if { [class match [IP::client_addr] equals allow_address_data_group ] } {
        set show_flag 1
    } else {
        if { $allow_flag } {
            set show_flag 1
        }
    }

    if { $show_flag } {
        if { [HTTP::uri] starts_with "/gel/" }{
            pool secure_80_pool
        } elseif { [HTTP::uri] starts_with "/water/" }{
            pool secure_80_pool 
        } else {
        HTTP::redirect "http://deafult-internal.net"
    }

} else {
    HTTP::redirect "http://default_external.com"
}

}

iRule with new restrictions

when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } {

    set show_flag 0
    set allow_flag 0
     new flags for URI and IP respectively
    set r1_flag 0
    set r2_flag 0
Set the allow flag as required for each URI below
    if { [HTTP::uri] starts_with "/gel/" } {
        set allow_flag 1
    } elseif { [HTTP::uri] equals "/water/" } {
        set allow_flag 1
    }
Set the allow flag for new URI
    if { [HTTP::uri] starts_with "/new-URI/" } {
        set r1_flag 1
    }
the below filters the URI by IP
    if { [class match [IP::client_addr] equals allow_address_data_group ] } {
        set show_flag 1
    } else {
        if { $allow_flag } {
            set show_flag 1
    } else { [class match [IP::client_addr] equals new_allow_address_data_group ] } {
        set r2_flag 1   
    } else {
        if { $r1_flag } {
            set r2_flag 1
    }

    if { $show_flag } {
        if { [HTTP::uri] starts_with "/gel/" }{
            pool secure_80_pool
        } elseif { [HTTP::uri] starts_with "/water/" }{
            pool secure_80_pool 
        } else {
            if { $r2_flag } {
        if { HTTP::uri] starts_with "/new-URI/" }{
            pool secure_80_pool
        } else {
        HTTP::redirect "http://deafult-internal.net"
    }


} else {
    HTTP::redirect "http://www.default-external"
}

}

13 Replies

  • Try something like below. It should be less complicated and more efficient.

    when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } {
        If URI start with /gel/ or /water/ validate allowed IP and send it to the pool or redirect
        if { [HTTP::uri] starts_with "/gel/" || [HTTP::uri] equals "/water/" } {
            if { [class match [IP::client_addr] equals allow_address_data_group ] } {
                pool secure_80_pool
            }
            else {
                HTTP::redirect "http://deafult-internal.net"
            }
        }
        If URI start with /new-URIr/ validate allowed IP and send it to the pool or redirect
        elseif { [HTTP::uri] starts_with "/new-URI/" } {
            if { [class match [IP::client_addr] equals new_allow_address_data_group ] } {
                pool secure_80_pool
            }
            else {
                HTTP::redirect "http://deafult-internal.net"
            }
        }
        Redirect all other URI
        else {
            HTTP::redirect "http://www.default-external"
        }
    }
    
    • Brad_Parker's avatar
      Brad_Parker
      Icon for Cirrus rankCirrus
      Missed a bracket when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } { If URI start with /gel/ or /water/ validate allowed IP and send it to the pool or redirect if { [HTTP::uri] starts_with "/gel/" || [HTTP::uri] equals "/water/" } { if { [class match [IP::client_addr] equals allow_address_data_group ] } { pool secure_80_pool } else { HTTP::redirect "http://deafult-internal.net" } } If URI start with /new-URIr/ validate allowed IP and send it to the pool or redirect elseif { [HTTP::uri] starts_with "/new-URI/" } { if { [class match [IP::client_addr] equals new_allow_address_data_group ] } { pool secure_80_pool } else { HTTP::redirect "http://deafult-internal.net" } } Redirect all other URI else { HTTP::redirect "http://www.default-external" } } }
    • JP_42120's avatar
      JP_42120
      Icon for Nimbostratus rankNimbostratus
      Hi Brad, thank you. I will try this format. We actually have 10+ URIs in the first filter. I guess it would look like below if we needed to add more. (I'm still new with iRules) :D adding additional URI's in the filter if { [HTTP::uri] starts_with "/gel/" || [HTTP::uri] equals "/water/" || [HTTP::uri] equals "/dirt/" || [HTTP::uri] equals "/sky/ || [HTTP::uri] equals "/etc/"................}
  • Try something like below. It should be less complicated and more efficient.

    when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } {
        If URI start with /gel/ or /water/ validate allowed IP and send it to the pool or redirect
        if { [HTTP::uri] starts_with "/gel/" || [HTTP::uri] equals "/water/" } {
            if { [class match [IP::client_addr] equals allow_address_data_group ] } {
                pool secure_80_pool
            }
            else {
                HTTP::redirect "http://deafult-internal.net"
            }
        }
        If URI start with /new-URIr/ validate allowed IP and send it to the pool or redirect
        elseif { [HTTP::uri] starts_with "/new-URI/" } {
            if { [class match [IP::client_addr] equals new_allow_address_data_group ] } {
                pool secure_80_pool
            }
            else {
                HTTP::redirect "http://deafult-internal.net"
            }
        }
        Redirect all other URI
        else {
            HTTP::redirect "http://www.default-external"
        }
    }
    
    • Brad_Parker_139's avatar
      Brad_Parker_139
      Icon for Nacreous rankNacreous
      Missed a bracket when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } { If URI start with /gel/ or /water/ validate allowed IP and send it to the pool or redirect if { [HTTP::uri] starts_with "/gel/" || [HTTP::uri] equals "/water/" } { if { [class match [IP::client_addr] equals allow_address_data_group ] } { pool secure_80_pool } else { HTTP::redirect "http://deafult-internal.net" } } If URI start with /new-URIr/ validate allowed IP and send it to the pool or redirect elseif { [HTTP::uri] starts_with "/new-URI/" } { if { [class match [IP::client_addr] equals new_allow_address_data_group ] } { pool secure_80_pool } else { HTTP::redirect "http://deafult-internal.net" } } Redirect all other URI else { HTTP::redirect "http://www.default-external" } } }
    • JP_42120's avatar
      JP_42120
      Icon for Nimbostratus rankNimbostratus
      Hi Brad, thank you. I will try this format. We actually have 10+ URIs in the first filter. I guess it would look like below if we needed to add more. (I'm still new with iRules) :D adding additional URI's in the filter if { [HTTP::uri] starts_with "/gel/" || [HTTP::uri] equals "/water/" || [HTTP::uri] equals "/dirt/" || [HTTP::uri] equals "/sky/ || [HTTP::uri] equals "/etc/"................}
  • does the irule work as intended in its current state? unless i'm misreading, it looks like $show_flag is always set if $allow_flag was set earlier in the rule, regardless of whether the client-IP is in allow_address_data_group:

    if { [class match [IP::client_addr] equals allow_address_data_group ] } {
        set show_flag 1
    } else {
        if { $allow_flag } {
            set show_flag 1
        }
    }
    

    it seems overly complicated and not very flexible. Why not store your allowed-URIs in a data-group?

    when HTTP_REQUEST {
      if { [HTTP::host] starts_with "foo.com" } {
           if { [ class match [IP::client_addr] equals allow_address_dg ] } {
            if { [ class match [HTTP::uri] starts_with allow_uri_dg ] } {
                 pool secure_80_pool
            } else {
                  client-IP matched allow_address_dg but uri didn't match allow_uri_dg
                 HTTP::redirect "http://default.internal.com"
             }
           } else {
               client-IP did not match allow_address_data_group 
              HTTP::redirect "http://default.external.com"
            }
      } else {
         host did not match foo.com
      }
    }
    
    • JP_42120's avatar
      JP_42120
      Icon for Nimbostratus rankNimbostratus
      Hi Shaggy, I was thinking that too when I first saw it, but the app team says it's been working as expected for them. Storing URI's in a datagroup is a great idea. (me newbie :D) it would simplify the irule. thanks!
  • shaggy's avatar
    shaggy
    Icon for Nimbostratus rankNimbostratus

    does the irule work as intended in its current state? unless i'm misreading, it looks like $show_flag is always set if $allow_flag was set earlier in the rule, regardless of whether the client-IP is in allow_address_data_group:

    if { [class match [IP::client_addr] equals allow_address_data_group ] } {
        set show_flag 1
    } else {
        if { $allow_flag } {
            set show_flag 1
        }
    }
    

    it seems overly complicated and not very flexible. Why not store your allowed-URIs in a data-group?

    when HTTP_REQUEST {
      if { [HTTP::host] starts_with "foo.com" } {
           if { [ class match [IP::client_addr] equals allow_address_dg ] } {
            if { [ class match [HTTP::uri] starts_with allow_uri_dg ] } {
                 pool secure_80_pool
            } else {
                  client-IP matched allow_address_dg but uri didn't match allow_uri_dg
                 HTTP::redirect "http://default.internal.com"
             }
           } else {
               client-IP did not match allow_address_data_group 
              HTTP::redirect "http://default.external.com"
            }
      } else {
         host did not match foo.com
      }
    }
    
    • JP_42120's avatar
      JP_42120
      Icon for Nimbostratus rankNimbostratus
      Hi Shaggy, I was thinking that too when I first saw it, but the app team says it's been working as expected for them. Storing URI's in a datagroup is a great idea. (me newbie :D) it would simplify the irule. thanks!
  • Combining both methods....

     

    new iRule

    when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } { If URI match allowed URI's if { [class match [HTTP::uri] starts_with allow_URI_data_group ] } { if { [class match [IP::client_addr] equals allow_address_data_group ] } { pool 80_pool } else { HTTP::redirect "http://deafult-internal.net" } } If URI start with new URI validate allowed IP and send it to the pool or redirect elseif { [class match [HTTP::uri] starts_with new_allow_URI_data_group ] } { if { [class match [IP::client_addr] equals new_allow_address_data_group ] } { pool 80_pool } else { HTTP::redirect "http://deafult-internal.net" } } Redirect all other URI else { HTTP::redirect "http://www.default-external" } } }

     

    • Brad_Parker's avatar
      Brad_Parker
      Icon for Cirrus rankCirrus
      Once you start needing that many uri options the data group is the way to go.
    • JP_42120's avatar
      JP_42120
      Icon for Nimbostratus rankNimbostratus
      HI Brad, Actually, the second condition "/water/more.." is a subset of the first URI "/water/...". Would it be possible to negate "/water/more..." in first condition? Is there a better way? new first condition.. when HTTP_REQUEST { if { [HTTP::host] starts_with "foo.com" } { If URI match allowed URI's if { [class match [HTTP::uri] starts_with allow_URI_data_group ] } { Negate if { [class match [HTTP::uri] not_starts_with "/water/more..."] } { if { [class match [IP::client_addr] equals allow_address_data_group ] } { pool 80_pool } else { HTTP::redirect "http://deafult-internal.net" } }......