Routing HTTP by request headers

Dynamic network routing protocols, like BGP, allows Internet traffic to go from point A to B.  Using iControl REST we can create our own dynamic protocol to route HTTP requests from point 1 to 2.

Routing by HTTP request

There’s a finite number of IPv4 addresses available and an increasing number of web applications that are being deployed that consume these resources. To help conserve IPv4 resources we’d like to map multiple web applications on a single front-end public IPv4 address while allow multiple separate back-end private IPv4 addresses that are running different web stacks (i.e. PHP for marketing, NodeJS for mobile, IIS for HR, Docker container for IT, etc…).

Ideally we can go from an infrastructure that looks like:

www.mycompany.example: 192.168.1.10
blog.mycompany.example: 192.168.1.11
ecommerce.mycompany.example: 192.168.1.12
socialapp.mycompany.example: 192.168.1.13


To something like:

(www|blog|socialapp|ecommerce).mycompany.example: 192.168.1.10


To accomplish this we need a mechanism to examine the HTTP request (URL) and route to the correct backend server.

Tools for routing by HTTP request

From a similar article about name-based virtual host we know that we can utilize iRules for processing HTTP requests. Since TMOS 11.4.0 we can also use local traffic policies to do the same. For the following we’ll utilize an iRule for routing, but add a dynamic mechanism to update the routing.

The iRule

The following iRule looks similar to the original article, but has two differences:

1. Utilizes a data group for extracting the desired configuration

2. Routes to nodes instead of pools

when HTTP_REQUEST {
  set host_hdr [getfield [HTTP::host] ":" 1]
  set node_addr [class match -value [string tolower $host_hdr] equals my_nodes]
  if { $node_addr ne "" } {
    node $node_addr
  } else {
    reject
  }
}

You could modify the example to route to pools or route by URI, but for today’s example we assume we are routing requests to separate standalone servers.

The data group is used as a key/value pair that uses the desired host header as the key (i.e. www.mycompany.example) and the desired backend node address and port as the value (i.e. 10.10.1.10:80).

Updating the routing via the GUI

Via the TMOS GUI one needs to update the data group to reflect the desired configuration.

Updating the routing via iControl REST

Now that the configuration is stored in a data group it becomes possible to modify the configuration via iControl REST. Here’s an example utilizing the command line tool curl (note that it requires updating all the data group records each time).

% curl -k -H "Content-Type: application/json" \
-u admin:[admin password] \
https://[mgmt host]/mgmt/tm/ltm/data-group/internal/~Common~my_nodes \
-X PUT \
-d '{"records":[{"name":"www.mycompany.example","data":"10.10.1.11:80"},{"name":"blog.mycompany.example","data":"10.10.1.12:80"},{"name":"ecommerce.mycompany.example","data":"10.10.1.13:80"},{"name":"socialapp.mycompany.example","data":"10.10.1.14:80"}]}'

One could build on the curl example to create their own utility.  I created the "Chen Gateway Protocol" as a Python script.  The execution looks like the following:

% ./cgp.py add www.mycompany.example 10.10.1.11:80
added: www.mycompany.example
% ./cgp.py get www.mycompany.example
www.mycompany.example: 10.10.1.11:80
% ./cgp.py update www.mycompany.example 10.10.1.11:8000
updated: www.mycompany.example
% ./cgp.py del www.mycompany.example
deleted: www.mycompany.example

I've posted the code for cgp.py on the DevCentral codeshare.

Dealing with HTTPS

You can utilize SAN certs, SNI, or wildcard certs to consolidate SSL sites. The pros/cons will be a topic of a separate article.

From here

The above example illustrates what’s possible with the BIG-IP as a mediator of all things HTTP.  Configuration management tools like Puppet, Chef, OpsWorks, SCCM, or a home-grown solution could leverage iControl REST to provide the "dynamic protocol".  If you have any questions/suggestions or want to share how you’re routing by HTTP requests please share via the comments or send me a message via DC.

Updated Jun 06, 2023
Version 2.0