Forum Discussion

Eric_Frankenfie's avatar
Eric_Frankenfie
Icon for Nimbostratus rankNimbostratus
Sep 29, 2011

Parsing URI to Make Pool Selection

I am trying to write an iRule which will read in a URI and then based on what it finds match the source IP address to data lists to make the pool selection. For example...

 

 

URL: www.example.com/ws/test.asmx

 

 

 

If URI contains "/ws/test.asmx"

 

If source IP address equals Pool A data list

 

Use Pool A

 

Log the request was permitted from source IP address

 

If source IP address equals Pool B data list

 

Use Pool B

 

Log the request was permitted from source IP address

 

Else

 

Drop request

 

Log the request was denied from source IP address

 

 

 

Here is what I have so far, but it seems that all requests are going to pool A. Any help would be greatly appreciated.

 

 

 

when HTTP_REQUEST {

 

if { [string tolower [HTTP::path]] contains "/ws/test.asmx" } {

 

if { ([matchclass [IP::client_addr] equals poolA-AllowList])} {

 

use pool poolA

 

log local0. "Permitted: [IP::client_addr][IP::client_addr] --> [HTTP::header host][HTTP::uri]"

 

if { ([matchclass [IP::client_addr] equals poolB-AllowList])} {

 

use pool poolB

 

log local0. "Permitted: [IP::client_addr][IP::client_addr] --> [HTTP::header host][HTTP::uri]"

 

} else {

 

discard

 

log local0. "Denied: [IP::client_addr] --> [HTTP::header host][HTTP::uri]"

 

}

 

}

 

}

 

}

 

 

 

 

 

 

  • Hi Eric,

    Depending on which BIG-IP version you are running on:

    v9.x.x use "matchclass" and change your variable to $::variable

    v10.x.x use "class match" and leave the "$::" off.

    I would suggest renaming your Data Group and remove the "-" character or you might run into some strange behavior. I would suggest using Underscores or Periods as separators.

    
    when HTTP_REQUEST {
    if { [string tolower [HTTP::path]] contains "/ws/test.asmx" } {
    if { ([matchclass [IP::client_addr] equals poolA-AllowList])} {
    pool pool.fi.dev.gmacmbond.com.7172
    log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
    }
    if { ([matchclass [IP::client_addr] equals poolB-AllowList])} {
    pool pool.fi.dev.gmacsolutions.com.7173
    log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
    }
    else {
    discard
    log local0. "Denied: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
    }
    }
    }
    
  • We finally were able to schedule time to test this, however all did not go according to plan.

    I modified the iRule as follows

     
    when HTTP_REQUEST {
        if { [string tolower [HTTP::path]] contains "/ws/test.asmx" } {
            if { ([matchclass [IP::client_addr] equals poolA.AllowList])} {
                pool poolA
                log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
            }
            if { ([matchclass [IP::client_addr] equals poolB.AllowList])} {
                pool poolB
                log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
            }
            else {
                discard
                log local0. "Denied: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
            }
        }
    }
    

    It appears that
    if { [string tolower [HTTP::path]] contains "/ws/test.asmx" } 
    is not being evaluated properly. I took all entries out of both 'Data Group List' and I still am able to get to the page. In addition, I checked /var/log/ltm and there are no entries for this iRule.

    Are changes to iRules applied immediately or do they need to be reloaded into memory?

    Any suggestions?
  • I just ran another test after modifying the iRule to test the HTTP path, match the IP address in the first list, and log the result. This test was successful. Here is the iRule...

     
    when HTTP_REQUEST {
        if { [string tolower [HTTP::path]] contains "/ws/test.asmx" } {
            if { ([matchclass [IP::client_addr] equals poolA.AllowList])} {
                pool poolA
                log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
            }
    }
    

    For some reason when I try to add the additional conditions the request is sent to the pool defined in the VS and it doesn't appear to be processed by the iRule.

    Any suggestions?
  • I could not get the nested if statements to work. However, by creating two separate iRules, and applying each to the VS, I was able to get the logic to work.

    Virtual Server xyz.com iRules

    First: iRule_poolA

    Second: iRule_poolB

    iRule_poolA

    when HTTP_REQUEST { 
       if { [string tolower [HTTP::path]] contains "/ws/test.aspx" } { 
          if { ([matchclass [IP::client_addr] equals poolA.AllowList])} {
              use pool poolA
              log local0. "Permitted (poolA): [IP::client_addr][IP::client_addr] --> [HTTP::header host][HTTP::uri]"    } 
       }
    }  

    iRule_poolB

     when HTTP_REQUEST { 
       if { 
       [string tolower [HTTP::path]] contains "/ws/test.asmx" 
       } { if { ([matchclass [IP::client_addr] equals poolB.AllowList])} {
              use pool poolB
              log local0. "Permitted (poolB): [IP::client_addr][IP::client_addr] --> [HTTP::header host][HTTP::uri]"
    }  else {
    discard  
    log local0. "Denied (poolA and poolB): [IP::client_addr] --> [HTTP::header host][HTTP::uri]"      }  
       }
    }

    Any ideas why this doesn't seem to work by combining both iRules into a single iRule?
  • Strike that last post!

     

     

    If the address is in the poolA list and is permitted, the traffic will still be processed through the poolB iRule and the traffic will be discarded.

     

     

    Any help would be greatly appreciated.
  • Hi Eric,

    Try this:

     
    when HTTP_REQUEST {
    if { [string tolower [HTTP::path]] contains "/ws/test.asmx" } {
    if { [class match [IP::client_addr] equals poolA.AllowList] } {
                log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
    pool poolA
    HTTP::redirect "http://www.google.com"
            }
    elseif { [class match [IP::client_addr] equals poolB.AllowList] } {
                log local0. "Permitted: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
    pool poolB
    HTTP::redirect "http://www.yahoo.com"
            }
            else {
                log local0. "Denied: [IP::client_addr] --> [HTTP::host][HTTP::uri]"
    discard
    HTTP::redirect "http://www.msn.com"
            }
        }
    }
    
  • Solved!

     

     

    I was using an 'if' statement for the second Data Group List where I should have been using a 'elseif' statement.

     

     

    Here is the final iRule for reference.

     

     

  • Solved!

    I was using an 'if' statement for the second Data Group List where I should have been using a 'elseif' statement.

    Here is the final iRule for reference.

     
    when HTTP_REQUEST { 
       if { [string tolower [HTTP::path]] contains "/ws/test.aspx" } { 
          if { ([matchclass [IP::client_addr] equals poolA.AllowList])} {
              use pool poolA
              log local0. "Permitted (poolA): [IP::client_addr] --> [HTTP::header host][HTTP::uri]"
      } elseif { ([matchclass [IP::client_addr] equals poolB.AllowList])} {
              use pool poolB
              log local0. "Permitted (poolB): [IP::client_addr] --> [HTTP::header host][HTTP::uri]"
    }
    else {
    discard  
    log local0. "Denied (poolA/poolB): [IP::client_addr] --> [HTTP::header host][HTTP::uri]"      }  
       }
    }