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.
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.confserver {
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.confEnable the configuration by symbolically linking it
blog.example.com
sudo nano /etc/nginx/sites-available/blog.example.com.confserver {
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.confEnable the configuration by symbolically linking it
Restart Nginx
nginx -t && sudo systemctl restart nginxTest 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.
@— zone root, points at the IP address of their web serverwww.example.com— points at the IP address of their web serverblog.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
- User opens their web browser and navigates to
example.com - Computer makes a DNS query for
example.comand receives the IP from the name server - Format the HTTP Request
GET / HTTP/1.1
Host: example.com
Header: value
Header: value
- 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
- Web Server processes request
- The web server's network interface decapsulates the packet
- The destination port is
tcp/80and 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.htmlas the site root is defined as/var/www/website
- TCP/IP Networking
- The web server follows the same steps as mentioned above
- Returning the
index.htmldata back to the client
1. DNS
2. HTTP
Host: headerThe 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:
- The user opens their web browser and navigates to
blog.example.com - The computer makes a DNS query for
blog.example.comand gets the IP address from the name server - The HTTP request now contains the
Host: blog.example.comheader
GET / HTTP/1.1
Host: blog.example.com
Header: value
Header: value
- When the Nginx server receives the request, the
Host: blog.example.comheader matches the configuration in/etc/nginx/sites-enabled/blog.example.com.confwithserver_name blog.example.com;directive - The Nginx server returns
/var/www/blog/index.htmlto 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.
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
hostsfile is found at/etc/hosts - On Windows, it's found at
C:\Windows\System32\etc\drivers\hosts
sudo nano /etc/hostsEdit the hosts file on Linux
88.131.47.75 stage.example.comAdd the entry for stage.example.com to the hosts file
curl -k https://stage.example.comTesting connectivity with the curl command, more or less the same as typing the URL in a browser window
stage hostname and add it to their hosts file. More on that here.