In this small article I’ll instruct myself (and you too?) how to create a 2 way authentication (mutual authentication) SSL reverse proxy balancer gateway. This configuration is useful in any enterprise environment where it’s requested to separate clients, the frontend and the backend, and when the traffic between clients and the gateway, and between the gateway and the backends must be encrypted.
This also ensure the clients and the backends to be authentic, and avoids Man In The Middle attacks.
Since the reverse proxy is in the middle between the clients and the backends, it’s requested for the clients to send a known client certificate to the gateway (apache), so that the gateway can recognize them. This is done with X509 certificates.
For the same reason, each backend contacted by the gateway is requested to respond with a valid and known server certificate. This is also done with X509 certificates.
Generally, the clients and the backends will also check their peer’s (apache) certificate to be known and valid, so that if someone is going to impersonate the gateway, it will be found and will not be considered authentic.
To do so, we’ll use:
Everything is done with a simple and single virtualhost in apache to be included in httpd.conf.
A working example is given below (assumes apache to be installed in /opt/apache, working with IP 11.22.33.44 on port 443):
<VirtualHost 11.22.33.44:443>
# General setup for the virtual host
DocumentRoot “/opt/apache/htdocs”
ServerName 11.22.33.44:443
ServerAdmin hostmaster@yoursite.com
CustomLog “|/opt/apache/bin/rotatelogs /opt/apache/logs/ssl_request_%Y%m%d.log 43200” “%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \”%r\” %b”
ErrorLog “|/opt/apache/bin/rotatelogs /opt/apache/logs/error_%Y%m%d.log 43200”
CustomLog “|/opt/apache/bin/rotatelogs /opt/apache/logs/access_%Y%m%d.log 43200” combined# SSL CONFIGURATION – SERVER SIDE
# Enable SSL Server on this virtualhost
SSLEngine on
# Disable SSLv2 in favor of the more robust and secure SSLv3
SSLProtocol all -SSLv2
# List of supported cryptografic server cipher suites
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5# Apache server certificate
SSLCertificateFile “/opt/apache/conf/ssl/server.pem”
# Apache server private key
SSLCertificateKeyFile “/opt/apache/conf/ssl/key.pem”
# Apache server CA certificate (certificate of who released your server certificate)
SSLCertificateChainFile “/opt/apache/conf/ssl/ca.pem”
# Client’s CA certificates (list of certificates of who released your client’s certificates)
SSLCACertificateFile “/opt/apache/conf/ssl/ca.pem”
# It’s mandatory for apache to authenticate the client’s certificate
SSLVerifyClient require
# END OF SSL CONFIGURATION – SERVER SIDE# SSL CONFIGURATION – CLIENT SIDE
# Enable SSL Client on this virtualhost (the traffic to the backends can be encrypted)
SSLProxyEngine on
# Apache client CA certificate (certificate of who released your client certificate)
SSLProxyMachineCertificateChainFile “/opt/apache/conf/ssl/ca.pem”
# Apache client private key + client certificate (concatenated in a single file)
SSLProxyMachineCertificateFile “/opt/apache/conf/ssl/client.pem”
# Backends’ CA certificates (list of certificates of who released your backends’ certificates)
SSLProxyCACertificateFile “/opt/apache/conf/ssl/ca.pem”
# It’s mandatory for apache to authenticate the backends’ certificate
SSLProxyVerify require
# END OF SSL CONFIGURATION – CLIENT SIDE<FilesMatch “\.(cgi|shtml|phtml|php)$”>
SSLOptions +StdEnvVars
</FilesMatch>
<Directory “/opt/apache/cgi-bin”>
SSLOptions +StdEnvVars
</Directory>BrowserMatch “MSIE [2-5]” \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0# Define a load balancer worker to be used to balance the HTTPS traffic to three backends.
# The traffic between apache and the backends is encrypted
<Proxy balancer://httpslb>
# Define the first backend (https) with 2 way auth
BalancerMember https://192.168.1.11:443/ route=worker1 retry=10
# Define the second backend (https) with 2 way auth
BalancerMember https://192.168.1.12:443/ route=worker2 retry=10
# Define the third backend (https) with 2 way auth
BalancerMember https://192.168.1.13:443/ route=worker3 retry=10
</Proxy># Don’t send the “/balancer-manager” uri to the backends
ProxyPass /balancer-manager !
# Distribute the traffic (any url, since it is “/”) to the backends with round robin + cookie based session persistence
ProxyPass / balancer://httpslb/ lbmethod=byrequests stickysession=JSESSIONID</VirtualHost>
If the clients and the backends are configured to check the gateway (apache) certificates, this is considered to be a very secure configuration.
Enjoy!
The question is: how can I change the path of the JSESSIONID cookie for a web application deployed in tomcat, jboss, or any other AS, and served by an apache reverse proxy (ProxyPass on mod_proxy, or jkMount on mod_jk) to add a trailing slash?
The answer is in mod_headers module. This module supports perl regular expression that you can use to substitute a string with another on any HTTP header, on the request or on the response.
We may want to add a trailing slash (mypath/) to the JSESSIONID cookie path, for example for security reasons.
This is the correct way (apache >= 2.2.4):
Header edit Set-Cookie "^(JSESSIONID=.*; Path=/YOUR_APP_PATH)(.*)$" "$1/$2"
eg:
Header edit Set-Cookie "^(JSESSIONID=.*; Path=/jsp-examples)(.*)$" "$1/$2"
The first attribute defines the regular expression that matches against the string that must be edited (the SESSIONID header in this case), the second attribute is the expression of the new string (the sessionid with the path modified with a trailing slash). Note that the expression begins with ‘^‘ character (it means: the string must begin with).
This kind of regexp defines that each match pattern is enclosed into brackets, so the first match is anything that begins with “JSESSIONID=”, have some kind of sub string (.*), and then contains “; Path=/jsp-examples”.
The second match is anything on the right of the path (.*).
The second argument implies that the string is composed by the first match, a slash, then the second match. So we have a cookie called JSESSIONID with a trailing slash added in the path.
If you don’t understand perl regular expression well, I advice you to get deeper into it, because it’s very very very useful for any sysadmin. There is very good documentation in internet, try to google “perl regular expression examples”.
Apache httpd is a very good and powerful piece of code, and it’s generally possible to do anything you can thinking of. You have only to know where to search, and the manual is generally the right place.
Ciao, Dino.
Addresses are all on the same line!
XMR (Monero):
49ao1APy599ekbFRWCLgZw8CXKhUrke9
Q3GqjJBf9agG6NkHhQ3arxjbBmvYbBrm
ewEZas1Xvxngy6bivqx92nBZQzjq9LS
Thanks!