Adding nodes and Updating nodes behind a Cloud Load Balancer

I have succeeded in putting together a basic script documenting exactly how API works and for adding node(s), listing the nods behind the LB, as well as updating the nodes (such as DRAINING, DISABLED, ENABLED).

Use update node to set one of your nodes to gracefully drain (not accept new connections, wait for present connections to die). Naturally, you will want to put the secondary server in behind the load balancer first, with addnode.sh.

Once new node is added as enabled, set the old node to ‘DRAINING’. This will gracefully switch over the server.

# List Load Balancers

#!/bin/bash

USERNAME='yourmycloudusernamegoeshere'
APIKEY='apikeygoeshere'
LB_ID='157089'
CUSTOMER_ID='10017858'

TOKEN=`curl https://identity.api.rackspacecloud.com/v2.0/tokens -X POST -d '{ "auth":{"RAX-KSKEY:apiKeyCredentials": { "username":"'$USERNAME'", "apiKey": "'$APIKEY'" }} }' -H "Content-type: application/json" |  python -mjson.tool | grep -A5 token | grep id | cut -d '"' -f4`



curl -v -H "X-Auth-Token: $TOKEN" -H "content-type: application/json" -X GET "https://lon.loadbalancers.api.rackspacecloud.com/v1.0/$CUSTOMER_ID/loadbalancers/$LB_ID"

#

# Add Node(s) addnode.sh

#!/bin/bash

USERNAME='yourmycloudusernamegoeshere'
APIKEY='apikeygoeshere'
LB_ID='157089'
CUSTOMER_ID='10017858'

TOKEN=`curl https://identity.api.rackspacecloud.com/v2.0/tokens -X POST -d '{ "auth":{"RAX-KSKEY:apiKeyCredentials": { "username":"'$USERNAME'", "apiKey": "'$APIKEY'" }} }' -H "Content-type: application/json" |  python -mjson.tool | grep -A5 token | grep id | cut -d '"' -f4`

# Add Node
curl -v -H "X-Auth-Token: $TOKEN" -d @addnode.json -H "content-type: application/json" -X POST "https://lon.loadbalancers.api.rackspacecloud.com/v1.0/$CUSTOMER_ID/loadbalancers/$LB_ID/nodes"



## 

For the addnode script you require a file, called addnode.json
that file must contain the snet ip's you wish to add

#
# addnode.json

{"nodes": [
        {
            "address": "10.0.0.1",
            "port": 80,
            "condition": "ENABLED",
            "type":"PRIMARY"
        }
    ]
}

##

##

# updatenode.sh

#!/bin/bash

USERNAME='yourmycloudusernamegoeshere'
APIKEY='apikeygoeshere'
LB_ID='157089'
CUSTOMER_ID='100101010'
NODE_ID=719425

TOKEN=`curl https://identity.api.rackspacecloud.com/v2.0/tokens -X POST -d '{ "auth":{"RAX-KSKEY:apiKeyCredentials": { "username":"'$USERNAME'", "apiKey": "'$APIKEY'" }} }' -H "Content-type: applic

# Update Node

curl -v -H "X-Auth-Token: $TOKEN" -d @updatenode.json -H "content-type: application/json" -X PUT "https://lon.loadbalancers.api.rackspacecloud.com/v1.0/$CUSTOMER_ID/loadbalancers/$LB_ID/nodes/$NODE_ID"

##

##

## updatenode.json

{"node":{
            "condition": "DISABLED",
            "type":"PRIMARY"
        }
}

Naturally, you will be able to change condition to ENABLED, DISABLED, or DRAINING.

I recommend to use DRAINING, since it will gracefully remove the cloud-server, and any existing connections will be waited on, before removing the server from LB.

HTTPS to HTTP redirect for Rackspace Cloud Load Balancer

Hello,

So a customer reached out to us today asking about how to configure HTTPS to HTTP redirects. This is actually really easy to do.

Think of it like this;

When you enable HTTP and HTTPS (allow insecure and secure traffic), the protocol is always HTTP hitting the server.

When you ‘only allow secure traffic’ it will always be HTTPS. Think of it like, if the load balancer has certificates on it and supports both protocols (i.e. terminates SSL at the load balancer), then the requests hitting the server will always be HTTP.

This is why the X_forwarded_Proto becomes important in your server being able to determine what traffic hitting it coming from load balancer originated from HTTPS protocol, and which originated from HTTP protocol. This is what allows you to effectively do the redirection on the cloud-server side.

I hope this helps!

So the rewrite rule on the server, using x_forwarded_proto to detect the protocol instead of the usual ‘https’ directive can be (or rather will need to be replaced) with a rule that uses the header instead of the regular incoming protocol to determine redirect.

    RewriteEngine On
    RewriteCond %{HTTP:http_x_forwarded_proto} !=http
    RewriteCond %{REQUEST_URI} !^/some/path.*
    RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Quite simple, but took me the better part of half an hour to get my head properly around this 😀

You might be interested in achieving this on Windows systems with iis or similar, so check this link out which explains how to do that step by step in windows;

https://support.rackspace.com/how-to/configuring-load-balanced-sites-with-ssl-offloading-using-iis/

Checking a Website or Rackspace Load Balancers Supported SSL Ciphers

So, you may have recently had an audit performed, or have been warned about the dangers of SSLv3, poodle attack, heartbleed and etc. You want to understand exactly which ciphers your using on the Load Balancer, cloud-server, or dedicated server. It’s actually very easy to do this with nmap. Install it first, naturally.

# CentOS / RedHat
yum install nmap

# Debian / Ubuntu
apt-get install nmap

# Check for SSL ciphers

# nmap hostnamegoeshere.com --script ssl-enum-ciphers -p 443

Starting Nmap 6.47 ( http://nmap.org ) at 2016-10-11 09:12 UTC
Nmap scan report for 134.213.236.167
Host is up (0.0017s latency).
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| SSLv3: No supported ciphers found
| TLSv1.0:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_RSA_WITH_AES_256_CBC_SHA - strong
| compressors:
| NULL
| TLSv1.1:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_RSA_WITH_AES_256_CBC_SHA - strong
| compressors:
| NULL
| TLSv1.2: No supported ciphers found
|_ least strength: strong

Nmap done: 1 IP address (1 host up) scanned in 1.57 seconds

In this case we can see that only TLS v1.1 and TLS v1.0 are supported. No TLSv1.2 and no SSLv3.

Cheers &
Best wishes,
Adam

Checking Load Balancer Connectivity & Automating it in some interesting ways

So, in a dream last night, I woke up realising I had forgot to write my automated load balancer connectivity checker.

Basically, sometimes a customer will complain their site is down because their ‘load balancer is broken’! In many cases, this is actually due to a firewall on one of the nodes behind the load balancer, or an issue with the webserver application listening on the port. So, I wrote a little piece of automation in the form of a BASH script, that accepts an Load Balancer ID and then uses the API to pull the server nodes behind that Load Balancer, including the ports being used to communicate, and then uses, either netcat or nmap to check that port for connectivity. There were a few ways to achieve this, but the below is what I was happiest with.

#!/bin/bash

# Username used to login to control panel
USERNAME='mycloudusernamegoeshere'

# Find the APIKey in the 'account settings' part of the menu of the control panel
APIKEY="apikeygoeshere"

# Your Rackspace account number (the number that is in the URL of the control panel after logging in)
ACCOUNT=100101010

# Your Rackspace loadbalancerID
LOADBALANCERID=157089

# Rackspace LoadBalancer Endpoint
ENDPOINT="https://lon.loadbalancers.api.rackspacecloud.com/v1.0"

# This section simply retrieves and sets the TOKEN
TOKEN=`curl https://identity.api.rackspacecloud.com/v2.0/tokens -X POST -d '{ "auth":{"RAX-KSKEY:apiKeyCredentials": { "username":"'$USERNAME'", "apiKey": "'$APIKEY'" }} }' -H "Content-type: application/json" |  python -mjson.tool | grep -A5 token | grep id | cut -d '"' -f4`

#   (UNUSED) METHOD 1Extract IP addresses (Currently assuming port 80 only)
#curl -H "X-Auth-Token: $TOKEN" -H "Accept: application/json" -X GET "$ENDPOINT/$ACCOUNT/loadbalancers/$LOADBALANCERID/nodes" | jq .nodes[].address | xargs -i nmap -p 80 {}
#   (UNUSED) Extract ports
# curl -H "X-Auth-Token: $TOKEN" -H "Accept: application/json" -X GET "$ENDPOINT/$ACCOUNT/loadbalancers/$LOADBALANCERID/nodes" | jq .nodes[].port | xargs -i nmap -p 80 {}


# I opted for using this method to extract the important detail
curl -H "X-Auth-Token: $TOKEN" -H "Accept: application/json" -X GET "$ENDPOINT/$ACCOUNT/loadbalancers/$LOADBALANCERID/nodes" | jq .nodes[].address | sed 's/"//g' > address.txt
curl -H "X-Auth-Token: $TOKEN" -H "Accept: application/json" -X GET "$ENDPOINT/$ACCOUNT/loadbalancers/$LOADBALANCERID/nodes" | jq .nodes[].port > port.txt

# Loop thru both output files sequentially, order is important
# WARNING script does not ignore whitespace

while read addressfile1 <&3 && read portfile2 <&4; do
   ncat $addressfile1 $portfile2
done 3

Output looks a bit like;

# ./lbtest.sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5143 100 5028 100 115 4731 108 0:00:01 0:00:01 --:--:-- 4734
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 225 100 225 0 0 488 0 --:--:-- --:--:-- --:--:-- 488
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 225 100 225 0 0 679 0 --:--:-- --:--:-- --:--:-- 681
Ncat: No route to host.
Ncat: Connection timed out.

I plan to add some additional support that will check the load balancer is up, AND the servicenet connection between the cloud servers.

Please note that this script must be run on a machine with access to servicenet network, in the same Rackspace Datacenter to be able to check servicenet connectivity of servers. The script can give false positives if strict firewall rules are setup on the cloud server nodes behind the load balancer. It's kind of alpha-draft but I thought I would share it as a proof of concept.

You will need to download and install jq to use it. To download jq please see; https://stedolan.github.io/jq/download/

Custom Error pages for Linux Apache2 and the Rackspace Load Balancer

This article describes how to configure custom error pages for Apache2 and Zeus Load Balancer thru Rackspace API.

I have noticed that every now and then this question comes up. For instance, for most people there will define the errorpage within apache2, but if your not able to do that, and want a more helpful error page to be custom set, perhaps in the same xhtml layout as on your website, then custom error page for Load Balancer may be useful to you.

In apache2 this is traditionally set using the ErrorDocument directive.

The most common error pages are:

400 — Bad Request
The server did not understand the request due to bad syntax.

401 — Unauthorized
The visitor must by authorized (e.g., have a password) to access the page.

403 — Forbidden
The server understood the request but was unable to execute it. This could be due to an incorrect username and/or password or the server requires different input.

404 — Not Found
The server cannot find a matching URL.

500 — Internal Server Error
The server encountered an unexpected condition which prevented it from fulfilling the request.

In your apache2 httpd.conf you will need to add some directives to configure custom error pages. These custom error-pages will be forwarded to the Load Balancer in the case you have servers behind the Load Balancer, and the cloud server behind it encounters an error, it will be sent to the LB and then relayed to the customer, obviously. Instead of being sent directly to the customer as with a traditional apache2 webserver. To form your error page directive edit your httpd conf file either in sites-enabled or httpd.conf or similar, and merely add the following:

ErrorDocument 404 /my404page.html
ErrorDocument 500 /myphppage.php

ErrorDocument 403 /my-custom-forbidden-error-page.html
ErrorDocument 400 /my-bad-request-error-page.html

Then ensure that the error page defined (i.e. my404page.html my-custom-forbidden-error-page.html is placed in the correct directory i.e. the websites root /).

I.e. if your Documentroot is /var/www/html then your my404page.html should go in there.

For some people, for example who are using Load Balancer ACL, the blocked customer/client/visitor won’t be able to see/contact your server when it’s added to the LB DENY list. Therefore you might want to setup another error page on the LB to help customers that are accidentally/wrongly blocked on what process to carry out to remove the block, i.e. contact admin email, etc, etc.

To set custom error page on the load balancer you can use the API like so. You will need two files to achieve this, which will be detailed below:

errorpage.json (file)

{"errorpage":
{"content":"\n\n   Warning- Your IP has been blocked by the Load Balancer ACL, or there is an error contacting the servers behind the load balancer. Please contact [email protected] if you believe you have been blocked in error. \n\n"}
}

customerror.sh (file)

#!/bin/bash
# Make sure to set your customer account number, if you don't know what it is, it's the number that appears in the URL
# after logging in to mycloud.rackspace.com
# ALSO set your username and apikey, visible from the 'account settings' part of rackspace mycloud control panel

USERNAME='mycloudusernamehere'
APIKEY='mycloudapikeygoeshere'
ACCOUNTNUMBER='1001100'

# The load balancer ID, shown in the load balancer details page in mycloud contrl panel
LOADBALANCERID='157089'


API_ENDPOINT="https://lon.loadbalancers.api.rackspacecloud.com/v1.0/$ACCOUNTNUMBER"


# Store the API auth password response in the variable TOKEN

TOKEN=`curl https://identity.api.rackspacecloud.com/v2.0/tokens -X POST -d '{ "auth":{"RAX-KSKEY:apiKeyCredentials": { "username":"'$USERNAME'", "apiKey": "'$APIKEY'" }} }' -H "Content-type: application/json" |  python -mjson.tool | grep -A5 token | grep id | cut -d '"' -f4`

# Execute the API call to update the load balancer error page, submitting as a file the errorpage.json to be used

curl -s -v  \
-H "X-Auth-Token: $TOKEN"  \
-H "X-Project-Id: $ACCOUNTNUMBER" \
-H "Accept: application/json"  \
-d @errorpage.json -X PUT -H "content-type: application/json" \
"$API_ENDPOINT/loadbalancers/$LOADBALANCERID/errorpage"

That it, this concludes the discussion/tutorial on how to set basic error pages both in apache2 (without load balancer) , and with the load balancer only as described above. Please note, it appears you can only set a single error page for the load balancer, as opposed to one error page for each HTTP code.

If anyone see’s any differences or errors though, please let me know!

Best wishes,
Adam

PCI Compliance on Rackspace public cloud

So you wanna be PCI compliant on the public cloud? You server can’t be. But YOU CAN BE PCI COMPLIANT whilst still using your server on the cloud! By using a payment gateway with tokenisation like worldpay or paypal you won’t have to change all your infrastructure. Here is why:

The public cloud, because of the shared environment makes it more difficult to be PCI compliant than in dedicated solutions Rackspace offer, mainly because of the shared environment. Specifically, on the Load Balancers, all of the ciphers are shared, so removing TLS 1.0 for you would affect all other customers load balancers.

You could potentially run your own load balancer, and/or even if Rackspace were able to remove the TLS 1.0 cipher from the load balancer for you, because of the nature of the shared hypervisor, and the shared network it would be really difficult for your rackspace public cloud server to be PCI compliant on public cloud. For you to achieve this I would recommend considering private cloud or dedicated, as this would be practical to accommodate such requirements. It would however cost more though.

Just to re-emphasise, removing TLS 1.0 from the Load Balancer will not make you PCI compliant because of the nature of shared cloud infrastructure, one other important aspect of compliance is to ensure that payment information is tokenised. For instance one alternative that is available to you, so that you could continue to use the cloud as you are and be PCI compliant without making too many large changes, is to use a 3rd party payment gateway service, and tokenisation, that way you should satisfy the compliance, without having to move your website infrastructure. Worldpay and paypal are examples of payment gateways.

I hope this helps clarify PCI compliance on the public rackspace cloud, and how to do it right. Use a 3rd party internet gateway, if you really must keep your ecommerce store on the public cloud.

Using SNI with Rackspace Cloud Load Balancer and adding upto 20 SSL Certificates on single LB

This is going to be a short and dirty documentation on how to add multiple SSL certificates to a Rackspace Load Balancer.

1. Authorise with rackspace auth api (Get a token with user and api key credentials)
x-auth-key is apikey and x-auth-user is the mycloud username

curl -D - -H "x-auth-user: myusername" -H "x-auth-key: 1c989d8f89dfd87f3df3dff3d6f7fgf" https://auth.api.rackspacecloud.com/v1.0


HTTP/1.1 204 No Content
Server: nginx
Date: Thu, 19 Nov 2015 15:41:38 GMT
Connection: keep-alive
X-Storage-Token: AAA98345kdfg893DFGDF43iudng39dfgjkdfgDFI$JUIDFJGDFJGDFGDJJHDFGJHIfdg34dfgkdfjgiodfgiodfDFGDdg323
X-Storage-Url: https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_1001001
X-NewRelic-App-Data: PxQGUF9aDwETVlhSBQUP
X-CDN-Management-Url: https://cdn3.clouddrive.com/v1/MossoCloudFS_1001001
X-Auth-Token: AAA98345kdfg893DFGDF43iudng39dfgjkdfgDFI$JUIDFJGDFJGDFGDJJHDFGJHIfdg34dfgkdfjgiodfgiodfDFGDdg323
vary: Accept, Accept-Encoding, X-Auth-Token, X-Auth-Key, X-Storage-User, X-Storage-Pass, X-Auth-User
Cache-Control: s-maxage=86319
Front-End-Https: on

Now you can copy and paste the X-Auth-Token. It is needed for the next step

2. Configure the JSON file to upload an additional certificate and private key via API for a domain hostname. Here I am configuring domain.com

file: lb.json

{
  "certificateMapping": {
     "hostName": "domain.com",
     "certificate": "-----BEGIN CERTIFICATE-----\nMIIC/TCCAeWgAwIBAgIJAOjRMYJKDeryMA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV\nBAMMCmRvbWFpbi5jb20wHhcNMTUxMTE5MTQzMjE3WhcNMjUxMTE2MTQzMjE3WjAV\nMRMwEQYDVQQDDApkb21haW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAvHTjzWQchX+Gyl/No+ABR9R+F65rJmEPBEutjgWUynOir7ZYu5vmFol8\nhF054W5Xv3Ii4oYJjDJingOqQUBBxJD4jXx8H79y04JGXl8BBrG7azbRbowc4HoP\nRUiVTNaCPgYAGTreiRXmYKb/beotlGDvl0HQQLeDh4iq1X1E8R/lkFRHVAu0rEgC\nIeuJZ2L3Qu06A5yTCwdTJnZmviLmuDQtkfLDqTA8N67U8zjBgKGsj9t7GDSQ7zGp\n6JbTSJXqsXvd7XMLm2Ns2UelVUToxBTwgOIBn0XzZLCIOIlbIn0LHBk8oYEA4JDF\n1mXeqdsFOCtYvFcQBoUihiDjwDdTNQIDAQABo1AwTjAdBgNVHQ4EFgQU1wBZxNte\n9Q//UOl7ZMUvtsXghPEwHwYDVR0jBBgwFoAU1wBZxNte9Q//UOl7ZMUvtsXghPEw\nDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAUNM56u/cc56ESZY4gubX\nh0UQ8TjVbV2G4EkbBkNnm7RgNK48lFIxc55tshawhdN01JH5ZIgB1RvO1/lqouVs\nJrXwnPULBb4M5FcrjjBVu3bIvOjAUVDogOm7pKP/hJALM9CWMuZcXr5C+sYFczaB\nA7uDuMuQoTZBIGF1NyzfO7vmHT5QbEA/1ZYISWrVFNt8g2oxJY+jdgKacxVujWIs\nFpuiCCdvFVI05wCjj3C8BIN/EAcRIqe5gwr5oI+AtwK7fjK5K47/sREMI+W6Bj1w\nZEDz92S+dNtoSPJTBWiIQFLslTPiaDAu1EjJO1+YRXG7LANdxpQrogvDG1l9VpDW\nRg==\n-----END CERTIFICATE-----",
  "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAvHTjzWQchX+Gyl/No+ABR9R+F65rJmEPBEutjgWUynOir7ZY\nu5vmFol8hF054W5Xv3Ii4oYJjDJingOqQUBBxJD4jXx8H79y04JGXl8BBrG7azbR\nbowc4HoPRUiVTNaCPgYAGTreiRXmYKb/beotlGDvl0HQQLeDh4iq1X1E8R/lkFRH\nVAu0rEgCIeuJZ2L3Qu06A5yTCwdTJnZmviLmuDQtkfLDqTA8N67U8zjBgKGsj9t7\nGDSQ7zGp6JbTSJXqsXvd7XMLm2Ns2UelVUToxBTwgOIBn0XzZLCIOIlbIn0LHBk8\noYEA4JDF1mXeqdsFOCtYvFcQBoUihiDjwDdTNQIDAQABAoIBAQCSEJr7d0tv4P6s\n3gI5sIXtkXHFkwczcOi9sJYszICdRXDjdZZimpuD/j3HLaaN5gMWvDTzk2XVBrxO\nspKEDnSrEJ3Es6ZUyQMLkh5OSJ43/QtBNvSuFOTQy2oIjhBBxMSfo/DxnSIb6CBt\n6yFwpJ99MICioHzznAjSxId7/qKvq294emBGwpyP6JbCEtrM6rsnBO4J/uHUDLRj\nlU0zLFwFHNQnhnfIuxOoUZthyCSzZgUquC7C52qIPTZxqCydSi045pDoymn6pT43\n5YdafzWarmEqBGcyqDOyjOz01IEicrmFW7e2+DICIOTOvTSeFQtHbO4Rn2VE2V+x\nGNJY3DoFAoGBAORqB6gFlLUKBXdmP1VcEifjwcVtBaY9QwehbH8En6O0N1t5bKFx\nTBaShm2El+7UCeeSz9hx3vmV/4gn9amJnu6stOEUfjbfxe6mw8OtR13g5iSAI9TQ\nXesf1HoCrUsljzAPvBAKxWSQl9e6fYBxmB1IvFvd4n9uvoNWr/lOfbe3AoGBANM3\neddZYHBB0PhgiJ9aq7QkgqUSdv5JlBdtGdPDr3cpIx9QmXMtf+wc8vZ6CSvC3EIn\npADRt3QAIzxQLpXb3ADjBCwwsFCu27IXlVkvxD+yvqaLbAjB/LgbKqt5wR6YAarj\nDQzNzxhGvrCS+CvYSKospY6UK5+V0nuhuPVcuJRzAoGAAPHLTE+RmNoMwbyjgGfc\nD1wqvfVAc7qHH230c+YB/vxMyk0LPPOp++HpOmS0+CDaVaHOyDdYU7HiF58KrgPK\nq3P9X3zlNLbiK6V248VAqUu3x+jbvRKLgOBl0YdXThs+p1U5Utuoi0zpw9Oal0Bg\n/6YAWWTmfd5oXUSrf51qeasCgYEAgMahBZgbgTXPh6+rfKTWbQWZlbU1UYJgxQui\npIb5cwhkvpHwjNWf2cAorffnoYOzsK3kgw9Z72KqGPq1/G5Iq0293Idu6DJEBkf0\nqaTC3SdIr9fvbUOApmsBz/xyrwl0ctDtwvG0IxP27UceAfVjEEYaRly2YB0DcJdA\nYnA+pVsCgYEAoHfkw/ZPmB7r8LesF0+N93AErJ/IiPoCBFNKijVDplzLQbMeWyxL\njcnFdq8vQT0Os4qzRNCR5QbMcprJIh4LC96OIlGWz5NhKCWbGsKxA8N7YoWGYy9Z\nmRkVP6peBU2cGdXRWjCrxkKR+uJM9BCG0Ix3BOPy29nWaCEl+5wjBEc=\n-----END RSA PRIVATE KEY-----"
  }

3. Call API to add certificatemapping json lb hostname configuration file. This just allows example.com to have SSL on the Load Balancer.
(you can add up to 20 Domains). It’s lots cheaper and not as hard as I might have initially thought!!

curl -v -H "X-Auth-Token: $TOKEN" -d @lb.json -X POST -H "content-type: application/json"  https://lon.loadbalancers.api.rackspacecloud.com/v1.0/1001001/loadbalancers/157089/ssltermination/certificatemappings

It’s also possible to update the Load Balancer Certificates via the API, please see https://developer.rackspace.com/docs/cloud-load-balancers/v1/developer-guide/#update-certificate-mapping for more information

4. Confirm the certificate mappings are added (please note 1001011 is the customer DDI and 157090 is the Load Balancer ID).

curl -v -H "X-Auth-Token: $TOKEN" -X GET https://lon.loadbalancers.api.rackspacecloud.com/v1.0/1001011/loadbalancers/157090/ssltermination/certificatemappings


< HTTP/1.1 200 OK
< Content-Type: application/json
< Via: 1.1 Rackspace Cloud Load Balancer API v1.25.11 (Repose/2.11.0)
< Content-Length: 83
< Date: Thu, 19 Nov 2015 15:49:24 GMT
* Server Jetty(8.0.y.z-SNAPSHOT) is not blacklisted
< Server: Jetty(8.0.y.z-SNAPSHOT)
<
* Connection #0 to host lon.loadbalancers.api.rackspacecloud.com left intact
{"certificateMappings":[{"certificateMapping":{"id":999,"hostName":"domain.com"}}]}

You may note that the lb.json file has the certificate all on one line! how to do this? It's not that hard. Here is how I did it:

cat domain.com.cert | sed ':a;N;$!ba;s/\n/\\n/g'
cat domain.com.key  | sed ':a;N;$!ba;s/\n/\\n/g'
-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAvHTjzWQchX+Gyl/No+ABR9R+F65rJmEPBEutjgWUynOir7ZY\nu5vmFol8hF054W5Xv3Ii4oYJjDJingOqQUBBxJD4jXx8H79y04JGXl8BBrG7azbR\nbowc4HoPRUiVTNaCPgYAGTreiRXmYKb/beotlGDvl0HQQLeDh4iq1X1E8R/lkFRH\nVAu0rEgCIeuJZ2L3Qu06A5yTCwdTJnZmviLmuDQtkfLDqTA8N67U8zjBgKGsj9t7\nGDSQ7zGp6JbTSJXqsXvd7XMLm2Ns2UelVUToxBTwgOIBn0XzZLCIOIlbIn0LHBk8\noYEA4JDF1mXeqdsFOCtYvFcQBoUihiDjwDdTNQIDAQABAoIBAQCSEJr7d0tv4P6s\n3gI5sIXtkXHFkwczcOi9sJYszICdRXDjdZZimpuD/j3HLaaN5gMWvDTzk2XVBrxO\nspKEDnSrEJ3Es6ZUyQMLkh5OSJ43/QtBNvSuFOTQy2oIjhBBxMSfo/DxnSIb6CBt\n6yFwpJ99MICioHzznAjSxId7/qKvq294emBGwpyP6JbCEtrM6rsnBO4J/uHUDLRj\nlU0zLFwFHNQnhnfIuxOoUZthyCSzZgUquC7C52qIPTZxqCydSi045pDoymn6pT43\n5YdafzWarmEqBGcyqDOyjOz01IEicrmFW7e2+DICIOTOvTSeFQtHbO4Rn2VE2V+x\nGNJY3DoFAoGBAORqB6gFlLUKBXdmP1VcEifjwcVtBaY9QwehbH8En6O0N1t5bKFx\nTBaShm2El+7UCeeSz9hx3vmV/4gn9amJnu6stOEUfjbfxe6mw8OtR13g5iSAI9TQ\nXesf1HoCrUsljzAPvBAKxWSQl9e6fYBxmB1IvFvd4n9uvoNWr/lOfbe3AoGBANM3\neddZYHBB0PhgiJ9aq7QkgqUSdv5JlBdtGdPDr3cpIx9QmXMtf+wc8vZ6CSvC3EIn\npADRt3QAIzxQLpXb3ADjBCwwsFCu27IXlVkvxD+yvqaLbAjB/LgbKqt5wR6YAarj\nDQzNzxhGvrCS+CvYSKospY6UK5+V0nuhuPVcuJRzAoGAAPHLTE+RmNoMwbyjgGfc\nD1wqvfVAc7qHH230c+YB/vxMyk0LPPOp++HpOmS0+CDaVaHOyDdYU7HiF58KrgPK\nq3P9X3zlNLbiK6V248VAqUu3x+jbvRKLgOBl0YdXThs+p1U5Utuoi0zpw9Oal0Bg\n/6YAWWTmfd5oXUSrf51qeasCgYEAgMahBZgbgTXPh6+rfKTWbQWZlbU1UYJgxQui\npIb5cwhkvpHwjNWf2cAorffnoYOzsK3kgw9Z72KqGPq1/G5Iq0293Idu6DJEBkf0\nqaTC3SdIr9fvbUOApmsBz/xyrwl0ctDtwvG0IxP27UceAfVjEEYaRly2YB0DcJdA\nYnA+pVsCgYEAoHfkw/ZPmB7r8LesF0+N93AErJ/IiPoCBFNKijVDplzLQbMeWyxL\njcnFdq8vQT0Os4qzRNCR5QbMcprJIh4LC96OIlGWz5NhKCWbGsKxA8N7YoWGYy9Z\nmRkVP6peBU2cGdXRWjCrxkKR+uJM9BCG0Ix3BOPy29nWaCEl+5wjBEc=\n-----END RSA PRIVATE KEY-----

Notice the extra \n's after the processing.

Don't be intimidated by the sed line, it just replaces the \n newline with the character \n instead, so the json file is easier to lay out the cert as a 'string'.

Important notes on SNI:

We know we can add certificate mappings on the Load Balancer.
the Load Balancer has been configured for Allowing secure and insecure traffic, Port 443. SSL is terminated at the load balancer. This is what is known as OFFLOADING, it just means the SSL encryption is seen at the load balancer. Behind the load balancer, there is no encryption between it and the server. This allows the SNI hostname to be forwarded to the server, without it being in an encrypted form within the TCP packet.

5. Now lets install apache2 and configure some virtualhosts, at the most basic level. This is for an example and not a perfect setup

apt-get update
apt-get install httpd
vi /etc/apache2/httpd.conf



ServerName example.com
Documentroot /var/www/example.com/html




ServerName domain.com
Documentroot /var/www/domain.com/html


mkdir -p /var/www/domain.com/html
mkdir -p /var/www/example.com/html
echo 'example.com page body testing' > /var/www/example.com/html/index.html
echo 'domain.com page body testing' > /var/www/domain.com/html/index.html
vi /etc/apache2/apache2.conf

add one line in the file like:

Include /etc/apache2/httpd.conf

I just like to configure apache2 this way.

/etc/init.d/apache2 restart

6. Confirm both websites are working thru LB with SNI

# Curl domain
$ curl domain.com
domain.com page body testing

# curl domain 2
$ curl example.com
example.com page body testing

# curl IP address
curl https://194.213.79.117
someotherdefaultpage

# what happened when curling the IP address? Well..There was no TCP servername/hostname forwarded in the header for SNI support to detect the domain x-forwarded-for

# Lets provide the header
curl https://194.213.79.117 -H "host: example.com"

Testing SSL on the hostnames

openssl s_client -connect domain.com:443
openssl s_client -connect domain.com:443 -host domain.com
openssl s_client -connect domain.com:443 -servername domain.com