Virtual Hosting Explained

In this post, I provide a detailed diagram and technical analysis on how name-based virtual hosting works by serving multiple websites from a single IP address.
Virtual Hosting Explained
In: Web, Computer Networking

A Very Brief History

In the early days of the world wide web — before IPv4 address exhaustion was a concern — a web site would be running on a single IP address. So, one IP address per website. Not only is this a concern for IPv4 exhaustion, but it's also not a very efficient use of server infrastructure and resources.

As the Internet — and the web by extension — became more commoditized, more individuals were setting up websites to share information with the world. Also among the mix, were hosting providers giving space for people to create a website without the need for a personal server of their own.

The idea now is that you'd have many websites on a single IP address. But, this begs the question, "How is this possible?". The answer is virtual hosting and it's not as complicated as it sounds.



Many Websites, One IP Address

The answer lies in the fundamentals of TCP/IP networking and where things happen at different layers.

  • IP-based virtual hosting — One host has many IP addresses
  • Port-based virtual hosting — One TCP port maps to one website
  • Name-based virtual hosting — Relies on application layer protocols
    • DNS
    • HTTP

In this post, we are going to be focusing name-based virtual hosting, as this is the version most in-use today.

⚠️
I've seen many confuse subdomains and virtual hosts and I want to be clear that these two things are very different.

Subdomains: A facet of DNS
Virtual Hosts: A facet of HTTP

One can exist without the other.

✅ You can create a DNS subdomain, but that doesn't guarantee the web administrator has created the virtual host.

✅ Likewise, you can create a virtual host, but that doesn't guarantee the system admin has created the DNS subdomain record.



Virtual Hosting Diagram


Click here to view this diagram in a new tab



Making Sense of the Diagram

1) SSH into Web Server and Create the Virtual Hosts

The IT administrator for Example Corp. logs into the web server and modifies the configuration for their web server. For this example, we'll say they're running Nginx.

example.com and www.example.com

sudo nano /etc/nginx/sites-available/example.com.conf
server {
   listen 80;
   server_name example.com www.example.com;
   root /var/www/website;
   index index.html;

   location / {
       try_files $uri $uri/ =404;
   }
}

server_name example.com www.example.com;

sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf

Enable the configuration by symbolically linking it


blog.example.com

sudo nano /etc/nginx/sites-available/blog.example.com.conf
server {
   listen 80;
   server_name blog.example.com;
   root /var/www/blog;
   index index.html;

   location / {
       try_files $uri $uri/ =404;
   }
}

server_name blog.example.com;

sudo ln -s /etc/nginx/sites-available/blog.example.com.conf /etc/nginx/sites-enabled/blog.example.com.conf

Enable the configuration by symbolically linking it


Restart Nginx

nginx -t && sudo systemctl restart nginx

Test the new configs and if no errors, restart the web server to load the new configs


2) Add the DNS Records

The IT administrator logs into the DNS provider for Example Corp. and modifies the example.com DNS zone.

  1. @ — zone root, points at the IP address of their web server
  2. www.example.com — points at the IP address of their web server
  3. blog.example.com — points at the IP address of their web server

The DNS records are published and should resolve within a matter of seconds to minutes.


3) Client Navigates to Site

example.com or www.example.com

  1. User opens their web browser and navigates to example.com
  2. Computer makes a DNS query for example.com and receives the IP from the name server
  3. Format the HTTP Request
GET / HTTP/1.1
Host: example.com
Header: value
Header: value

  1. TCP/IP Networking
  • The HTTP application data is encapsulated down into the transport layer
  • The transport layer is encapsualted down into the network layer
  • The network layer is transported down into the Ethernet frame
  • The packet is put on the wire and transported over many intermediate routers
  • The packet reaches the web server for example.com
  1. Web Server processes request
  • The web server's network interface decapsulates the packet
  • The destination port is tcp/80 and is passed on to Nginx
  • Nginx parses the HTTP data
  • The HTTP data contains Host: example.com
  • A valid configuration exists for this hostname at /etc/nginx/sites-enabled/example.com.conf
  • The server loads /var/www/website/index.html as the site root is defined as /var/www/website
  1. TCP/IP Networking
  • The web server follows the same steps as mentioned above
  • Returning the index.html data back to the client
💡
The key takeaways to what makes this work is:

1. DNS
2. HTTP Host: header

The client includes the DNS name in the Host: header and since the Nginx server has a valid configuration with that server_name directive, the resource is loaded from the identified site root.

blog.example.com

The process is exactly the same as above except:

  1. The user opens their web browser and navigates to blog.example.com
  2. The computer makes a DNS query for blog.example.com and gets the IP address from the name server
  3. The HTTP request now contains the Host: blog.example.com header
GET / HTTP/1.1
Host: blog.example.com
Header: value
Header: value

  1. When the Nginx server receives the request, the Host: blog.example.com header matches the configuration in /etc/nginx/sites-enabled/blog.example.com.conf with server_name blog.example.com; directive
  2. The Nginx server returns /var/www/blog/index.html to the user



What About the Stage Hostname?

You may have noticed in the web server, there is another virtual host for stage.example.com. But, this virtual host does not have a DNS record published in the example.com domain.

💡
If a user tried to open their browser and navigate to https://stage.example.com, then they would receive a DNS error that the hostname was not resolved. Which again, is because the DNS record is not publicly published in the example.com zone.

That begs the question, "If the virtual host exists, but the DNS record does not, how can people navigate to it in their web browsers?"

There are two possible solutions to this:

Example Corp. has an internal DNS server which resolves the hostname for people working in the office or connected to the VPN.

✅ A user could modify their hosts file to create a local DNS name if there are no DNS servers able to resolve the DNS query.

  • On Linux the hosts file is found at /etc/hosts
  • On Windows, it's found at C:\Windows\System32\etc\drivers\hosts
sudo nano /etc/hosts

Edit the hosts file on Linux

88.131.47.75        stage.example.com

Add the entry for stage.example.com to the hosts file

curl -k https://stage.example.com

Testing connectivity with the curl command, more or less the same as typing the URL in a browser window

ℹ️
From a security perspective, this just reinforces the point that obscurity is not security. Given a decent word list, a motivated attacker could easily discover the stage hostname and add it to their hosts file. More on that here.
Comments
More from 0xBEN
Ethical Hacking Learning Path
Ethical Hacking

Ethical Hacking Learning Path

In this blog post, I detail what I believe to be the ideal learning path and roadmap for the complete beginner, and those with little experience, looking to get into ethical hacking.
My CTF Methodology
CTF

My CTF Methodology

In this post, I examine the steps I take to approach a typical CTF in the form of a vulnerable target (also known as boot2root), and elaborate on steps at each phase.
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.