I recently had to add an
SSL certificate to an
Apache web server (v2.2.4) that already had one certificate for a site running on port 443. That Apache server runs a couple of websites, each having its own domain name. Apache handles that situation thanks to
Name Based Virtual Hosts, a directive that allows it to run multiple domains on the same IP:port (obviously, port 80 for non-secured websites).
Toggle code [httpd.conf]
Listen 80
Listen 443
#...
NameVirtualHost 10.20.30.40:80
# ___________________________________________ REDIRECTS
<VirtualHost 10.20.30.40:80>
ServerName mycompany.com
Redirect 301 / http://www.mycompany.com/
</VirtualHost>
<VirtualHost 10.20.30.40:80 10.20.30.40:443>
ServerName brandone.com
Redirect 301 / http://www.brandone.com/
</VirtualHost>
# _______________________________________________ SITES
<VirtualHost 10.20.30.40:80>
ServerName www.mycompany.com
ServerAdmin me@mycompany.com
DocumentRoot C:/www/mycompany
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
# ________________________________________ SECURED SITES
<VirtualHost 10.20.30.40:443>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
SSLEngine On
SSLCertificateFile conf/ssl/bnrassurances.crt
SSLCertificateKeyFile conf/ssl/bnrassurances.key
SSLCACertificateFile conf/ssl/intermediate_bnr.crt
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
It would have been natural to think that it would work the same with SSL. Not at all, actually.... after a few unsuccessful attemps, I realized that it is not possible to secure two domains hosted on the same server, using the same IP and the same port. The reason is simple :
by design, SSL authentication is done before Apache can check the host name.
As a result, when you ask for a secured site on one IP:port, you always get served the
first matching virtual host of the Apache config,
no matter what domain you ask for.
I thought of four ways to solve that issue :
Run all secured areas under the same certificate
e.g. secure.mycompany.com serves secured content for brandone.com and brandtwo.com.
Toggle code [httpd.conf]
Listen 80
Listen 443
#...
NameVirtualHost 10.20.30.40:80
# ___________________________________________ REDIRECTS
<VirtualHost 10.20.30.40:80 10.20.30.40:443>
ServerName mycompany.com
Redirect 301 / http://www.mycompany.com/
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName brandone.com
Redirect 301 / http://www.brandone.com/
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName brandtwo.com
Redirect 301 / http://www.brandtwo.com/
</VirtualHost>
# ________________________________________________ SITES
<VirtualHost 10.20.30.40:80>
ServerName www.mycompany.com
ServerAdmin me@mycompany.com
DocumentRoot C:/www/mycompany
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName www.brandtwo.com
ServerAdmin me@brandtwo.com
DocumentRoot C:/www/brandtwo
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
# _________________________________________ SECURED SITES
<VirtualHost 10.20.30.40:443>
ServerName www.mycompany.com
ServerAdmin me@mycompany.com
DocumentRoot C:/www/mycompany
SSLEngine On
SSLCertificateFile conf/ssl/mycompany.crt
SSLCertificateKeyFile conf/ssl/mycompany.key
SSLCACertificateFile conf/ssl/intermediate_mycompany.crt
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
While that option would be convenient for non-commercial sites or intranet tools, it was out of the question, as brand names are very important to us.
Having clients redirected to a different domain when they have to pay online is not a smart idea, especially when they haven't noticed that mycompany owns brandone and brandtwo !
Use another port for the 2nd secured site
Toggle code [httpd.conf]
Listen 80
Listen 443
Listen 444
#...
NameVirtualHost 10.20.30.40:80
# ___________________________________________ REDIRECTS
<VirtualHost 10.20.30.40:80>
ServerName mycompany.com
Redirect 301 / http://www.mycompany.com/
</VirtualHost>
<VirtualHost 10.20.30.40:80 10.20.30.40:443>
ServerName brandone.com
Redirect 301 / http://www.brandone.com/
</VirtualHost>
<VirtualHost 10.20.30.40:80 10.20.30.40:444>
ServerName brandtwo.com
Redirect 301 / http://www.brandtwo.com/
</VirtualHost>
# ______________________________________________ SITES
<VirtualHost 10.20.30.40:80>
ServerName www.mycompany.com
ServerAdmin me@mycompany.com
DocumentRoot C:/www/mycompany
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName www.brandtwo.com
ServerAdmin me@brandtwo.com
DocumentRoot C:/www/brandtwo
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
# ____________________________________ SECURED SITES
<VirtualHost 10.20.30.40:443>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
SSLEngine On
SSLCertificateFile conf/ssl/brandone.crt
SSLCertificateKeyFile conf/ssl/brandone.key
SSLCACertificateFile conf/ssl/intermediate_brandone.crt
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:444>
ServerName www.brandtwo.com
ServerAdmin me@brandtwo.com
DocumentRoot C:/www/brandtwo
SSLEngine On
SSLCertificateFile conf/ssl/brandtwo.crt
SSLCertificateKeyFile conf/ssl/brandtwo.key
SSLCACertificateFile conf/ssl/intermediate_brandtwo.crt
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
That's what I did as a quick workaround : the 2nd site ran on port 444 for several weeks, but we knew some heavily firewalled people (don't laugh; some of them happen to have influence :/ ) couldn't reach the secured parts of the site.
As I know our host runs an advanced firewall, I phoned him and basically asked him if he could do host-based dispatching
before reaching Apache, by proxying HTTP requests like this :
brandone.com:443 ->firewall-> apache:85
brandtwo.com:443 ->firewall-> apache:86
The answer was that it was possible... however it would require a complex set up, and it would be impossible to reproduce the whole thing in our test and pre-production environments, which left me with a bad feeling.
Use another IP for the 2nd secured site
Toggle code [httpd.conf]
Listen 80
Listen 443
#...
NameVirtualHost 10.20.30.40:80
NameVirtualHost 10.20.30.41:80
# ___________________________________________ REDIRECTS
<VirtualHost 10.20.30.40:80>
ServerName mycompany.com
Redirect 301 / http://www.mycompany.com/
</VirtualHost>
<VirtualHost 10.20.30.40:80 10.20.30.40:443>
ServerName brandone.com
Redirect 301 / http://www.brandone.com/
</VirtualHost>
<VirtualHost 10.20.30.41:80 10.20.30.41:443>
ServerName brandtwo.com
Redirect 301 / http://www.brandtwo.com/
</VirtualHost>
# ______________________________________________ SITES
<VirtualHost 10.20.30.40:80>
ServerName www.mycompany.com
ServerAdmin me@mycompany.com
DocumentRoot C:/www/mycompany
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.40:80>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.41:80>
ServerName www.brandtwo.com
ServerAdmin me@brandtwo.com
DocumentRoot C:/www/brandtwo
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
# ___________________________________ SECURED SITES
<VirtualHost 10.20.30.40:443>
ServerName www.brandone.com
ServerAdmin me@brandone.com
DocumentRoot C:/www/brandone
SSLEngine On
SSLCertificateFile conf/ssl/brandone.crt
SSLCertificateKeyFile conf/ssl/brandone.key
SSLCACertificateFile conf/ssl/intermediate_brandone.crt
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
<VirtualHost 10.20.30.41:443>
ServerName www.brandtwo.com
ServerAdmin me@brandtwo.com
DocumentRoot C:/www/brandtwo
SSLEngine On
SSLCertificateFile conf/ssl/brandtwo.crt
SSLCertificateKeyFile conf/ssl/brandtwo.key
SSLCACertificateFile conf/ssl/intermediate_brandtwo.crt
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Directory />
Options FollowSymLinks
AllowOverride None
Order Deny,Allow
Allow from all
Satisfy all
</Directory>
#otherstuff
</VirtualHost>
Some of you might have already guessed : the smartest solution is to associate as many IPs to the web server as there are domains to secure. Hopefully, our host had extra IPs to
give sell us :)
modSSL FAQ
Apache v2.2 - Name virtual hosts
This post has been completed while listening to :
http://ff7.ocremix.org - Voices of the Lifestream (OCRemix community)