NSX Load Balancer for HTTPS Name-based Virtual Hosting

Few of you all know I used NSX Load Balancer for Name-based Virtual Hosting in my home lab as I only got a single Public IP Address and I got a few websites that I would like to host. For example, this blog you are reading now is actually being hosted behind a NSX LB. Try resolving blog.acepod.com and nsx.acepod.com, they will both resolve to same IP address ie. 101.100.182.15 but when you access these URLs, they are actually different web servers. I used to do that with an apache proxy server but managing the config was rather painful. Since NSX Load Balancer was able to achieve that and it comes with a nice UI, why not? Of course, the other motivation of using NSX LB is for the benefit of my work, getting to know the inside-out of the NSX LB is always good.

Name-based Virtual Hosting for HTTP has been working well for me. I always wanted to find out whether that will work for HTTPS. Asking around my friends on this requirement ie. multiple https websites on the same port 443 and same IP Address seems possible. I was referred to Server Name Indication.

So lets see whether something like this will work for HTTPS. First I have to find some web servers internally that able to do https. I have been using this Turnkey debian LAMP for my NSX testing, so I will use them in this test.

Before testing HTTPS, let see the HTTP in action first. These are the individual web servers, accessing them directly with IP address.

Screen Shot 2017-07-25 at 5.35.27 PM

Lets now map dev2.acepod.com and dev3.acepod.com to the same IP address, which is 192.168.191.36 that has been configured on the NSX ESG as secondary IP Address.

Screen Shot 2017-07-25 at 5.38.38 PM

 

Screen Shot 2017-07-25 at 5.28.16 PM

 

OK. lets now access the web servers using their FQDN. Great! It works! NSX LB is now looking at the URL given and point it to the right pool.

Screen Shot 2017-07-25 at 5.40.41 PM

 

Well, if you are interested in the script that made this work. Here you go.

acl host_app11 hdr(Host) -i dev2.acepod.com

acl host_app12 hdr(Host) -i dev3.acepod.com

use_backend dev2acepod if host_app11

use_backend dev3acepod if host_app12

You will need use the Application Rule. After you create the Application Rule, you have to attach it to the Virtual Server.

Screen Shot 2017-07-25 at 5.43.39 PM

Screen Shot 2017-07-25 at 5.46.14 PM

Alright. Lets now get to the goal which is test out the HTTPS. Same test again, now with HTTPS.

Screen Shot 2017-07-25 at 5.33.10 PM

I’m going to write an application rule that is something similar but now I will use a different Pool. I will name the pool dev2acepod-https and dev3acepod-https.

Screen Shot 2017-07-25 at 6.03.35 PM Screen Shot 2017-07-25 at 6.03.43 PM

Screen Shot 2017-07-25 at 5.55.52 PM

Screen Shot 2017-07-25 at 5.52.55 PM

 

This is the Application Rule I used for HTTPS.

 

acl host_app21 hdr(Host) -i dev2.acepod.com

acl host_app22 hdr(Host) -i dev3.acepod.com

use_backend dev2acepod-https if host_app21

use_backend dev3acepod-https if host_app22

Next will be creating a Virtual Server and attach this Application Rule to it.

Screen Shot 2017-07-25 at 5.54.24 PM

Screen Shot 2017-07-25 at 5.55.12 PM

 

The final configuration looks like this.Screen Shot 2017-07-25 at 5.59.10 PM

 

OK. Let test it out. So, as you can see, it does not work. Different URL, but its still goes to the same pool. It uses the dev2acepod-https pool because I place it as the default pool.

Screen Shot 2017-07-25 at 6.04.29 PM

 

Lets now take away the default pool and see how it goes.

Screen Shot 2017-07-25 at 6.06.13 PM

 

Cannot even load.

Screen Shot 2017-07-25 at 6.07.00 PM

 

Conclusion is we have to use different secondary IP addresses for different https url. Then the next question is why would you use LB to do this, why not consider NAT?

The other thought is maybe the application rule does not work out this way. Will have to spend some time researching on the right application rule.

 

[25 July 2017 Update]

Alright, its the application rule after some researching here. So by changing to the following, it works!!!

mode tcp

tcp-request inspect-delay 5s

tcp-request content accept if { req_ssl_hello_type 1 }

use_backend dev2acepod-https if { req_ssl_sni -i dev2.acepod.com }

use_backend dev3acepod-https if { req_ssl_sni -i dev3.acepod.com }

Screen Shot 2017-07-25 at 6.37.24 PM

Screen Shot 2017-07-25 at 6.34.28 PM