Forum Discussion

James_Thomson's avatar
Aug 23, 2007

how to findclass with client IP matching string

I trying to write an iRule for a wildcard virtual server that will look at the client's IP address, then find out what subnet it is in by looking at a class to see where it maps. I don't need a "most specific" match because nothing will overlap.

This rule is doing exactly what I need it to do:


when CLIENT_ACCEPTED {
  if { [IP::addr [IP::remote_addr] equals "10.10.10.0/24"] ne 0} {node 10.10.10.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.230.0/25"] ne 0} {node 10.10.11.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.20.0.0/16"] ne 0} {node 10.10.12.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.22.0/24"] ne 0} {node 10.10.13.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.14.0/24"] ne 0} {node 10.10.14.1}
  elseif { [IP::addr [IP::remote_addr] equals "3.0.0.0/8"] ne 0} {node 10.10.15.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.16.0/24"] ne 0} {node 10.10.16.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.17.0/24"] ne 0} {node 10.10.17.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.18.0/24"] ne 0} {node 10.10.18.1}
  elseif { [IP::addr [IP::remote_addr] equals "10.10.19.0/24"] ne 0} {node 10.10.19.1}
  else { discard }
}

However, I would like to try and get these subnets into a class instead of in the iRule itself.

So, I tried a class and rule like this:


class mapping {
   "10.10.10.0/24 10.10.10.52"
   "10.10.10.0/255.255.255.0 10.10.10.51"
}
rule match-trying {
   when CLIENT_ACCEPTED {
  set my_gw [findclass [IP::client_addr] $::mapping " "]
  log local0. "node $my_gw"
  if { $my_gw ne "" } {
    node $my_gw
  } else { discard }
}
}

but a findclass won't work because the IP I pull from IP::client_addr is a specific address while I have a subnet in the class. Worse off is the subnet in the class is a string so I can't use IP::addr to compare the two.

The previous rule logs nothing.

That is why this returns nothing, because it doesn't string match. The subnets are not always the same so I can't assume that.

I found a few other posts that are so close, but not right.

http://devcentral.f5.com/Default.aspx?tabid=53&view=topic&forumid=5&postid=7784

http://devcentral.f5.com/Default.aspx?tabid=53&view=topic&forumid=5&postid=3691

Any ideas?
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    As you found, I don't think it will work with a single class. You could create two classes and then use matchclass and findclass. Or you could create an array with three elements (network, mask, gateway) and use IP::addr with the client IP and the first two elements to find a match.

    Here's a quick example for using two classes:

    
    when RULE_INIT {
       log local0. "\$::address_class: $::address_class"
       log local0. "\$::gw_class: $::gw_class"
       log local0. "\[matchclass 10.100.0.1 equals \$::address_class\]: [matchclass 10.100.0.1 equals $::address_class]"
       log local0. "[findclass [matchclass 10.100.0.1 equals $::address_class] $gw_class " "]"
       log local0. "\[matchclass 192.168.2.2 equals \$::address_class\]: [matchclass 192.168.2.2 equals $::address_class]"
       log local0. "[findclass [matchclass 192.168.2.2 equals $::address_class] $gw_class " "]"
    }

    With two classes:

    
    class address_class  {
       network 10.0.0.0 mask 255.0.0.0
       network 172.16.0.0 mask 255.240.0.0
       network 192.168.0.0 mask 255.255.0.0
    }

    
    class gw_class  {
       "1 10.1.1.1"
       "2 172.16.0.1"
       "3 192.168.0.1"
    }

    The log output is:

    
     $::address_class: {10.0.0.0/8} {172.16.0.0/12} {192.168.0.0/16}
     $::gw_class: {2 172.16.0.1} {1 10.1.1.1} {3 192.168.0.1}
     [matchclass 10.100.0.1 equals $::address_class]: 1
     10.1.1.1
     [matchclass 192.168.2.2 equals $::address_class]: 3
     192.168.0.1

    With that said, an array might be a cleaner solution.

    Aaron