Using Apache/Lighttpd, SSL on all vhosts with just one IP

For the Lighttpd part and potential problems with it see below.

Using Apache, SSL on all vhosts with just one IP

If you use the Apache Webserver with multiple namebased vhosts and one IP you can only use SSL on one vhost. Thats what the specification of SSL say.
Google didn't give any solutions of this problem, except the use of different ports or multiple IP's. So you have to get more public IP's or the simple use of https://host1.tld/ and https://host2.tld/, host1.tld and host2.tld have the same IP address, won't work, right? Wrong! There's a work around.

Enable mod_rewrite:
---schnipp---

LoadModule rewrite_module       /path/to/mod_rewrite.so
---schnapp---

Define your default SSL vhost:
---schnipp---

<IfDefine SSL>
  <VirtualHost _default_:443>
    DocumentRoot /path/to/defaultserver
    ServerName name.of.your.server
    ServerAdmin your@email.address
    ErrorLog /path/to/logs/ssl-error_log
    TransferLog /path/to/logs/ssl-access_log
    SSLEngine on
    SSLCertificateFile    /path/to/your/certificate/server.crt
    SSLCertificateKeyFile /path/to/your/key/server.key
    CustomLog /path/to/logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteCond %{HTTP_HOST}    ^.*host1.tld$
        RewriteRule  ^/(.*)$        /path/host1.tld/$1  [L]
        RewriteCond %{HTTP_HOST}    ^.*host2.tld$
        RewriteRule  ^/(.*)$        /path/host2.tld/$1  [L]
    </IfModule>

  </VirtualHost>
</IfDefine>
---schnapp---

Now your usual vhost:
---schnipp---

<VirtualHost host1.tld:80>
  ServerAdmin your@email.address
  DocumentRoot /path/host1.tld
  ServerName host1.tld
  ServerAlias www.host1.tld
  ErrorLog /path/to/log/host1.tld_log
  CustomLog /path/to/log/host1.tld-access_log combined
</VirtualHost>

<VirtualHost host2.tld:80>
  ServerAdmin your@email.address
  DocumentRoot /path/host2.tld
  ServerName host2.tld
  ServerAlias www.host2.tld
  ErrorLog /path/to/log/host2.tld_log
  CustomLog /path/to/log/host2.tld-access_log combined
</VirtualHost>
---schnapp---

Thats it. The trick is that you check on your default SSL vhost, to which server the browser want to connect. If the condition (https://host1.tld/ or https://host2.tld/ match, Apache loads internal the data of the host1.tld or host2.tld. Same happens with any other hostname like foobar.host1.tld. The RewriteCond check is a regular expression.

There are two negativ aspects about it. If you connect to https://host1.tld/, then all access will be logged in /path/to/logs/ssl-access_log and not in the corresponding host1.tld logfile. The second aspect is, that the certificate name don't match the name of the host you connect to. This will result in a browser warning.

If you want to have all access of host1.tld logged to your host1.tld and the reason why you need this https:// option is that https://host1.tld/ don't show the default server page (which will happen without this work around), then you can redirect all traffic from https://host1.tld/ to http://host1.tld/ via
---schnipp---

RewriteCond %{HTTP_HOST}    ^.*host1.tld$
RewriteRule  ^/(.*)$         http://host1.tld/$1  [L]
---schnapp---

It should be possible to use one certificate for more as one vhost. The certificate needs aliase for it. But AFAIR you need to be CA for it. This will solve the two here described problems and this page describes a fast work around.

You should label the certificate as "*.your_domain.tld". If you use this certificate with another domain.tld it will give you a warning. All subdomains under your_domain.tld will work without any warnings.

Another solution how to handle SSL Certificates for different domainnames on just one IP is descripted here.

Using Lighttpd, SSL on all vhosts with just one IP

Why writing about it with Lighttpd? Lighttpd supports this feature since I know it without any hacks like with Apache. This shows another time how much more advanced lighttpd is.
But the problem starts if you want to redirect (all) http requests to https. If you use:
$HTTP["host"] =~ "(^|www\.)host1.tld" {
	server.document-root = "/var/www/host1.tld"
	accesslog.filename = "/var/log/lighttpd/host1.tld-access.log"
	url.redirect = ( "^/" => "https://www.host1.tld/" )
}
The result is that you can reach www.host1.tld without a problem, but you will end in a loop. http and https reads the same hostname redirect option and both, http and https, requests will process it. Looks like http://www.host1.tld/ ⇒ https://www.host1.tld ⇒ https://www.host1.tld ⇒ ... and so on. The solution is using two hostdefinitons. Once for http (port 80) and http (port 443):
$HTTP["host"] =~ "^host-without-redirect.tld" {
	server.document-root = "/var/www/host-without-redirect.tld"
	accesslog.filename = "/var/log/lighttpd/host-without-redirect.tld-access.log"
}

$SERVER["socket"] == ":80" {
        $HTTP["host"] =~ "^host1.tld" {
                server.document-root = "/var/www/host1.tld"
                accesslog.filename = "/var/log/lighttpd/host1.tld-access.log"
                url.redirect = ( "^/" => "https://host1.tld/" )
        }
        $HTTP["host"] =~ "^host2.tld" {
                server.document-root = "/var/www/host2.tld"
                accesslog.filename = "/var/log/lighttpd/host2.tld-access.log"
                url.redirect = ( "^/" => "https://host2.tld/" )
		}
}
$SERVER["socket"] == "0.0.0.0:443" {
		[... usual ssl configuration ...]
        $HTTP["host"] =~ "^host1.tld" {
                server.document-root = "/var/www/host1.tld"
                accesslog.filename = "/var/log/lighttpd/host1.tld-access-ssl.log"
        }
        $HTTP["host"] =~ "^host2.tld" {
                server.document-root = "/var/www/host2.tld"
                accesslog.filename = "/var/log/lighttpd/host2.tld-access-ssl.log"
		}
}
usual hosts without redirects can stay outside. The biggest advantage compared to apache is the possibiltity to have two logfiles. One for http and another for https.
Another feature is the fact that you can put the document-root whereever you want, not based on the https root like with apache.

Certificates are the same problem like described in the end of the apache part.

uhrig.eu.org/unix/


$Id: index.html,v 1.12 2008-03-28 14:30:41 volker Exp $