Direct HTTP request from an IP to specific pool members

We have an iRule works OK as below. HTTP requests are directed to coresponding pools respectively according to URI.

Rule_1:

when HTTP_REQUEST {

switch -glob [HTTP::uri] {

“/video/*” { pool VIDEO }

“/audio/*” {pool AUDIO}

“/text/*” {pool TEXT}

default {pool default_pool}

}

}

Now we want to divert all HTTP requests coming from IP 1.2.3.4 to the first member of each pool.

I add a new rule Rule_2 above Rule_1.

Rule_2:

when HTTP_REQUEST {

if { [HTTP::header “True-Client-IP”] equals “1.2.3.4”} {

log local0. " Requests from 1.2.3.4"

switch -glob [HTTP::uri] {

“/video/*” { pool VIDEO member video_a}

“/audio/*” {pool AUDIO member audio_a}

“/text/*” {pool TEXT member text_a}

default {pool default_pool member default_a}

}

}

}

It doesn’t work. I can see the log " Requests from 1.2.3.4" though, but HTTP request can still land on other pool members.

Any hits or advise are much appreciated.

Not how persistence works with an iRule “pool” command… but am wondering if it is not sending a request to a different pool member because if persistence.

tqu

I’d either combine the 2 irules into 1 or due to the fact that it’s the same event then you may want to use a priority to double ensure the irule no.2 fires the http_request event first

priority 100
when HTTP_REQUEST {
switch -glob [HTTP::uri] {
    "/video/*" { pool VIDEO }
    "/audio/*" {pool AUDIO}
    "/text/*" {pool TEXT}
   default {pool default_pool}
    }
}

priority 10
when HTTP_REQUEST {
 if { [HTTP::header "True-Client-IP"] equals "1.2.3.4"} {
log local0. "  Requests from 1.2.3.4" 
  switch -glob [HTTP::uri] {
    "/video/*" { pool VIDEO member video_a}
    "/audio/*" {pool AUDIO member audio_a}
    "/text/*" {pool TEXT member text_a}
   default {pool default_pool member default_a}
     }
}
}

Hope this helps,

N

tqu

Thought I’d repost back with my 1 iRule for this:

when HTTP_REQUEST {       
 if { [HTTP::header "True-Client-IP"] equals "1.2.3.4"} {    
  log local0. "Requests from 1.2.3.4"
    switch -glob [HTTP::uri] {
    "/video/*" { pool VIDEO member video_a}
    "/audio/*" {pool AUDIO member audio_a}
    "/text/*" {pool TEXT member text_a}
    default {pool default_pool member default_a}
  }
} else {  
  switch -glob [HTTP::uri] {
    "/video/*" { pool VIDEO }
    "/audio/*" {pool AUDIO}
    "/text/*" {pool TEXT}
   default {pool default_pool}
    }
  }
}

Also, according to DevCentral

You can also choose a specific pool member using the pool command:

pool HTTP_pool member 10.10.10.1 80

So if you haven’t you may bee to add the port number after video_a etc..

Hope this helps,

N

tqu

Apologies, messed up my last post:

Thought I’d repost back with my 1 iRule for this:

when HTTP_REQUEST {       
 if { [HTTP::header "True-Client-IP"] equals "1.2.3.4"} {    
  log local0. "Requests from 1.2.3.4"
    switch -glob [HTTP::uri] {
    "/video/*" { pool VIDEO member video_a}
    "/audio/*" {pool AUDIO member audio_a}
    "/text/*" {pool TEXT member text_a}
    default {pool default_pool member default_a}
  }
} else {  
  switch -glob [HTTP::uri] {
    "/video/*" { pool VIDEO }
    "/audio/*" {pool AUDIO}
    "/text/*" {pool TEXT}
   default {pool default_pool}
    }
  }
}

And, according to “https://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/130/iRules-101–05–Selecting-Pools-Pool-Members-and-Nodes.aspx” you need to add the pool member port after the member (pool HTTP_pool member 10.10.10.1 80) e.g. video_a (if you haven’t already of course).

Hope this helps,

N

Thank you for your responses.

@ Mohamed. the virtual server is cookie persistant. I cannot change it for business reasons. But does it mean persistance can override an iRule?

@ Nathan, prioritize two rules doesn’t solve it either. I haven’t tried to put two rules into one yet, do you mean cut rule_2 and paste it to the top of rule_1, and apply only one rule? will it change the flow ?

I don’t know about who wins, the pool command in an iRule or the persistence table. You could ask Support.

Nathan gave you the full combined iRule to use. He also said you need to specify the port number in the “pool” command. Maybe that will fix it?

@Nathan, thank you so much. It looks like your proposed script works!

Hi guys, sorry. It still doesn’t work, when I test it massively with automated testing. :frowning:

It might be wise to enable OneConnect for the Virtual Server and retest, this should stop persistence and the iRule conflicting.

OneConnect Profile is enabled. but still not working.

I’m wondering how soon the updated iRule will be effective? I often test it after 2 minutes, maybe too soon?

tqu

The iRule becomes effective straight away as it’s compiled as soon as you save it.

What Lies Beneath was right about OneConnect - apologies for not mentioning it myself. You may want to take a look at this askf5 KB article to see if this helps:

Rgds

Nathan

@tqu

As nathan pointed out, you can use: pool member member.ip.address member.port to specify the specific member of a pool that you want to direct traffic to. The caveat is that you have to hard code it to the iRule.

This is because there is no simple way to get the BIG-IP to look at a pool, gather a list of members, designate a numeric value of membership, and then make a decision to direct traffic to something as generic as pool member 1, 2, etc.

What Lies Beneath’s suggestion could assist you with your automated testing. The OneConnect profile has several uses, but the one that will specifically help you in your automated testing is the ability to re-use existing connections and a deeper inspection of all incoming traffic allowing individual TCP Requests from the same source IP to be handled independently.

This is used in situations where you have a large amount of traffic coming into your BIG-IP from a NAT (or a service like Akamai) or a single testing server.

Without OneConnect enabled, persistence data is examined only in the first request of a Keep-Alive connection, so if multiple requests are sent on the same clientside Keep-Alive connection, LTM will persist them all to the same destination as the first unless a OneConnect profile is applied (even if logic contained in an iRule dictates otherwise).

@Mohamed Lrhazi

You can get strange behavior if you try and redirect traffic to a specific pool member after the initial load balancing decision has been made. The traffic will bounce back and forth between the Cookie Persistence pool member and the specified pool member.

If you capture the request initially like tqu is trying to do then the default cookie persistence should hold the traffic to the specified node for all remaining request.

If you are routing traffic to a different pool based on something like the [HTTP::uri] value then you should get another BIG-IP Cookie to hold the load balancing decision to the new pool’s pool member.

iRule’s can override and change persistence though see the command.

Hope this helps.

It’s hardly desirable but you could also try one other thing; setup three new pools, each containing only the single member you’d like used by IP 1.2.3.4 and then reference those in your iRule. It would be interesting to see if this worked or not.

Oh, and I know you have a OneConnect profile assigned, but do you also have the OneConnect Transformations option enabled in your HTTP Profile?

tqu,

What OneConnect Mask are you using and are you using SNAT?

If you’re using SNAT then the default /0 mask is fine, if not then you’ll need to configure the mask as /32

Rgds

N

Thank you again all for your replies.

OneConnect Transformations option is enabled, pool member ports are there too.

It is working perfect now :slight_smile: I guess it’s the cookie persistent issue. Once I wait until cookie expired, no test fails at all.

Glad to hear it.