Mar 132016
 

Adding SSL capabilities to HAproxy:

Add those into the global haproxy.config section:

        tune.ssl.default-dh-param 2048

        ssl-default-bind-options no-sslv3 no-tls-tickets
        ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA38
4:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA2
56:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-S
HA384: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:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA2
56: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-options no-sslv3 no-tls-tickets
        ssl-default-server-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA
384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SH
A256: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:DH
E-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SH
A256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CB
C3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA

and have a frontend for https:


frontend https-in
        bind *:443 ssl crt /etc/haproxy/ssl/private/qw2.org.pem
        reqadd X-Forward-Proto:\ https
        acl is_site1 hdr_end(host) -i www.qw2.org
        acl is_site2 hdr_end(host) -i www2.qw2.org
        use_backend site1 if is_site1
        use_backend site2 if is_site2

Note that the PEM file above is a concat of the ca.cer, qw2.org.cer and wq2.org.key I got via le via Let’s Encrypt.

To verify all is good, check this: https://www.ssllabs.com/ssltest/analyze.html?d=www.qw2.org

Mar 062016
 
Using HAProxy with Web Mirrors

Setting up dockerized webmirrors is easy with this


docker run -e web_source="http://www.theregister.co.uk/" -e port=3402 --expose=3402 -P --name=mirror_theregister -d hkubota/webmirror

and you’ll get a descent copy of The Register’s web page on port 3402. Thus access is via http://this.host:3402

Accessing would be nicer via a virtual hostname (e.g. theregister-mirror.this.host). That’s where HAProxy comes into play: as a reverse proxy. I found the basics here.

Here the complete start script:

#!/bin/bash
# Create a valid and usable configport_blog=`docker inspect mirror_haraldblog | jq -r '.[0].NetworkSettings.Ports."3401/tcp"[0].HostPort'`
port_reg=`docker inspect mirror_theregister | jq -r '.[0].NetworkSettings.Ports."3402/tcp"[0].HostPort'`

cat <~/haproxy/config/haproxy/haproxy.cfg
global
 user haproxy
 group users
 # Admin socket 
 stats socket /var/run/haproxy.sock mode 600 level admin 
 stats timeout 2m
 
 #daemon

 # 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).
#ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL

defaults
 log global
 mode http
 option httplog
 option dontlognull
 timeout connect 5000
 timeout client 50000
 timeout server 50000
 errorfile 400 /etc/haproxy/errors/400.http
 errorfile 403 /etc/haproxy/errors/403.http
 errorfile 408 /etc/haproxy/errors/408.http
 errorfile 500 /etc/haproxy/errors/500.http
 errorfile 502 /etc/haproxy/errors/502.http
 errorfile 503 /etc/haproxy/errors/503.http
 errorfile 504 /etc/haproxy/errors/504.http
 stats enable 
 stats uri /stats 
 stats realm Haproxy\ Statistics 
 stats auth admin:ADMIN_PASSWORD
 
frontend http-in
 bind *:80
 acl is_site1 hdr_end(host) -i www1.studiokubota.com
 acl is_site2 hdr_end(host) -i www2.studiokubota.com
 use_backend site1 if is_site1
 use_backend site2 if is_site2

backend site1
 balance first
 option httpclose
 option forwardfor
 server realblog harald.studiokubota.com:80 maxconn 32 check
 server mirrorblog studiokubota.com:${port_reg} maxconn 32 check
 stats admin if true
backend site2
 balance roundrobin
 option httpclose
 option forwardfor
 server s2 studiokubota.com:${port_blog} maxconn 32

listen admin
 bind *:1936
 stats enable
 stats admin if TRUE
_EOF_

docker run -v ~/haproxy/config:/config -p 80:80 -d -p 1936:1936 hkubota/haproxy

Via HAProxy you can access the mirrors via http://www1.studiokubota.com resp. another mirror at http://www2.studiokubota.com, which are much nicer to use.

This setup is probably something for docker-compose if this was one application.

Update 2016-05-03: Enable admin interface: disable/enable backend servers via http://host:1936/haproxy?stats