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:
blog.mycompany.example: 192.168.1.11
ecommerce.mycompany.example: 192.168.1.12
socialapp.mycompany.example: 192.168.1.13
To something like:
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.
- hooleylistCirrostratusGreat example Eric!
- This is awesome!