Setting up a Reverse Proxy with Apache


Install the base package and enable at startup in any scenario, e.g. on CentOS,

yum install httpd mod_ssl openssl
service httpd start
chkconfig httpd on

on Ubuntu,

    apt install apache2 openssl libapache2-mod-gnutls

enable paranoid dns checks so the logs actually tells you who’s accessing the server,

cd /etc/httpd/conf/
cp -pi httpd.conf httpd.conf.dist
vi httpd.conf

HostnameLookups Double

disable a few default confs, e.g.,

cd /etc/httpd/conf.d/
mv welcome.conf welcome.conf.disabled

note. it may come back when updating the apache package so if it does, rather edit the file and comment out the shit.

note. same for the ssl.conf, keep it named like that or it might come back after an update.


service httpd restart


Make some handy symlinks for operations,

cd ~/
ln -s /etc/httpd/conf
ln -s /etc/httpd/conf.d


The certificates

See Preparing SSL certificates

Deploy & setup the certs

mkdir /etc/httpd/ssl/

Just in case one doesn’t have real certificates,

cd /etc/httpd/ssl/
openssl genrsa -out ca.key 2048 
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt


Deploy the officially delivered SSL certificate into e.g. /etc/httpd/ssl/ (RapidSSL, Trustico, whatever…) and check the perms (folder has 700, files have 400 all owned by root, apache restarts fine),

chmod 700 /etc/httpd/ssl/
ls 400 /etc/httpd/ssl/*
ls -alhF /etc/httpd/ssl/

Setup the certs include,

cd /etc/httpd/conf/
vi certs.conf

    Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains;"
    SSLEngine on
    SSLProtocol all -TLSv1 -SSLv2 -SSLv3
    SSLHonorCipherOrder on
    SSLCertificateFile /etc/httpd/ssl/certificate.crt
    SSLCertificateKeyFile /etc/httpd/ssl/certificate.key
    SSLCertificateChainFile /etc/httpd/ssl/issuer-concat-cert.crt

Note. SSLv2 and SSLv3 and TLSv1.0 are disabled! TLS v1.1 & v1.2 are allowed!

Allow wheeled users to read the apache logs on CentOS/RHEL,

chown -R root:wheel /etc/httpd/
chmod 750 /etc/httpd/
chmod 640 /etc/httpd/*

Setup a common config headers that globally enables SSL for all the vhosts (replacing the CentOS/RHEL ssl.conf template),

cd /etc/httpd/conf.d/
ls -lhF /usr/libexec/httpd-ssl-pass-dialog
ls -lhF /run/httpd/sslcache # will be created
ls -lhF /dev/urandom
vi 00ssl.conf

Listen 443 https

SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache  shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

Virtual hosts

Setup e.g. examplehost vhost, as root,

cd /etc/httpd/conf.d/
vi examplehost.ssl.conf

<VirtualHost *:80>
        ServerAlias examplehost
        Redirect /

<VirtualHost *:443>
        Include conf/certs.conf
        ServerName examplehost
        Redirect /

<VirtualHost *:443>
        Include conf/certs.conf

        ErrorLog logs/examplehost.ssl.error.log
        TransferLog logs/examplehost.ssl.access.log
        #CustomLog logs/examplehost.ssl.request.log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
        CustomLog logs/examplehost.ssl.request.log ssl_combined
        LogLevel warn

        ProxyRequests off
        ProxyTimeout 300

        <Proxy *>
                Order deny,allow
                Allow from all

        <Location />
                #Require ip ::1/128
                ProxyPass http://localhost:9001/
                ProxyPassReverse http://localhost:9001/

Note. on the Require line, adding IPv6 localhost just in case we are serving IPv6…

Reverse Proxy against an SSL service

Setup Apache SSLProxyEngine (reverse proxying an SSL enabled service): you need to add that in the vhost config,

SSLProxyEngine On

and eventually bypass the hostname mismatch caused by the container hostname which is not an fqdn and doesn’t match with the world-facing address,

Error during SSL Handshake with remote server


SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off


Ready to go

Make sure apache is up and running,

    netstat -antpe --inet --inet6 | grep LISTEN | egrep "80|443"
    service httpd restart
    (provide the pass phrase if there is one)
    netstat -antpe --inet --inet6 | grep LISTEN | egrep "80|443"

Check Check Check

Eventually check the quality of your SSL setup:

Additional Notes

Proxy modules:

Nethence | Pub | Lab | Pbraun | SNE Russia | xhtml