Layer 7 Cookbook

Introduction

This document gives several examples of common L7 load balancer usage. For a description of L7 load balancing see: Layer 7 Load Balancing

For the purposes of this guide we assume that the OpenStack Client command-line interface is going to be used to configure all features of Octavia with the Octavia driver back-end. Also, in order to keep these examples short, we assume that many non-L7 configuration tasks (such as deploying loadbalancers, listeners, pools, members, healthmonitors, etc.) have already been accomplished. A description of the starting conditions is given in each example below.

Examples

Redirect http://www.example.com/ to https://www.example.com/

Scenario description:

  • Load balancer lb1 has been set up with TERMINATED_HTTPS listener tls_listener on TCP port 443.

  • tls_listener has been populated with a default pool, members, etc.

  • tls_listener is available under the DNS name https://www.example.com/

  • We want any regular HTTP requests to TCP port 80 on lb1 to be redirected to tls_listener on TCP port 443.

Solution:

  1. Create listener http_listener as an HTTP listener on lb1 port 80.

  2. Set up an L7 Policy policy1 on http_listener with action REDIRECT_TO_URL pointed at the URL https://www.example.com/

  3. Add an L7 Rule to policy1 which matches all requests.

CLI commands:

openstack loadbalancer listener create --name http_listener --protocol HTTP --protocol-port 80 lb1
openstack loadbalancer l7policy create --action REDIRECT_PREFIX --redirect-prefix https://www.example.com/ --name policy1 http_listener
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value / policy1

Send requests starting with /js or /images to static_pool

Scenario description:

  • Listener listener1 on load balancer lb1 is set up to send all requests to its default_pool pool1.

  • We are introducing static content servers 10.0.0.10 and 10.0.0.11 on subnet private-subnet, and want any HTTP requests with a URL that starts with either “/js” or “/images” to be sent to those two servers instead of pool1.

Solution:

  1. Create pool static_pool on lb1.

  2. Populate static_pool with the new back-end members.

  3. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at static_pool.

  4. Create an L7 Rule on policy1 which looks for “/js” at the start of the request path.

  5. Create L7 Policy policy2 with action REDIRECT_TO_POOL pointed at static_pool.

  6. Create an L7 Rule on policy2 which looks for “/images” at the start of the request path.

CLI commands:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name static_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.0.10 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer member create --address 10.0.0.11 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool static_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value /js policy1
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool static_pool --name policy2 listener1
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value /images policy2

Alternate solution (using regular expressions):

  1. Create pool static_pool on lb1.

  2. Populate static_pool with the new back-end members.

  3. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at static_pool.

  4. Create an L7 Rule on policy1 which uses a regular expression to match either “/js” or “/images” at the start of the request path.

CLI commands:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name static_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.0.10 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer member create --address 10.0.0.11 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool static_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type REGEX --type PATH --value '^/(js|images)' policy1

Send requests for http://www2.example.com/ to pool2

Scenario description:

  • Listener listener1 on load balancer lb1 is set up to send all requests to its default_pool pool1.

  • We have set up a new pool pool2 on lb1 and want any requests using the HTTP/1.1 hostname www2.example.com to be sent to pool2 instead.

Solution:

  1. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at pool2.

  2. Create an L7 Rule on policy1 which matches the hostname www2.example.com.

CLI commands:

openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool2 --name policy1 listener1
openstack loadbalancer l7rule create --compare-type EQUAL_TO --type HOST_NAME --value www2.example.com policy1

Send requests for *.example.com to pool2

Scenario description:

  • Listener listener1 on load balancer lb1 is set up to send all requests to its default_pool pool1.

  • We have set up a new pool pool2 on lb1 and want any requests using any HTTP/1.1 hostname like *.example.com to be sent to pool2 instead.

Solution:

  1. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at pool2.

  2. Create an L7 Rule on policy1 which matches any hostname that ends with example.com.

CLI commands:

openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool2 --name policy1 listener1
openstack loadbalancer l7rule create --compare-type ENDS_WITH --type HOST_NAME --value example.com policy1

Send unauthenticated users to login_pool (scenario 1)

Scenario description:

  • TERMINATED_HTTPS listener listener1 on load balancer lb1 is set up to send all requests to its default_pool pool1.

  • The site behind listener1 requires all web users to authenticate, after which a browser cookie auth_token will be set.

  • When web users log out, or if the auth_token is invalid, the application servers in pool1 clear the auth_token.

  • We want to introduce new secure authentication server 10.0.1.10 on Neutron subnet secure_subnet (a different Neutron subnet from the default application servers) which handles authenticating web users and sets the auth_token.

Note: Obviously, to have a more secure authentication system that is less vulnerable to attacks like XSS, the new secure authentication server will need to set session variables to which the default_pool servers will have access outside the data path with the web client. There may be other security concerns as well. This example is not meant to address how these are to be accomplished–it’s mainly meant to show how L7 application routing can be done based on a browser cookie.

Solution:

  1. Create pool login_pool on lb1.

  2. Add member 10.0.1.10 on secure_subnet to login_pool.

  3. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at login_pool.

  4. Create an L7 Rule on policy1 which looks for browser cookie auth_token (with any value) and matches if it is NOT present.

CLI commands:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name login_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.1.10 --protocol-port 80 --subnet-id secure_subnet login_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool login_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type REGEX --key auth_token --type COOKIE --value '.*' --invert policy1

Send unauthenticated users to login_pool (scenario 2)

Scenario description:

  • TERMINATED_HTTPS listener listener1 on load balancer lb1 is set up to send all requests to its default_pool pool1.

  • The site behind listener1 requires all web users to authenticate, after which a browser cookie auth_token will be set.

  • When web users log out, or if the auth_token is invalid, the application servers in pool1 set auth_token to the literal string “INVALID”.

  • We want to introduce new secure authentication server 10.0.1.10 on Neutron subnet secure_subnet (a different Neutron subnet from the default application servers) which handles authenticating web users and sets the auth_token.

Note: Obviously, to have a more secure authentication system that is less vulnerable to attacks like XSS, the new secure authentication server will need to set session variables to which the default_pool servers will have access outside the data path with the web client. There may be other security concerns as well. This example is not meant to address how these are to be accomplished– it’s mainly meant to show how L7 application routing can be done based on a browser cookie.

Solution:

  1. Create pool login_pool on lb1.

  2. Add member 10.0.1.10 on secure_subnet to login_pool.

  3. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at login_pool.

  4. Create an L7 Rule on policy1 which looks for browser cookie auth_token (with any value) and matches if it is NOT present.

  5. Create L7 Policy policy2 with action REDIRECT_TO_POOL pointed at login_pool.

  6. Create an L7 Rule on policy2 which looks for browser cookie auth_token and matches if it is equal to the literal string “INVALID”.

CLI commands:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name login_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.1.10 --protocol-port 80 --subnet-id secure_subnet login_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool login_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type REGEX --key auth_token --type COOKIE --value '.*' --invert policy1
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool login_pool --name policy2 listener1
openstack loadbalancer l7rule create --compare-type EQUAL_TO --key auth_token --type COOKIE --value INVALID policy2

Send requests for http://api.example.com/api to api_pool

Scenario description:

  • Listener listener1 on load balancer lb1 is set up to send all requests to its default_pool pool1.

  • We have created pool api_pool on lb1, however, for legacy business logic reasons, we only want requests sent to this pool if they match the hostname api.example.com AND the request path starts with /api.

Solution:

  1. Create L7 Policy policy1 with action REDIRECT_TO_POOL pointed at api_pool.

  2. Create an L7 Rule on policy1 which matches the hostname api.example.com.

  3. Create an L7 Rule on policy1 which matches /api at the start of the request path. (This rule will be logically ANDed with the previous rule.)

CLI commands:

openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool api_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type EQUAL_TO --type HOST_NAME --value api.example.com policy1
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value /api policy1

Redirect requests with an invalid TLS client authentication certificate

Scenario description:

  • Listener listener1 on load balancer lb1 is configured for OPTIONAL client_authentication.

  • Web clients that do not present a TLS client authentication certificate should be redirected to a signup page at http://www.example.com/signup.

Solution:

  1. Create the load balancer lb1.

  2. Create a listener listner1 of type TERMINATED_TLS with a client_ca_tls_container_ref and client_authentication OPTIONAL.

  3. Create a L7 Policy policy1 on listener1 with action REDIRECT_TO_URL pointed at the URL http://www.example.com/signup.

  4. Add an L7 Rule to policy1 that does not match SSL_CONN_HAS_CERT.

CLI commands:

openstack loadbalancer create --name lb1 --vip-subnet-id public-subnet
openstack loadbalancer listener create --name listener1 --protocol TERMINATED_HTTPS --client-authentication OPTIONAL --protocol-port 443 --default-tls-container-ref http://192.0.2.15:9311/v1/secrets/697c2a6d-ffbe-40b8-be5e-7629fd636bca --client-ca-tls-container-ref http://192.0.2.15:9311/v1/secrets/dba60b77-8dad-4171-8a96-f21e1ca5fb46 lb1
openstack loadbalancer l7policy create --action REDIRECT_TO_URL --redirect-url http://www.example.com/signup --name policy1 listener1
openstack loadbalancer l7rule create --type SSL_CONN_HAS_CERT --invert --compare-type EQUAL_TO --value True policy1

Send users from the finance department to pool2

Scenario description:

  • Users from the finance department have client certificates with the OU field of the distinguished name set to finance.

  • Only users with valid finance department client certificates should be able to access pool2. Others will be rejected.

Solution:

  1. Create the load balancer lb1.

  2. Create a listener listner1 of type TERMINATED_TLS with a client_ca_tls_container_ref and client_authentication MANDATORY.

  3. Create a pool pool2 on load balancer lb1.

  4. Create a L7 Policy policy1 on listener1 with action REDIRECT_TO_POOL pointed at pool2.

  5. Add an L7 Rule to policy1 that matches SSL_CONN_HAS_CERT.

  6. Add an L7 Rule to policy1 that matches SSL_VERIFY_RESULT with a value of 0.

  7. Add an L7 Rule to policy1 of type SSL_DN_FIELD that looks for “finance” in the “OU” field of the client authentication distinguished name.

CLI commands:

openstack loadbalancer create --name lb1 --vip-subnet-id public-subnet
openstack loadbalancer listener create --name listener1 --protocol TERMINATED_HTTPS --client-authentication MANDATORY --protocol-port 443 --default-tls-container-ref http://192.0.2.15:9311/v1/secrets/697c2a6d-ffbe-40b8-be5e-7629fd636bca --client-ca-tls-container-ref http://192.0.2.15:9311/v1/secrets/dba60b77-8dad-4171-8a96-f21e1ca5fb46 lb1
openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name pool2 --protocol HTTP
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool2 --name policy1 listener1
openstack loadbalancer l7rule create --type SSL_CONN_HAS_CERT --compare-type EQUAL_TO --value True policy1
openstack loadbalancer l7rule create --type SSL_VERIFY_RESULT --compare-type EQUAL_TO --value 0 policy1
openstack loadbalancer l7rule create --type SSL_DN_FIELD --compare-type EQUAL_TO --key OU --value finance policy1