Redirectting to https using SSLrequireSSL

NB: this page is currently a work in progress!

Outline

When I host a web site I like to serve exactly the same tree via http and https however some parts of the tree should only be served via https. Apache has the SSLrequireSSL directive to prevent access to such pages via http.

Apache has RFC2817 support which negotiates TLS upgrade on an http connection, in my opinion this protocol should never be used but I present a method here to hook the apache RFC2817 support to redirect to the same page on the https site.

The result is when you use the SSLrequireSSL directive the end user is automagically re-directed to the https version of the page!

This replies on the http site having the following directive

SSLEngine optional

Basic scripts

I will dump the basic scripts here and come back and fill out the full guide later. NB: these docs are not yet complete

#Multi language and custom Error Documents - static files
mkdir /srv/httpd
cp -a /usr/share/apache2/error /srv/httpd/

#Place in the SSLrequireSSL redirect scripts
cat << 'EOFeofEOF' >/srv/httpd/error/HTTP_UPGRADE_REQUIRED.cgi 
#!/usr/bin/python

import os,sys

if os.environ.has_key('REDIRECT_SCRIPT_URI'):
    URL=os.environ['REDIRECT_SCRIPT_URI']
    if URL.startswith('http://'):
        NEWURL=URL.replace('http:','https:',1)
        print("Status: 303 See Other" )
        print("Location: %s"%NEWURL)
        print("Connection: close")
        print("Content-Type: text/html; charset=iso-8859-1")
        print("")
        print('<!--#set var="REDIRECT_STATUS" value="303" -->')
        print('<!--#include virtual="/error/HTTP_UPGRADE_REQUIRED.html.var" -->')
        sys.exit()

#If we get here things have gone wrong... so just 505 Internal Server Error
print("Status: 500 Internal Server Error" )
print("Connection: close")
print("Content-Type: text/html; charset=iso-8859-1")
print("")
print('<!--#set var="REDIRECT_STATUS" value="500" -->')
print('<!--#include virtual="/error/HTTP_INTERNAL_SERVER_ERROR.html.var" -->')
EOFeofEOF

chmod a+x /srv/httpd/error/HTTP_UPGRADE_REQUIRED.cgi 

cat <<'EOFeofEOF' >/srv/httpd/error/HTTP_UPGRADE_REQUIRED.html.var
Content-language: en
Content-type: text/html; charset=ISO-8859-1
Body:----------en--
<!--#set var="TITLE" value="Upgrade Required" -->
<!--#if expr="$REDIRECT_SCRIPT_URI = /^http:\/\/(.*)/" -->
  <!--#set var="refreshurl" value="https://$1" -->
<!--#endif -->
<!--#include virtual="include/top.html" -->
   The requested resource can only be retrieved using SSL. <!-- The server is
   willing to upgrade the current connection to SSL, but your client doesn't
   support it. Either upgrade your client, or --> Try requesting the page using
   https://
<!--#if expr="$refreshurl" -->
  <p>
  In 5 seconds you will be redirected to the https:// version: 
  <a href="<!--#echo encoding="url" var="refreshurl" -->">
    <!--#echo encoding="url" var="refreshurl" -->
  </a>
<!--#endif -->

<!--#include virtual="include/bottom.html" -->
----------en--
EOFeofEOF

#Fixup standard files also for SSLrequireSSL redirect
cp  /srv/httpd/error/contact.html.var /srv/httpd/error/include/
# edit /srv/httpd/error/include/top.html
#add the following 3 lined between <head> and <title>
 <!--#if expr="$refreshurl" -->
 <meta http-equiv="REFRESH" content="5;url=<!--#echo encoding="url" var="refreshurl" -->">
 <!--#endif -->
# edit /srv/httpd/error/include/bottom.html
#change reference to "../contact.html.var" to "./contact.html.var"

In http vhost

#Use "SSLEngine  Optional" but then catch 426 Upgrade status and use it to redirect 303 to https://
SSLEngine  Optional
SSLCertificateFile      /path/to/crt
SSLCertificateKeyFile   /path/to/key
SSLCACertificateFile    /path/to/intermediateCA.crt

Alias /error/HTTP_UPGRADE_REQUIRED.html.var /srv/httpd/error/HTTP_UPGRADE_REQUIRED.html.var
ErrorDocument 426 /error/HTTP_UPGRADE_REQUIRED.cgi

ErrorDocument 403 default