How Shared SSL Works

Limitations for web sites using Shared SSL

For the typical implementation of Shared SSL, a web site's data should follow these rules and limitations, many of which are good practices anyway, but some of which are not universal in all environments, or limit the functionality of your site or account.

  1. Never specify the scheme or domain name when linking to pages or objects within the site.
  2. Never use absolute URLs (that start with "/"). Know where in the hierarchy this file is, and use relative paths (starting with "../" if you need to reach a parent). This includes references to CSS files, Javascript files, <a>, <img>, <object>, <style>, <script>, <link>, <meta>, and <base> tags and anywhere else that might have an "href" or "src" or other attribute that has a URL as a parameter.
  3. Have only a single domain configured for your account.
  4. Don't use Apache's mod_rewrite rules, or equivalent features in other web servers.

OK, that said, an understanding of the techniques used to implement Shared SSL can help you overcome some of the above limitations in some circumstances, using careful programming.

Understanding the basic technique

SSL certificates are bound to a particular domain name. Therefore, in order to share an SSL certificate, you have to use the domain name of the certificate, which is not your domain name. If you want to use your domain name, and not see any other domain names, then you need to buy your own certificate, and use dedicated SSL. You probably also need a dedicated IP address to go along with the certificate, as it seems that SSL certificates are also bound to an IP address.

Most hosting companies implement Shared SSL by obtaining and configuring a certificate for their own domain, or a subdomain assigned to a particular shared hosting server. For ease of discussion, we will call this domain ssl.host.com, where "ssl" is arbitrary (may often be "secure" or "shared" or the computername of the server), and "host" is typically the name of the hosting company, and "com" may instead be "net" or some country-level substitution.

To discriminate among the domains served by the shared host, most hosting companies add to the username to their shared host name, producing a URL prefix such as https://ssl.host.com/~username/ — a technique that seems to have been borrowed from early multi-user web servers within an intranet, as it is a common Unix technique for finding the path to each user's account.

When the shared server gets a URL via https:, and it has a path starting with ~username, it turns those requests over to the account specified, and the configured path for that account.

The details of configuring a server to use shared SSL is beyond the scope of this article.

When can the scheme or domain name be specified?

This is probably the strictest limitation. If you specify the scheme or domain name for your "regular" domain, users that are accessing the site via the shared SSL will get serious-looking warning messages about security violations if a single page is composed of pieces accessed both via shared SSL and via normal http:. Telling people that it really is OK to ignore such warning messages is not only poor practice, but could become a full-time endeavor, so it really is best to omit (and thus inherit) the scheme and domain name for most URLs. There might be a few that specifically are intended for transitioning between the secure part of your site and the non-secure part of your site that would appropriately have the scheme and domain name. These should be destination HTML pages, and should probably include target="_top" just to help you notice situations where you think you want to make a security transation but not to the whole page... that is unlikely to be a good practice, as it would likely trigger a security warning for the user.

When can absolute URLs be specified?

The problem with absolute URLs in a shared SSL environment is that when accessed via the shared SSL scheme https://ssl.host.com/~username/resource-path, the top of the site starts after ~username/, but the concept of absolute URL starts before ~username/. So the use of an absolute URL such as /resource-path will cause the browser to chop off the ~username/ part of the URL, resulting in https://ssl.host.com/resource-path — a path using the shared SSL domain, but not specifying the ~username.

If you actually try to use an absolute URL, however, you will be pleasantly surprised to discover that they probably work! If you right click, and copy the link from the browser, and paste it in another browser tab or window, it probably won't work!

What actually happens is the https://ssl.host.com/resource-path cannot be routed by the shared SSL server, except if it also is passed an HTTP-REFERER header that contains the same server name, and also the ~username/ part. If that information is available, then it will borrow the ~username/ from the HTTP-REFERER, and send the browser a 301 redirect from https://ssl.host.com/resource-path to https://ssl.host.com/~username/resource-path. While this is almost like magic, it has a performance cost of extra server time to generate the redirect, and extra network latency to send it back to the browser, which will immediately send it (the revised request) back to the server again.

Using absolute URLs, then, isn't a great idea, although for using shared SSL on a single domain installation, it will be functional until you can search out and revise all those absolute URLs to relative URLs.

When can multiple domains or subdomains be used?

Multiple domains and subdomains are usually implemented in shared hosting servers by configuring each domain or subdomain in a subdirectory of the user's account. The first (primary) domain configured for a user (generally when the account is established, and generally cannot be reconfigured to a different domain) is configured at the root of the user's allocated web space (on Unix servers, sometimes ~username, sometimes ~username/public_html, sometimes ~username/www). When additional domains or subdomains are added to the account, they are usually, by default, configured in a subdirectory with the same name as the first part of domain or subdomain. This can cause conflicts or require restructuring of the original web site. Additional domains and subdomains are configured with their root (absolute URL path) pointing directly at their location, so using absolute paths can work... but only when the using URLs starting with the additional domain or subdomain, such as http://additional-subdomain.domain.com/.

Implementating additional domains and subdomains as subdirectories of the primary domain is a workable solution, but often permits access to the additional domain or subdomain not only from http://additional-subdomain.domain.com/ but also from http://domain.com/additional-subdomain/ — unless additional measures are taken to prevent that. It might even be possible to access the additional domain or subdomain using https://ssl.host.com/~username/additional-subdomain/ — but if that additional domain or subdomain uses absolute paths, it is beyond the magic of the shared web server to discriminate and fix those absolute paths.

A better solution would create sibling directories in a user's account for each domain and subdomain, whether primary or additional.

There is also the concept of aliased, or parked domains. These domains do not have their own directory (or subdirectory) structure, but instead point to the same directory (or subdirectory) as some other domain (or subdomain). Such domains generally work identically to the domain with which they share the directory structure, but are another reason not to use a scheme or domain name in internal URLs (limitation 1), except perhaps for very specific transition points.

Given the above, typical, implementation, with knowledge of the directory structure of the various domains, and with the avoidance of absolute URLs and URLs containing the scheme or domain name, it can be possible to construct a URL that will access the various domains via the shared SSL... but such URLs will be lengthy and expose the internal structure of the domains. Any restructuring of the domain and subdomain structure is likely to break saved shared SSL URLs. Whether this, or the structure exposed by the length of the URL, is problematic or not, depends on the site and its users, but it is certainly complex.

A better technique would be if the hosting company would use the configured domains and subdomains as a discriminant for the shared SSL server, instead of the user account. A URL such as https://ssl.host.com/~domain.com/ or https://ssl.host.com/~additional-subdomain.domain.com/ (with or without the "~") would avoid exposing the account's username to the users of the shared SSL server, and would avoid exposing the internal directory hierarchy of various domains in the site. It would also allow the workaround for absolute URLs (limitation 2), to work not only for the primary domain, but also for all additional domains and subdomains that are configured. Finally, it would give the actual domain or subdomain name being accessed a bit of visibility in the shared SSL URL. However, due to the widespread use of the current techniques, I don't expect them to change soon, if at all. Further, making shared SSL more user-friendly would reduce the number of sales of dedicated IP addresses and private SSL certificates.

It is possible, with clever programming, in the typical shared hosting implementation, to create a technique where URLs of the form https://ssl.host.com/~username/domain.com/ and https://ssl.host.com/~username/additional-subdomain.domain.com/ can be used, and also absolute URLs can be supported for each domain and subdomain using such URLs. The basic technique is to detect use of shared SSL (environment variable HTTPS) and rewrite the domain or subdomain name to the actual path when being accessed via shared SSL. If there is no domain or subdomain name, that would be an error, unless there is an HTTP_REFERER containing the domain or subdomain name. The HTTP_REFERER can help implement the absolute URL references, but note that there will now be two levels of redirection: the first from an absolute URL to one containing the ~username/ (done by the shared SSL server), and the second to also add in the domain or subdomain name (done by the clever programming).

When can mod_rewrite be used?

Actually, mod_rewrite can be used any time your hosting company uses an Apache web server, and the host has the module configured and enabled, which is usually. But there are some things to watch out for when using shared SSL, and some handy techniques for detecting and using the information.

The user or directory level .htaccess files are the ones generally available to the users of a shared hosting server. mod_rewrite is complex, and it is easy to make errors, and because turning on the mod_rewrite error log dramatically reduces the performance of the server most hosting companies prevent mod_rewrite error logging, making it very difficult to debug the rules. If you don't have a private Apache installation, there are some helpful techniques available.

Original URL

Here is some Python to recreate the original URL from the environment variables passed to a CGI script.
    host = os.environ.get("HTTP_HOST", "")
    if host == "":
        host = os.environ.get("SERVER_NAME", "")
        if host == "":
            host = os.environ.get("SERVER_ADDR", "")
    port = os.environ.get("HTTP_PORT", "")
    if port == "":
        port = os.environ.get("SERVER_PORT", "")
    if os.environ.get("HTTPS", '') == 'on':
        scheme = "https://"
        if port != "443":
            host += ":" + port
    else:
        scheme = "http://"
        if port != "80":
            host += ":" + port
    url = scheme + host + os.environ.get("REQUEST_URI", "/")