Thumbnail image generated by Stable Diffusion Online with the prompt: a man searching for a gate leading to a server in the middle of a thousand servers.
Why?
Hostname spoofing is commonly used when you want to test the reachability of a service behind a reverse proxy or a load balancer. - Typically, this is done when you are testing a new server or a load balancer. For instance, let’s say you have service.example.com
pointing to lb.example.com
, and you want to test the behavior with a new load balancer called new-lb.example.com
. Instead of modifying your DNS to point to the new LB, you can employ hostname spoofing.
Hostname spoofing relies on setting the value of the HTTP Host header to indicate which VirtualHost (Apache) or Server block (nginx) the request should be routed to.
In our example mentioned above, if you want to reach service.example.com
via the new load balancer, you can use curl to set the Host header to service.example.com
.
|
|
Hostname spoofing with TLS/SNI?
Recently, I had to test out a scenario where I was moving traffic from one domain (service.example.com
) to another (service.example.net
). Both the domains were fronted by the same Load Balancer (lb.example.com - which is an AWS ALB), but the load balancer had a default certificate with the Common Name set to *.example.com
, with an additional certificate for *.example.net
. My goal was to test out the new additional certificate for *.example.net
was being used for the requests and ensure that an end-to-end connection could be established, receiving a response in return.
I started out by host spoofing with curl
|
|
Well, this failed. I thought the Host header would be sufficient, but clearly it wasn’t. I found out that Host header wouldn’t be used for SNI, and that SNI sends the hostname (as provided in the URL) during the TLS Handshake. I tried to search for “curl SNI” and found some posts and Super User/Stack Overflow answers but didn’t clearly explain how to get it to work. However, I came across this blog post by Claudio Kuenzler which talks about using OpenSSL to validate that the SNI certificate works, using the -servername
parameter.
Happy to see this, I tried it out:
|
|
Yay! Positive response. I was able to establish a connection with the new domain passed as the servername, and the correct certificate was used to validate the connection. The author, however, wasn’t able to test out using curl
since back then, curl had not yet released version 7.49.0. This version added the --connect-to
parameter that makes SNI connections much simpler to request.
The general structure of the command is :
|
|
Adapting this to our needs,
|
|
References
If you’re interested in reading more about TLS, TLS Handshake, SNI and more, I would recommend these articles:
- curl another host - Daniel Stenberg, maintainer of curl talks about what I did here with an added
resolve
command. - The Illustrated TLS 1.2 Connection - Michael Driscoll’s excellent illustrated explanation of TLS handshake process.
- The curious case of curl, SSL SNI and the HTTP Host header - Claudio Kuenzler