iRules Recipe 3: Pool and SNAT Selection by Host Header Value

The Problem

You manage a number of web sites, and they are spread across servers in several different pools. You want to use a single public IP for all of these, so you need to make a pool selection based on the incoming Host header value. Moreover, one pool requires SNAT but the others do not. Finally, you need persistence for all landing sites but one.

The Configuration

ltm virtual vs-websites {
    destination 203.0.113.10:http
    ip-protocol tcp
    mask 255.255.255.255
    persist { cookie { } }
    pool default-web-pool
    profiles { http { } tcp { } }
    rules { by-host-pool-selector }
}

The Code

when HTTP_REQUEST {
    switch [string tolower [HTTP::host]] {
        "www.great-app.com" -
        "great-app.com" {
            pool great-app-pool
        }

        "dev.great-app.com" {
            pool great-app-dev-pool
            snat automap
        }

        "www.fun-app.org" -
        "fun-app.org" - {
            pool fun-app-pool
            persist none
        }
    }
} 

Analysis

Notice that the Virtual Server to which this rule is applied does not have SNAT enabled, but does have Cookie Persistence enabled. The

switch
command's first argument normalizes the Host header value, changing it to all lower-case. See the "Analysis" section in iRule Recipe 1 to understand why this is necessary when performing comparisons on the Host header. If the (lower-case normalized) Host header has the value "www.great-app.com" or "great-app.com", then the pool selected will be "great-app-pool" (rather than the pool configured on the attached Virtual Server, which in this example is called "great-app-pool"). Notice that, if this branch is followed, then Cookie Persistence applies (because it is defined on the Virtual Server and this condition doesn't disable it) and SNAT is not used (because no SNAT is configured on the Virtual Server and it is not enabled in this code branch). To understand why the first matching case has a dash (-), and why that means this match uses the code for the following case, refer to the "Analysis" section of iRule Recipe 2. If the Host header has the value "dev.great-app.com", then the pool is "great-app-dev-pool" and Automap SNAT is enabled. Notice that, once again Cookie persistence applies in this case because it is defined on the Virtual Server, and is not disabled in the code. If the Host header is "www.fun-app.org" or "fun-app.org", then the pool used will be "fun-app-pool". In this case, the Cookie persistence is disabled (because of
persist none
), which means that no persistence will apply. Moreover, SNAT is not used because it is not configured on the Virtual Server and is not activated in the code. If the Host header matches none of these conditions, then the pool will be "default-web-pool", there will be no SNAT, and Cookie persistence will apply. That's because these are all configured on the Virtual Server, and no code overrides these settings.

Elaboration

In Recipe 2, I used the -glob flag with the

switch
command. Notice that I do not do so here. The -glob flag makes the
switch
slower (that is, it takes more processing cycles). So, if you are performing only exact string matching (and specifically, are not using glob-style matchers), then omit the -glob flag. Notice that the
persist
command can be used to enable or change persistence. This is beyond the scope of this article, but it's worth noting. Moreover, the
snat
command can be used to disable Automap SNAT, or it can be used to specify a specific SNAT address (and, optionally, port). If, however, you want to use a SNAT pool, use the
snatpool
command. However, if a SNAT pool is assigned to the Virtual Server, and you want to disable it for a particular condition, then you would still use
snat none
to disable use of the SNAT pool.

Updated Jun 06, 2023
Version 2.0
  • iRules is a Tcl dialect. It supports a subset of the language, but also adds BIG-IP specific commands and operators.

     

  • Thank you! And to extend it - how to perform http to https redirection at the same time? We do this with the following iRule attached to the VIP:

    when HTTP_REQUEST {
        HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
    }
    

    Do we need to keep it as a second iRule?

  • For a given incoming request, you can either redirect or perform pool selection, but not both. That's because a redirect is a direct response from the BIG-IP platform to the client, and there is only a client flow, whereas pool selection specifies the destination for the server-side flow.