_                      _             _ _
| |_ ___ _ __ _ __ ___ (_)_ __   __ _| | | ___   __ _
| __/ _ \ '__| '_ ` _ \| | '_ \ / _` | | |/ _ \ / _` |
| ||  __/ |  | | | | | | | | | | (_| | | | (_) | (_| |
 \__\___|_|  |_| |_| |_|_|_| |_|\__,_|_|_|\___/ \__, |
			                        |___/

Konfiguracja HAProxy dla HTTP oraz HTTPS

HAProxy jak podaje Wikipedia jest load-balancerem oraz serwerem proxy dla połączeń TCP oraz aplikacji HTTP. Dla mnie jest program, który zrobił robotę jeśli chodzi o hosting aplikacji internetowych na kontenerach. Bez HAProxy, aplikacje WWW na innych fizycznych serwerach musiały mieć odzielny publiczny adres IP. To się zmieniło, właśnie dzięki temu oprogramowaniu. Ten materiał pojawia się na "terminallog", bo jest o stricte jednym programie bez wskazania konkrenej platformy czy systemu operacyjnego.

Ja HAP-a konfigurowałem na Ubuntu 18.04 oraz 20.04. Jednak, tak jak już wspomniałem możemy sobie nawet go skonfigurować na OpenBSD. Mój wybór wtedy padł na Ubuntu, gdyż dopiero co zaznajomiłem się technologią kontenerów LXD.

Przejdźmy może już do konfiguracji. Ten materiał będzie składał się w bardzo dużej części z listingów plików konfiguracyjnych oraz ich opisów. Takie informacje na szybko, bez zbędnej teorii.

Rozpoczniemy od proxy dla HTTP, poniżej znajduje się konfiguracja dostarczana wraz z pakietem.

global
	log /dev/log	local0
	log /dev/log	local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
	stats timeout 30s
	user haproxy
	group haproxy
	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). 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 ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:
	ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
	ssl-default-bind-options no-sslv3

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

Wartość opcji ssl-default-bind-ciphers złamano tylko i wyłączenie dla celów estetycznych strony.

Kolejny listing przestawia już gotową konfigurację HTTP

	global
	log /dev/log	local0
	log /dev/log	local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
	stats timeout 30s
	user haproxy
	group haproxy
	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). 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 ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:
	ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
	ssl-default-bind-options no-sslv3

defaults
	log	global
	mode	http
	option	httplog
	option	dontlognull
	option	forwardfor
	option	http-server-close
        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

frontend www_front
	bind *:80
	acl host_stronya hdr(host) -i example.edu.pl www.example.edu.pl
	
	use_backend stronaa if host_stronya


backend stronaa
	http-request set-header X-Client-IP %[src]
	server stronaa 192.168.56.2:80 check

Wartość opcji ssl-default-bind-ciphers złamano tylko i wyłączenie dla celów estetycznych strony.

Więc, co się zmieniło względem konfiguracji bazowej? W konfiguracji domyślnej defaults zmieniono dwie opcje:

Dodano sekcję frontend. Zawiera ona opcje uruchomieniowe proxy takie jak port, na którym HAP ma nasłuchiwać oraz reguły, według których należy traktować spływające do usługi dane. Na przykład do jakiego serwera przekierować żądanie na konkretny adres. W przypadku proxy dla HTTP, wystarczą tylko poniższe opcje: Jeśli chodzi o HTTP, to tak naprawdę tyle. Ta konfiguracja powinna bez trudu działać.

Konfigurację HAProxy możemy przetestować przed uruchomieniem za pomocą poniższego polecenia:

$ sudo haproxy -f <ścieżka_do_pliku_konfiguracyjnego> -c

Użycie HAProxy dla HTTPS, wydaje się być jeszcze prostsze. Poniżej znajduje się listing konfiguracji dla HTTPS jednak w tym przypadku jest TCP/443.

global
	log /dev/log	local0
	log /dev/log	local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
	stats timeout 30s
	user haproxy
	group haproxy
	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). 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 ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:
	ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
	ssl-default-bind-options no-sslv3

defaults
	log	global
	mode	tcp
	option	tcplog
	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

frontend port443
	mode tcp
	bind *:443
	tcp-request inspect-delay 5s
	tcp-request content accept if { req_ssl_hello_type 1 }
	use_backend www if { req_ssl_sni -i www.example.edu.pl }
	use_backend www if { req_ssl_sni -i example.edu.pl }
	
backend www 
	mode tcp
	server www 192.168.56.2:443

Wartość opcji ssl-default-bind-ciphers złamano tylko i wyłączenie dla celów estetycznych strony.

Jeśli przyrównamy sobie konfiguracje dla HTTP oraz TCP (HTTPS), to pierwszą rzeczą, która będzie rzucać się nam w oczy będzie zmiana trybu w sekcji defaults

defaults
...
	mode tcp
	option tcplog
...

Z tej sekcji usunięto również opcje forwardfor oraz http-server-close, ponieważ są to ustawienia trybu http

W sekcji frontend nie ma już ACL-elek są warunki są używane bezpośrednio przez polecenie use_backend, więc po kolei:

Kolejnymi liniami tej sekcji są już polecenia use_backend, które przekazują żądania do konkretnego serwera na podstawie warunku. Tym warunkiem jest przypasowanie wartości SSL SNI do ciągu znaków (w tym przypadku www.example.edu.pl) bez rozróżniania wielkości znaków (flaga -i).

use_backend www if { req_ssl_sni -i www.example.edu.pl }

Po sekcji frontend występują już sekcje backend, wewnątrz sekcji znajduje się ustawienie trybu TCP oraz opcja server wraz z adresem IP oraz portem serwera.

backend www 
	mode tcp
	server www 192.168.56.2:443

To już jest wszystko co trzeba zrobić, aby skonfigurować HAProxy w podstawowy sposób. Te konfiguracje przedstawiają HAP-a jako proxy, które może zastąpić reverse-proxy lokalnie instalowane na serwerach przy pomocy NGINX czy Apache2. Wystarczy tylko skonfigurować aplikacje tak, aby nasłuchiwały na wszystkich interfejsach systemu.

~xf0r3m