SslTerminating

The duty of this module is to offload HTTPS connections, and help our CaptchaHttp and WAF module to work properly with HTTPS requests. If you enable SslTerminating it will try to download and install bitninja-ssl-termination package to /opt/bitninja-ssl-termination, which is basically a HAProxy 1.8.9. We decided to build and publish our self-built HAProxy, because it will not depend on official repositories, and it will not interfere with other HAProxy installations and configurations. After installation succeeds, it will try to find currently active virtual hosts using HTTPS and extract any information which can be used to generate a valid haproxy.cfg. The module is responsible for collecting and generating pem files every 5 minutes, which can be used by bitninja-ssl-termination to offload HTTPS requests.

The module works with CaptchaHttp and WAF 2.0 modules. When a greylisted IP tries to connect to your server on 443 it will be redirected to bitninja-ssl-termination’s frontend. The CAPTCHA will appear, and the innocent visitor can solve it.

Certificate miners

To gather certificate information, SSL Terminating module currently uses three certificate miner implementations. These miners are: ApacheCertMiner, NginxCertMiner, LiteSpeedCertMiner.

A certificate miner implementation should consist of the following steps:
  • Collect the public key, the private key and the chain file for the SSL Certificate and put them in a pem file.
  • Put the newly created pem file location in /opt/bitninja-ssl-termination/etc/haproxy/cert-list-lst file, with every domain that belongs to this certificate, separated with spaces. Like this: /opt/bitninja-ssl-termintion/etc/haproxy/certs/example.com-ssl.pem example.com www.example.com *.example.com

An example bash implementation for DirectAdmin:

echo > /opt/bitninja-ssl-termination/etc/haproxy/cert-list.lst
for i in `ls /usr/local/directadmin/data/users/*/domains/* | grep ".key"  | awk -F "/" {'print $9'} | sed 's/\.[^.]*$//'` ;

 do

cat /usr/local/directadmin/data/users/*/domains/"$i".key /usr/local/directadmin/data/users/*/domains/"$i".cert > /opt/bitninja-ssl-termination/etc/haproxy/certs/"$i".pem
echo "/opt/bitninja-ssl-termination/etc/haproxy/certs/$i.pem $i www.$i *.$i" >> /opt/bitninja-ssl-termination/etc/haproxy/cert-list.lst

done

The Apache certificate miner tries to retrieve VirtualHost information using apache2ctl/apachectl/httpd -S (depending on the current OS). If this miner fails to find the apachectl binary, you can add it’s path to the config.ini webserver section with: apachectlBinaryLocation = ‘path/to/binary’

The Nginx certificate miner tries to retrive the main Nginx configuration file using nginx -V. It will follow includes and collect every virtual host using SSL certificates. If this miner fails to find your Nginx binary, you can add its path to the config.ini webserver section with: nginxBinaryLocation = ‘path/to/binary’ If you are using a different main configuration which was configured at Nginx build time, you can add your main configuration file to the config.ini webserver section with: nginxMainConfigFileLocation = ‘path/to/nginx.conf’

LiteSpeed certificate miner currently tries to parse the Apache main configuration file, follow includes and collect every virtual host using SSL certificates. If you are using a different main configuration file, you can add it to the config.ini webserver section with: apacheMainConfigFileLocation = ‘path/to/apache.conf’

Pattern certificate will be coming soon and it will be able to collect certificates with file patterns like: keyfiles= ‘path/to//domains/.key’ pemfiles= ‘path/to//domains/.pem’

CLI options

You can use CLI to enable and disable SslTerminating module with:

bitninjacli --module=SslTerminating --enabled
bitninjacli --module=SslTerminating --disabled

HAProxy configuration can be reloaded, if they were manually edited with:

bitninjacli --module=SslTerminating --reload

HAProxy configuration can be regenerated, if module configurations were edited:

bitninjacli --module=SslTerminating --regenerate

Configuration

The module can be configured in /etc/bitninja/SslTerminating/config.ini. This config file contains 9 config sections. The first two are for HAProxy and Apache binary settings. The other seven sections are for configuring different sections of the haproxy.cfg, if needed.

;
; SslTerminating module uses HAProxy 1.5.8. This section defines basic configurations.
;
[haproxy]
;; where is the haproxy binary
;binaryLocation='/opt/bitninja-ssl-termination/sbin/haproxy'
;; where should we look for haproxy config file
;configLocation='/opt/bitninja-ssl-termination/etc/haproxy/haproxy.cfg'
;; where could haproxy work
;workingDirectory='/var/lib/bitninja/SslTerminating'
;; where could SslTerminating put collected cert files
;certDir = '/opt/bitninja-ssl-termination/etc/haproxy/certs'
;; where is the cert list file
;certListFile = '/opt/bitninja-ssl-termination/etc/haproxy/cert-list.lst'
;; user for haproxy
;haproxyUser='bitninja-ssl-termination'
;; Https Captcha backend port
;haproxyPort = 60413
;; front end port
;httpsPort = 443
;; Captcha front and backend settings
;CaptchaFrontEndSettings[name]= 'Captcha-https'
;CaptchaFrontEndSettings[iface]= '*'
;CaptchaFrontEndSettings[port]= 60413
;CaptchaBackEndSettings[name]= 'Captcha-https-backend'
;; WAF front and backend setting
;; not used for now
;WafFrontEndSettings[name]= 'waf-https'
;WafFrontEndSettings[iface]= '*'
;WafFrontEndSettings[port]= '60414'
;WafBackEndSettings[name]= 'waf-https-backend'
;
; Web server settings
;
[webserver]
;; if binary location not set SslTerminating module tries to find where is apache.
;apachectlBinaryLocation = '/usr/sbin/apache2ctl'
;apachectlBinaryLocation = '/usr/sbin/httpd'
;apachectlBinaryLocation = '/opt/sp/apache/bin/apachectl'
;listVirtualHostParameter= '-S'
;nginxBinaryLocation = 'usr/local/nginx/sbin/nginx'
    ;nginxMainConfigFileLocation = '/etc/nginx/nginx.conf'
    ;apacheMainConfigFileLocation = '/etc/apache2/apache2'
;
; Haproxy global settings. Every ini key value will be converted to a haproxy configuration.
; E.g.: chroot = '/var/lib/bitninja/SslTerminating'
; Will be converted to:
;       chroot =        /var/lib/bitninja/SslTerminating
; If you want to add multiple values, use ini arrays.
; E.g.: log[] = '/dev/log       local0'
;    log[] = '/dev/log  local1 notice'
; This will be converted to:
;       log =   /dev/log local0
;       log =   /dev/log local1 notice
; See more about haproxy configuration at: https://cbonte.github.io/haproxy-dconv/1.5/configuration.html
;
[haproxyGlobalSettings]
;log[] = '/dev/log      local0'
;log[] = '/dev/log      local1 notice'
;chroot = '/var/lib/bitninja/SslTerminating'
;stats[] = 'socket /var/lib/bitninja/SslTerminating/admin.sock mode 660 level admin'
;stats[] = 'timeout 30s'
;user = 'bitninja-ssl-termination'
;group = 'bitninja-ssl-termination'
;; Default SSL material locations
;ca-base = '/etc/ssl/certs'
;crt-base = '/etc/ssl/private'

;; Default ciphers to use on SSL-enabled listening sockets.
;; For more information, see ciphers(1SSL). This list is from:
;;  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
;; An alternative list with additional directives can be obtained from
;;  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
;ssl-default-bind-ciphers = 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'
;ssl-default-server-ciphers = 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'
;ssl-default-bind-options = 'no-sslv3 no-tlsv10'
;tune.ssl.default-dh-param = 2048
;
; Haproxy default Settings
;
[haproxyDefaultSettings]
;log = 'global'
;mode = 'http'
;option[] = 'httplog'
;option[] = 'dontlognull'
;option[] = 'forwardfor'
;timeout[] = 'connect 5000'
;timeout[] = 'client  50000'
;timeout[] = 'server  50000'
;errorfile[] = '400 /opt/bitninja-ssl-termination/etc/haproxy/errors/400.http'
;errorfile[] = '403 /opt/bitninja-ssl-termination/etc/haproxy/errors/403.http'
;errorfile[] = '408 /opt/bitninja-ssl-termination/etc/haproxy/errors/408.http'
;errorfile[] = '500 /opt/bitninja-ssl-termination/etc/haproxy/errors/500.http'
;errorfile[] = '502 /opt/bitninja-ssl-termination/etc/haproxy/errors/502.http'
;errorfile[] = '503 /opt/bitninja-ssl-termination/etc/haproxy/errors/503.http'
;errorfile[] = '504 /opt/bitninja-ssl-termination/etc/haproxy/errors/504.http'
;
; Stat page setting. For security reason please Change uri, auth
;
[statPageSettings]
; Haproxy bind setting. Change it before enabling stat page.
;bind = '*:1936'
;mode = 'http'
;log = 'global'
;maxconn = 10
;timeout queue =  '100s'
;stats[] = 'enable'
;stats[] = 'hide-version'
;stats[] = 'refresh 30s'
;stats[] = 'show-node'
; Haproxy stat page auth setting. Change it before enabling stat page.
;stats[] = 'auth user:password'
; Haproxy stat page uri setting. Change it before enabling stat page.
;stats[] = 'uri  /haproxy?stats'
;
; Haproxy Captcha frontend settings.
; Don't use Haproxy bind configuration in thes section.
;
[CaptchaFrontEndSettings]
;option[]= "httpclose"
;reqadd = 'X-Forwarded-Proto:\ https'
;
; Haproxy Captcha backend settings
;
[CaptchaBackEndSettings]
;redirect = 'scheme https if !{ ssl_fc }'
;server= 'captcha-1 *:60412 check'
;
; Haproxy WAF frontend settings.
; Not used yet.
;
[WafFrontEndSettings]
;reqadd = 'X-Forwarded-Proto:\ https'
;default_backend = 'waf-https-backend'
;
; Haproxy WAF backend settings.
; Not used yet.
;
[WafBackEndSettings]
;redirect = 'scheme https if !{ ssl_fc }'
;server 'waf-1 *:60045 check'

Regenerating certificate information

If the SslTerminating is using expired certificate information on your server for some reason, you can regenerate the certificate information by running the following commands:

chmod +x /opt/bitninja/modules/Cli/scripts/force_recollect_ssl_certs.sh
/opt/bitninja/modules/Cli/scripts/force_recollect_ssl_certs.sh

This script contains the following commands, which you can also run manually, one after the other, if needed:

rm -f /opt/bitninja-ssl-termination/etc/haproxy/certs/*
rm -f /opt/bitninja-ssl-termination/etc/haproxy/cert-list.lst
rm -f /opt/bitninja-ssl-termination/etc/haproxy/haproxy.cfg
bitninjacli --module=SslTerminating --regenerate
bitninjacli --module=SslTerminating --reload