Search
Close this search box.

When is Nginx serving wrong virtual host (vhost) SSL certificate

Table of Contents

 

How to correctly setup SSL certificates with Nginx serving multiple https virtual hosts

 

Eager to serve valuable content from your new Linux SSD VPS server via multiple domains ?

You just deployed a new Linux VPS server in one of VPSie datacenters, optimized it’s security, installed nginx, mysql, php and you’ve got your SSL certificates ready.

After copying https virtual hosts configuration from an old nginx vps server or from the internet, you set up your virtual hosts as below:

Nginx SSL Virtual host 1


root@ubuntu-vps:/etc/nginx/conf.d# cat server1.conf
server {
        server_name server1.domain.com;
        #server_name server1.domain.com;
        server_tokens off;

        listen       10.1.1.60:443 ssl;
        ssl                  on;
        ssl_certificate      /etc/nginx/server1.pem;
        ssl_certificate_key  /etc/nginx/private.key;
        ssl_session_timeout  5m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:ECDHE-RSA-RC4-SHA:DHE-RSA-AES128-SHA;
        ssl_prefer_server_ciphers   on;
        ssl_ecdh_curve secp521r1;
        ssl_session_cache shared:SSL:10m;

        root /var/www/public_html/server1;
        index index.html index.htm;
}

Nginx SSL Virtual host 2


root@ubuntu-vps:/etc/nginx/conf.d# cat server2.conf
server {
        server_name server2.domain.com;
        server_tokens off;

        listen       443 ssl;
        ssl                  on;
        ssl_certificate      /etc/nginx/server2.pem;
        ssl_certificate_key  /etc/nginx/private.key;
        ssl_session_timeout  5m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:ECDHE-RSA-RC4-SHA:DHE-RSA-AES128-SHA;
        ssl_prefer_server_ciphers   on;
        ssl_ecdh_curve secp521r1;
        ssl_session_cache shared:SSL:10m;

        root /var/www/public_html/server2;
        index index.html index.htm;
}

Everything should be working. First you test https://server1.domain.com and you find that it is working properly (no warnings are displayed). When you check https://server2.comain.com you notice a warning in your browser:
Nginx serving wrong virtual host (vhost) SSL certificate

Why is nginx serving the public certificate for server1.domain.com when my browser requests server2.domain.com ?

Troubleshooting wrong https

virtual host certificate served by NGINX

 

Let’s confirm that the browser is correctly sending the Server Name Indication in clear text so that NGINX has a chance to look at the domain before actual encrypting/decrypting any data. We take a look at the hex format of the “Client Hello” SSL handshake packet sent by the browser to nginx, in tcpdump:


22:25:29.100189 IP 192.168.3.100.57413 > 10.1.1.60.443: Flags [P.], seq 1:209, ack 1, win 4117, options [nop,nop,TS val 626190298 ecr 540309], length 208
	0x0000:  4500 0104 84e8 4000 3f06 e6c2 c0a8 0364  E.....@.?......d
	0x0010:  0a01 013c e045 01bb e739 71fe 1a4d 0a0e  ...............S
	0x0040:  091a 6b0c 9463 6bc2 9987 7506 bd72 a40c  ..k..ck...u..r..
	0x0050:  005b 23e3 1f22 17ec 3026 055e 78d1 8800  .[#.."..0&.^x...
	0x0060:  0020 c02b c02f c00a c009 c013 c014 c007  ...+./..........
	0x0070:  c011 0033 0032 0039 002f 0035 000a 0005  ...3.2.9./.5....
	0x0080:  0004 0100 007e 0000 0017 0015 0000 1273  .....~.........s
	0x0090:  6572 7665 7232 2e64 6f6d 6169 6e2e 636f  erver2.domain.co   --> SNI
	0x00a0:  6dff 0100 0100 000a 0008 0006 0017 0018  m...............
	0x00b0:  0019 000b 0002 0100 0023 0000 3374 0000  .........#..3t..
	0x00c0:  0010 0021 001f 0568 322d 3134 0873 7064  ...!...h2-14.spd
	0x00d0:  792f 332e 3106 7370 6479 2f33 0868 7474  y/3.1.spdy/3.htt
	0x00e0:  702f 312e 3100 0500 0501 0000 0000 000d  p/1.1...........
	0x00f0:  0012 0010 0401 0501 0201 0403 0503 0203  ................
	0x0100:  0402 0202                                ….

We confirm that the packet from client to https server (destination port 443) contains server2.domain.com as the SNI.
And we take the same look at the “Server hello” TCP packet returned by the nginx https server:


22:30:28.182532 IP 10.1.1.60.443 > 192.168.3.100.57454: Flags [P.], seq 1:1346, ack 209, win 235, options [nop,nop,TS val 615080 ecr 626487909], length 1345
	0x0000:  4500 0575 6a13 4000 4006 fc26 0a01 013c  E..uj.@.@..&...<
	0x0010:  c0a8 0364 01bb e06e d775 08b5 5365 cf91  ...d...n.u..Se..
	0x0020:  8018 00eb d4b0 0000 0101 080a 0009 62a8  ..............b.
	0x0030:  2557 7265 1603 0300 4a02 0000 4603 0303  %Wre....J...F...
	0x0040:  a4f0 db9e e0da b40e 82c6 9125 5bca b516  ...........%[...
	0x0050:  e199 e450 1522 339c d201 f8dd d110 6100  ...P."3.......a.
	0x0060:  c02f 0000 1eff 0100 0100 000b 0004 0300  ./..............
	0x0070:  0102 0023 0000 3374 0009 0868 7474 702f  ...#..3t...http/
	0x0080:  312e 3116 0303 034e 0b00 034a 0003 4700  1.1....N...J..G.
	0x0090:  0344 3082 0340 3082 0228 0209 00df 5d29  .D0..@0..(....])
	0x00a0:  dac3 4bd0 f930 0d06 092a 8648 86f7 0d01  ..K..0...*.H....
	0x00b0:  010b 0500 3062 310b 3009 0603 5504 0613  ....0b1.0...U...
	0x00c0:  0241 5531 1330 1106 0355 0408 0c0a 536f  .AU1.0...U....So
	0x00d0:  6d65 2d53 7461 7465 3121 301f 0603 5504  me-State1!0...U.
	0x00e0:  0a0c 1849 6e74 6572 6e65 7420 5769 6467  ...Internet.Widg
	0x00f0:  6974 7320 5074 7920 4c74 6431 1b30 1906  its.Pty.Ltd1.0..
	0x0100:  0355 0403 0c12 7365 7276 6572 312e 646f  .U....server1.do  --> SSL certificate "Common Name"
	0x0110:  6d61 696e 2e63 6f6d 301e 170d 3135 3032  main.com0...1502
	0x0120:  3233 3230 3436 3531 5a17 0d31 3630 3232  23204651Z..16022
	0x0130:  3332 3034 3635 315a 3062 310b 3009 0603  3204651Z0b1.0...
	0x0140:  5504 0613 0241 5531 1330 1106 0355 0408  U....AU1.0...U..
	0x0150:  0c0a 536f 6d65 2d53 7461 7465 3121 301f  ..Some-State1!0.
	0x0160:  0603 5504 0a0c 1849 6e74 6572 6e65 7420  ..U....Internet.
	0x0170:  5769 6467 6974 7320 5074 7920 4c74 6431  Widgits.Pty.Ltd1
	0x0180:  1b30 1906 0355 0403 0c12 7365 7276 6572  .0...U....server
	0x0190:  312e 646f 6d61 696e 2e63 6f6d 3082 0122  1.domain.com0..”

You will notice that the server, indeed sends a certificate valid for server1.domain.com.

What can we troubleshoot further ?

Debug SSL certificate problem with OpenSSL s_client

If we confirm that remote https clients are sending correct SNI, let’s see what OpenSSL reports when initating an https connection to nginx on the localhost.

root@ubuntu-vps:/etc/nginx/conf.d# openssl s_client -connect localhost:443 -servername server2.domain.com
CONNECTED(00000003)
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = server2.domain.com
verify error:num=18:self signed certificate
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = server2.domain.com
verify return:1
---
Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server2.domain.com
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server2.domain.com

Note: The “-servername” directive sets the SNI in the “Client Hello” packets. It is added in recent versions of openssl.

So we have two situations: Remote clients accessing nginx server via https to IP 10.1.1.60 receive a certificate for server1.domain.com and localhost client receives certificate for server2.domain.com. In both situations server2.domain.com is requested.

The only obvious place is the virtual host configurations in nginx, specifically the “listen” lines:


root@ubuntu-vps:/etc/nginx/conf.d# grep listen *
server1.conf:        listen       10.1.1.60:443 ssl;
server2.conf:        listen       443 ssl;

The reason behind it is that server2 vhost configuration instructs nginx to server https over port 443, without specifying the IP address to serve it on. It looks like NGINX interprets this as listen to localhost when other https virtual hosts are configured for that specific IP address.

This nginx behavior can be rectified by either removing the IP from server1 vhost configuration or adding it to to server2 vhost configuration.

You can actually try those configuration on our platform in few minutes utilizing our PCS (Private Cloud Solution) which allows you to have VPSie(s) on a private network – NAT – Port forward – traffic control for inbound and outbound – multiple gateway IPs which you could use for the load-balancing and failover.

 

Possible Causes of Nginx Serving Wrong Virtual Host SSL Certificate

  1. Incorrect Configuration: One of the most common causes of Nginx serving the wrong virtual host SSL certificate is erroneous configuration. If the Nginx configuration file is not set up correctly, Nginx may not be able to identify the correct virtual host for the request.
  2. IP-Based Virtual Host: If the virtual host is configured based on the IP address rather than the domain name, Nginx may serve the SSL certificate associated with the IP address instead of the domain name.
  3. Outdated Cache: Sometimes, Nginx may serve the wrong SSL certificate due to an obsolete cache. If Nginx has cached the inaccurate SSL certificate for a domain name, it may continue to do that certificate even after the correct certificate has been installed.
  4. Incorrect Server Name: If the server_name directive in the Nginx configuration file needs to be set up correctly, Nginx may not be able to identify the correct virtual host for the request.

Advantages of Using Nginx for Serving Multiple Virtual Hosts with SSL Certificates

  1. High Performance: Nginx is designed to handle high-traffic websites and applications, making it a popular choice for serving multiple virtual hosts with SSL certificates.
  2. Easy to Configure: Nginx is easy to configure, and its configuration file is well-documented, making it easy for developers to set up and manage virtual hosts with SSL certificates.
  3. Reverse Proxy: Nginx can be used as a reverse proxy, allowing you to load balance traffic across multiple servers and improve the performance and availability of your website or application.
  4. Security: Nginx supports SSL/TLS encryption, ensuring that traffic between the server and the client is secure and cannot be intercepted or tampered with.

Disadvantages of Using Nginx for Serving Multiple Virtual Hosts with SSL Certificates

  1. Complexity: Configuring multiple virtual hosts with SSL certificates can be complex, especially if you are unfamiliar with Nginx configuration.
  2. Learning Curve: Nginx has a steep learning curve, and it may take some time to master its features and configuration options.
  3. Resource Usage: Nginx can consume significant system resources, primarily if you serve multiple virtual hosts with SSL certificates on a single server.

Conclusion

Serving multiple virtual hosts with SSL certificates using Nginx is a great way to improve your website or application’s performance, security, and availability. However, ensuring that Nginx is serving the correct SSL certificate for each virtual host is essential to avoid security warnings and errors for users.

If Nginx is serving the wrong virtual host SSL certificate, it is usually due to incorrect configuration, IP-based virtual host, outdated cache, or incorrect server name. To fix this issue, verify the design, use a domain-based virtual host, clear the cache, or restart Nginx.

Overall, Nginx is a powerful and flexible web server and reverse proxy server that can help you serve multiple virtual hosts with SSL certificates. While it may have a vertical learning curve and consume significant system resources, it offers high performance, easy configuration, and robust security features, making it a popular choice for hosting websites and applications.

How to install Node.js on Debian

SSL (Secure Sockets Layer) is a security protocol that enables encrypted transmission between a web server and a web browser. SSL ensures that all data transmitted between the two is encrypted and cannot be intercepted or tampered with by third parties. This is important for websites because it protects sensitive intelligence such as login credentials, credit card information, and personal data from being stolen or compromised.

Nginx supports SSL through the use of SSL certificates. SSL certificates are digital certificates that verify the identity of a website and enable SSL encryption. Nginx can be configured to serve SSL certificates for one or multiple virtual hosts.

A virtual host in Nginx is a way to host multiple websites or applications on a single server. Each virtual host has its configuration, including server name, document root, and SSL certificate.

To install an SSL certificate on Nginx, you first need to obtain a valid SSL certificate from a trusted Certificate Authority (CA). Once you have the certificate, you can configure Nginx to use it by adding the SSL configuration to the Nginx virtual host configuration file.

To configure Nginx to serve multiple virtual hosts with SSL certificates, you must create a separate virtual host configuration for each domain name and SSL certificate. Each virtual host configuration should include the SSL certificate, private key, server name, and document root.

The recommended SSL configuration for Nginx includes enabling SSL encryption, using a robust cipher suite, enabling HTTP Strict Transport Security (HSTS), and enabling OCSP stapling.

Make a Comment
Share on
Facebook
Twitter
LinkedIn
Print
VPSie Cloud service

Fast and Secure Cloud VPS Service

Try FREE
For a month

The First 1 orders gets free discount today! Try Sign up on VPSie to get a chance to get the discount.