Forum Discussion

ccraddock_33000's avatar
ccraddock_33000
Icon for Nimbostratus rankNimbostratus
Feb 27, 2019

iRule assistance

Dear Dev Central,

I have some specific requirements for an iRule but am not exactly sure how to make it all work in one iRule or if I should use 2 iRules evaluated sequentially. The iRules are as follows:

when HTTP_REQUEST { 
  if {[HTTP::path] starts_with "/resources/" } { 
    pool pool_atldevngn


when HTTP_REQUEST { 
    if { !([class match [HTTP::uri] contains api_string])} { 
       discard 
       log local0. "connection DISCARDED from [IP::client_addr]"
     } else { 
       pool pool_atlapipool1

The first iRule obviously states that if the http path starts with "/resources/" then send that traffic to the "pool_atldevngn" pool. The second irule is a little more complex. This irule states that if the uri DOES NOT contain any of the specified strings preconfigured in the "api_string" Data Group List then drop and log that traffic otherwise just send the traffic to the "pool_atlapipool1" pool.

My question is this: Should I keep these as two separate irules, evaluating the "resources" irule first and then the other? or is there a way to create what would basically be a multi if-elseif branch irule? I am having trouble figuring out how to format it into one iRule.

Any help you can provide would be great! Thanks!

21 Replies

  • It's a matter of personal preference, but I like to consolidate iRules into one as much as possible.

    You can use the return statement to prevent further logic from being executed under the same event within the same iRule

    Does the following help?

    when HTTP_REQUEST {
        if { [HTTP::path] starts_with "/resources/" } {
            pool pool_atldevngn
            return
        } 
        if { !( [class match [HTTP::uri] contains api_string] ) } {
            discard
            log local0. "connection DISCARDED from [IP::client_addr]"
            return
        }
        pool pool_atlapipool1
    }
    
  • Michael,

     

    Thanks for the quick reply! I am not familiar with the return statement. Would you be willing to explain the program flow of the consolidated iRule using the return statement? I would like the "resources" logic to be processed first, if the traffic does not meet that criteria then I want the F5 to move to the next statement in the iRule which is the "api_string". if again that condition is not met then just send the traffic to the atlapipool1 pool. Does this combined iRule do that?

     

    Thanks!

     

  • What you just described is exactly the order in which the iRule will get processed.

     

    You can find more information on the return statement here:

     

    https://clouddocs.f5.com/api/irules/return.html

     

    The return statement will make the F5 stop processing further logic within the same event within the same iRule (there are certain caveats to this e.g. if you specify priorities on the event)

     

    For the above iRule in question, there is only one event i.e. HTTP_REQUEST so if the first IF statement evaluates as true, the return statement will stop the subsequent IF statements from being executed.

     

    With the return statement, it is important to note that if you were to for example add another event further down to this iRule e.g. HTTP_RESPONSE, then this will still get executed since it's a different event. In addition, if you were to add a second separate iRule to the virtual server with the HTTP_REQUEST event, this will also still get executed even if the return statement got hit in the first iRule.

     

    If you wanted to disable ALL further iRule execution (all events and all iRules applied to the virtual server) then you can use the event disable all command

     

  • Looks like this iRule you require. condition sequence can be changed based on the preference.

     

    when HTTP_REQUEST { if { !([class match [HTTP::uri] contains api_string])} { discard log local0. "connection DISCARDED from [IP::client_addr]" } elseif { [HTTP::path] starts_with "/resources/" } { pool pool_atldevngn } else { pool pool_atlapipool1 } }

     

    • Michael_Saleem1's avatar
      Michael_Saleem1
      Icon for Cirrus rankCirrus

      Do you want all requests going to /resources/ to be allowed and sent to pool pool_atldevngn even if the URI does NOT contain one of the values in the data group api_string? If so, the following might work also:

      1) Checks if the URI contains one of the values in data group *api_string. If it it DOES, then send the request to pool pool_atlapipool1. If it does NOT, then:

      2) Check if the path starts with /resources/. If it does, send the request to pool pool_atldevngn. If not, discard (drop) the request

      when HTTP_REQUEST { 
          if { !([class match [HTTP::uri] contains api_string])} { 
              if { [HTTP::path] starts_with "/resources/" } { 
                  pool pool_atldevngn 
              }
              else {
                  discard 
                  log local0. "connection DISCARDED from [IP::client_addr]" 
              } 
          } 
          else { 
              pool pool_atlapipool1 
          } 
      }
      
    • ccraddock_33000's avatar
      ccraddock_33000
      Icon for Nimbostratus rankNimbostratus

      I truly appreciate all the comments and feedback on this post. I think I may have figured it out. Could you check the logic on this irule and let me know if you see any conflicts? Thanks.

      when HTTP_REQUEST { 
        if {[HTTP::path] starts_with "/resources/" } { 
          pool pool_atldevngn
        } elseif { !([class match [HTTP::uri] contains api_string ])} { 
          discard
          log local0. "connection DISCARDED from [IP::client_addr]
        } else {
          pool pool_atlapipool1
        }
      }
      
    • Michael_Saleem1's avatar
      Michael_Saleem1
      Icon for Cirrus rankCirrus

      You're most welcome; that's what this community is here for! :-D

       

      I think there is a conflict with your latest iRule (I may be wrong).

       

      Let's say an HTTP request comes in for: http://www.example.com/resources/

       

      My thinking is that the first if statement will evaluate as true so the F5 will select the pool pool_atldevngn. However, the F5 will not stop there and continue to process the elseif statement which will also evaluate as true (assuming that there is no match against data group api_string). The request will therefore be discarded.

       

      Anyone else agree/ disagree?

       

  • uzair's avatar
    uzair
    Icon for Nimbostratus rankNimbostratus

    Looks like this iRule you require. condition sequence can be changed based on the preference.

     

    when HTTP_REQUEST { if { !([class match [HTTP::uri] contains api_string])} { discard log local0. "connection DISCARDED from [IP::client_addr]" } elseif { [HTTP::path] starts_with "/resources/" } { pool pool_atldevngn } else { pool pool_atlapipool1 } }

     

    • Do you want all requests going to /resources/ to be allowed and sent to pool pool_atldevngn even if the URI does NOT contain one of the values in the data group api_string? If so, the following might work also:

      1) Checks if the URI contains one of the values in data group *api_string. If it it DOES, then send the request to pool pool_atlapipool1. If it does NOT, then:

      2) Check if the path starts with /resources/. If it does, send the request to pool pool_atldevngn. If not, discard (drop) the request

      when HTTP_REQUEST { 
          if { !([class match [HTTP::uri] contains api_string])} { 
              if { [HTTP::path] starts_with "/resources/" } { 
                  pool pool_atldevngn 
              }
              else {
                  discard 
                  log local0. "connection DISCARDED from [IP::client_addr]" 
              } 
          } 
          else { 
              pool pool_atlapipool1 
          } 
      }
      
    • ccraddock_33000's avatar
      ccraddock_33000
      Icon for Nimbostratus rankNimbostratus

      I truly appreciate all the comments and feedback on this post. I think I may have figured it out. Could you check the logic on this irule and let me know if you see any conflicts? Thanks.

      when HTTP_REQUEST { 
        if {[HTTP::path] starts_with "/resources/" } { 
          pool pool_atldevngn
        } elseif { !([class match [HTTP::uri] contains api_string ])} { 
          discard
          log local0. "connection DISCARDED from [IP::client_addr]
        } else {
          pool pool_atlapipool1
        }
      }
      
    • You're most welcome; that's what this community is here for! :-D

       

      I think there is a conflict with your latest iRule (I may be wrong).

       

      Let's say an HTTP request comes in for: http://www.example.com/resources/

       

      My thinking is that the first if statement will evaluate as true so the F5 will select the pool pool_atldevngn. However, the F5 will not stop there and continue to process the elseif statement which will also evaluate as true (assuming that there is no match against data group api_string). The request will therefore be discarded.

       

      Anyone else agree/ disagree?

       

  • uzair's avatar
    uzair
    Icon for Nimbostratus rankNimbostratus

    return is nasty. Suppose u discarded in HTTP request, Here the http packet will be discarded but connection will be opened to server. Which can be a security hole.

     

    event disable will cause all other event not to be executed for this connection, But securtity hole still exist.

     

    Ideal way should be to respond back with error response and make sure connection is closed after that. Even if we discard the request, rule should be resetting the connection.

     

  • Good point about the return statement Uzair, I did not know it could potentially create a security hole.

     

  • You need to be really careful closing a TCP connection. If you are behind a service such as Akamai, closing a TCP connection for one HTTP request could drop connections for thousands of legitimate requests as Akamai multiplex (like OneConnect) connections from end clients.