aflex ip based traffic management

leburtonleburton Member
Hi, i'm having a problem with some (basic) aflex traffic redirection on a virtual server that I'm trying to use.

I'm trying to match certain subnet ranges of users to a prioritised server pool (sg2-80), but to not prevent them from connectivity if that prioritised pool goes down for some reason, and send the majority of traffic to the sg1-80 pool. (traffic to real servers is http over port 80 with ssl terminated at a10).

I've applied the aflex template to the virtual server, and at the moment it seems to be matching all traffic to the default in the switch statement regardless of the other cases matching before it (so no traffic is going to sg2) if i take away the "default" then traffic it works but won't catch any cases that dont match the specific ruleset (if it's not in 10.10.0.0/16 in this case).

In the virtual server I haven't bound any service group (the aflex template seems to take care of service group mapping) but if i do then again it seems to ignore the custom matching for specific subnets in the 10.10.0.0/16 range (outside those sent to service group 1)

for reference we have a a10 thunder series 3030s.

I have changed the ip addresses / urls in the aflex code below for privacy, but essentially i'm using these sort of pattern matching rules:

## Redirect end-user connections based on ip address / host header statements on ipv4
# work out if sg2-80 pool is down or if request is specifically for sg2-80 pool on a separate cname alias in host header

when HTTP_REQUEST {
if {[LB::status pool sg2-80] == "down" } { pool sg1-80
} elseif { [HTTP::host] contains "alternate.websitename.co.uk" } { pool sg2-80 }

# matching of internal user subnets to redirect traffic as appropriate

switch [IP::client_addr] {
10.10.10.0/24 { pool sg1-80 }
10.10.28.0/22 { pool sg1-80 }
10.10.60.0/24 { pool sg1-80 }
10.10.0.0/16 { pool sg2-80 }
192.168.0.0/24 { pool sg2-80 }
default { pool sg1-80 }
}
#### at this point I could add ( if { [HTTP::host] contains "default.websitename.co.uk" } { pool sg1-80 } ) to catch outliers which might be a solution but it’s not ideal as it requires working out all the outlying cases… when it would be better to just have a catch all at the bottom
#### alternately I could try using an if{}elseif{} for all tests which may work, but the switch statement is recommended and is certainly more readable as here : https://www.a10networks.com/blog/aflex-optimization
}

Thanks for your help, apologies if some of this doesn't entirely make sense at first glance!
Tagged:

Comments

  • DaniTomDaniTom Member
    edited March 2017
    Hi, I guess, it's not possible with the switch command (maybe other guys knows it better then me ;o).
    My assumption is that switch just compare the "string" of your ip address and thatswhy you will never get a match on the subnet address - like:

    10.10.10.1 is not equal 10.10.10.0/24.

    I think you have two options:
    a) using the "Class::match ip" command or
    b) the "IP::addr" command

    With both commands you can compare an IP address to a subnet. I used that in a "if ... else" statement (but maybe it is usable in "switch" command too!?!?)

    Here my example I just tested some minutes before in my lab and it works for me.

    First I created to classlists called "CL_SRC_POOL_1" and "CL_SRC_POOL_"
    Both classlists are of type ip and have values of subnets:

    ; Class list - CL_SRC_POOL_1
    ; IPv4
    ; IP subnet (Total: 2)
    10.10.10.0 /24
    10.10.28.0 /24

    ; Class list - CL_SRC_POOL_2
    ; IPv4
    ; IP subnet (Total: 2)
    10.12.0.0 /16
    10.16.160.0 /24

    Then create a new aflex :

    when RULE_INIT {
    # for debugging - set it to 0 no logging is perfromed, if set to 1 info log messages in system log is created
    set ::DEBUG 1
    }
    #
    when HTTP_REQUEST {
    # matching of internal user subnets to redirect traffic as appropriate
    #
    set SRC [IP::client_addr]
    set ::CL_01 CL_SRC_POOL_1
    set ::CL_02 CL_SRC_POOL_2
    #
    if { [CLASS::match $SRC $::CL_01 ip] } {
    if { $::DEBUG == 1 } { log "$SRC is on $::CL_01" }
    pool SG_POD1
    } elseif { [CLASS::match $SRC $::CL_02 ip] } {
    if { $::DEBUG == 1 } { log "$SRC is on $::CL_02" }
    pool SG_POD2
    } else {
    if { $::DEBUG == 1 } { log "IP address: $SRC not found on any class-list" }
    pool SG_POD1
    }
    #
    }

    So, I tried that one and it works in my environment. If my IP is in classlist 1 then use poo1, if my IP in cl2 thenn pool2 otherwise if not in any cl then pool1.
    I'm not pretty sure what happens if the ip matches in both cls !?!?! You should give them a try but I assume it grabs on the first match.

    The other option is to use the IP::addr command but I didn't try it. From the documentation:

    when CLIENT_ACCEPTED {
    if { [IP::addr [IP::client_addr] equals 10.10.10.0/24] } {
    pool my_pool
    }
    }

    Hope that helps a little and have a good day,
    Thomas.
  • leburtonleburton Member
    edited March 2017
    Hi Thomas,
    This is a good solution to my problem, thanks very much!
    as I had a large number of ranges to add, using a class-list makes sense, not a feature i've used before :)
    Thanks for your help!

    Laurence
Sign In or Register to comment.