Forum Discussion

What_Lies_Bene1's avatar
What_Lies_Bene1
Icon for Cirrostratus rankCirrostratus
Feb 01, 2006

Combining Logical Operators

Hi all. Hope you're all well.

 

 

I'd like to reduce some scripts I have that are used to restrict and redirect traffic. Access is based on domain name and client IP address. We've multiple domain names pointing to a single VS and restricted URI's too, as well as multiple clients, none of whom should see each others sites.

 

 

So, I've got something like that below. We check the IP against the data group and then evaluation the host and uri. Based on the results we redirect accordingly. Then we have to do the same for every different host and every different uri. A nightmare.

 

 

It's never gonna be great (we're simply running too much through a single VS) however, I'm sure some of the checks could be reduced. For instance [matchclass [IP::client_addr] equals $::AAA_HOSTS or BBB_HOSTS or CCC_HOSTS]. Is it possible?

 

 

(We can combine the data groups by the way, we'd lose track of who's who - unless we could reference data groups from within data groups??)

 

 

if {[matchclass [IP::client_addr] equals $::AAA_HOSTS] && "[HTTP::host]" equals "HOSTA" && "[HTTP::uri]" equals "/"}

 

{

 

log local0. "blah blah"

 

HTTP::redirect https://blah blah

 

}

 

elseif {[matchclass [IP::client_addr] equals $::BBB_HOSTS] && "[HTTP::host]" equals "HOSTA" && "[HTTP::uri]" equals "/"}

 

{

 

HTTP::redirect https://somewhere else

 

}

 

if

 

 

 

Thanks in advance

10 Replies

  • I am trying to generalize some rules, to do this I think a "class" needs to be created. The "class" would be loaded into an array to be referenced by the rule. The size of the class would be unknown and have a format something like this:

     

     

    IP, number of items that follow, port 1, port 2, port x

     

    "10.10.10.10,2,4111,4121"

     

     

    Is there a way to bulk load a class into an array?

     

    Should I have a last line in the class to search for?
  • Data Groups (or classes) can be operated on as if they were a TCL list. You can use the TCL list commands to get the length of the list and extract elements. I'm unsure why you want to use an array for this.

     

     

    If you want to convert the values in the lines of the list into an array, I guess I could understand that but you can still use the list commands to achieve the same goal.

     

     

    Another question I have is why you are including the number of items after the address in the class item value? Here's some code that will take a class, pull out line by line, convert each line into a separate list (from the comma separated values) and extract the relevant information.

     

     

    class port_mappings {
      "10.10.10.10,4111,4121",
      "10.10.10.20,5111,5121"
    }
    *** BEGIN iRule ***
    when HTTP_REQUEST {
         iterate through port_mappings class (as a list)
        foreach line $::port_mappings {
         Create a list from the current line
        set item_list [split $line ","]
         Extract item 0 (ip address)
        set ip [lindex $item_list 0]
         iterate through all the port numbers.
        for {set x 1} {$x<[llength $item_list]} {incr x} {
          set port [lindex $src_list $x]
        } 
      }
    }
    *** END iRule ***

     

     

    Sidenote, if you are trying to use the data group with the matchclass command to find a matching ip address, you could use findclass instead and have it return the trailing list of ports if you format the line like this and call findclass with a separator of a space.

     

     

    "10.10.10.10 4111,4121"

     

     

    Not sure if this helps you or not, but I hope it gives you some ideas...

     

     

    -Joe

     

  • I think this is just what I wanted. We are in the process of moving from 4.5.x to 9.x.y and have more than 50 rules per LB, they are all tweaked a little for each VIP. I would like to generalize to about 5 - 10 rules, to do this I need variable data per VIP.

     

     

    Also to do this I could use an "init rule" to load the data or have the rule sense the data hadn't been loaded and load it at that time. If the rule senses the data is to be loaded it adds overhead.

     

     

    if { [info exists ::slice_list] } {

     

    if {$::slice_list(0) != "loaded" } {

     

     

    Is there another / better way of doing this?
  • Thanks for the reply Colin. I think the first option is the most appropriate, it will still simplify things alot, nice one. The second isn't really useable as two IP's (it's all client web proxies) needs access to multiple domains pointing to a single VS but only specific URI's on those domains, another single IP needs access to only one of those domains and on and on and on. That covers a client, their call centre provider and their IVR system. Then you have another client, different domains, same VS, same URI restrictions and so on. Every client has a slightly different setup and trust levels for their IVR providers etc are also different.

     

     

    It's efficient on the server/platform side but tough to manage, hence the need to seperate the IP's and data group to keep a grip!

     

     

    Thanks again.
  • Worth noting for anyone who found this useful that my LB's (running 9.05) didn't like the round brackets () at all. Simply removing them solved the problem. Cheers
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Really? Your BIG-IP had problems with the parenthesis " ) "? That's surprising.

     

     

    I'd be willing to bet it was a spacing issue, more than a parenthesis issue. I know iRules can be quite picky about spacing. Thanks very much for the feedback though, it's very helpful to hear people's experiences.

     

     

    Thanks,

     

    -Colin
  • This question is about matchclass using a class having an incorrect format:

     

     

    b class slice_port '{

     

    "10.47.149.251:4111 10.47.134.19:80"

     

    "10.47.149.251:4121"

     

    }'

     

     

    If I search for the :4111 port I get the corresponding right side of the line back, if I search for the :4121, I seem to get the left side back.

     

     

    I am trying to protect myself from misconfigured class? Any suggestions?
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    If you're using matchclass you should get a result of 0 or 1 depending on the match. If you're using findclass with a delimiter specified, then you should get whatever comes after said delimiter.

     

     

    I.E. in your example, you would need a findclass statement with a " " or ":4111 " delimiter specified, and you'd get whatever came after that part of the class entry.

     

     

    I'm not quite sure what your specific question is, though, so perhaps you could add a little more detail?

     

     

    Thanks,

     

    -Colin
  • I am using a findclass, and mistakenly entered a record in the class table with no space:

     

     

    case 1: "a b" (this is correct)

     

    case 2: "a " (this will return a null sting)

     

    case 3: "a" (this will return a)

     

     

    Is there a way I can protect myself from case 3?
  • I have it now, after speaking with (Anthony Gerace F5) I can test if the index into the class is equal to the returned value to test for the missing space.

     

     

    Thanks.