Skip to main content

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

You can make your custom cert miner as default. To use your custom certificate miner instead of the ConfigParser module:

  • Disable the useConfigParserModule variable and enable the allowCertListFileEditio option.
  • Move your certificate miner to the /etc/bitninja/SslTerminating/cert_miners/ directory.
  • Currently only BASH scripts are supported.
  • The script has to be a .sh file.
  • The owner of the script has to be ROOT

The cert miner will run automatically when the SslTerminating module is started or restarted.

ApacheCertMiner

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'

NginxCertMiner

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'

LiteSpeedCertMiner

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' and 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.

;
;
; Bitninja [SslTerminating] Module configuration file
;
;

;
; SslTerminating module uses HAProxy 1.5.8. This section define basic configurations.
;

[certificateMiner]
;useConfigParserModule=0
;
; Allow edition of the cert-list.lst file, when Certificate miners found any certificate.
; When Certificate miners fail to find any valid certificate, manually creation and mantaining the list file
; are not changed.
;
;allowCertListFileEdition=0

;
; Allow run of the Certificate finder cron, which runs every 5 minutes.
;
;allowCertificateFinderCron=1

; Certiicate miner need to read the webserver's configuration file which can be huge.
; We need to increase the module memory limit to avoid out of memory fatal errors.
; Memory limit value is in Mega bytes default. Default value is 2024 Mega byte (2Gb).
; The minimum value is 100 Mb.
;memoryLimit='2024'

[domainratelimit]
; Maximum requests per domain every 'perDomainRateLimitInterval' seconds (see below)
; If set to 0, rate limiting is disabled
; perDomainRateLimit = 0
; How many seconds should take before resetting the rate limit counter
; perDomainRateLimitInterval = 0

[general]
; Always generate haproxy configuration based on config.ini setting.
;generate_config_on_startup = 1

[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'

;
; 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 whan 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]
;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