HaProxy - group tcp and http hosts dependent of each other - load-balancing

I have the following scenario:
Haproxy is running in front of my two groups of servers:
two http servers (active / backup)
two tcp servers (active / backup)
I now want to fail over from the active sides to the backup ones of ANY of the active services goes down (fail over HTTP and TCP at the same time).
Is there any way to do so in HAproxy? I so far was only able to fail over to one of them depending on the protocol but not both. Can these be grouped?
i was wondering if the can be done via ACLs and things like the fe_conn directive

I think haproxy's nbsrv works here. If your nbsrv count, number of healthy instances, falls below desired amount on EITHER pool switch both pools to the backup backend. Otherwise just use the default pool. Here is an example verified on 1.5.18 but should work fine on newer versions:
defaults all
timeout connect 30s
timeout client 30s
timeout server 30s
mode http
# http frontend
frontend http *:80
# use the backup service if EITHER service is down
acl use_backup nbsrv(http_service) lt 1
acl use_backup nbsrv(tcp_service) lt 1
use_backend http_service_backup if use_backup
default_backend http_service
# tcp frontend
frontend tcp_10000 *:10000
mode tcp
# use the backup service if EITHER service is down
acl use_backup nbsrv(http_service) lt 1
acl use_backup nbsrv(tcp_service) lt 1
use_backend tcp_service_backup if use_backup
default_backend tcp_service
backend tcp_service
mode tcp
# main tcp instance here
# can also include backup server here with backup directive if desired
server tcp-service1 tcp-service1.local:10000 check
backend tcp_service_backup
mode tcp
# backup tcp instance here
server tcp-service2 tcp-service2.local:10000 check
backend http_service
# main http instance here
# can also include backup server here with backup directive if desired
server http-service1 http-service1.local:80 check
backend http_service_backup
# backup http instance here
server http-service2 http-service2.local:80 check
See https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#nbsrv for more nbsrv details.

Related

Haproxy + TCP + SSL Passthrough + send-proxy

I am using the following Haproxy configuration to pass SSH connections to the backend servers.
global
log 127.0.0.1 local0
daemon
maxconn 2048
defaults
log global
timeout connect 500000ms
timeout client 86400s
timeout server 86400s
listen stats
bind :1936
mode http
stats enable
stats realm Haproxy\ Statistics
stats uri /
frontend front-ssh-servers
mode tcp
option tcplog
bind *:22
default_backend back-ssh-servers
timeout client 8h
backend back-ssh-servers
mode tcp
balance leastconn
stick-table type ip size 1m expire 8h
stick on src
server server1 X.X.X.X:22 check send-proxy
server server2 X.X.X.X:22 check send-proxy
server server3 X.X.X.X:22 backup send-proxy
The idea of adding send-proxy was to capture the actual client IP in the backend SSH servers. However, with send-proxy or send-proxy-v2, the connections are not reaching the destination backend SSH servers. Without the send-proxy option, the connections are reaching the backend SSH servers.
The Haproxy version is 1.8. Haproxy logs show the below.
2023-02-09T10:27:59-08:00 127.0.0.1 haproxy[3190902]: X.X.X.X:36730 [09/Feb/2023:10:27:59.175] front-ssh-servers back-ssh-servers/X.X.X.X 1/0/8 21 SD 2/1/0/0/0 0/0
The termination code is "SD". I read that proxy protocol also needs to be enabled at the backend hosts. Appreciate any help on how to achieve this for SSH connections. My backend hosts are running OpenSSH_7.4p1.

Openshift on VCenter UPI installation bootstrap not working

Trying to install openshift in vcenter. The bootstrap is booting up but not grabbing the bootstrap.ign from my web server.
set semanage fcontext public_content_rw_t on /var/www/openshift directory but I am getting
DEBUG Still waiting for the Kubernetes API: Get "https://api.cl.ops.local:6443/version": http: server gave HTTP response to HTTPS client
my haproxy server looks like this I am only testing with static IP addreses.
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# utilize system-wide crypto-policies
#ssl-default-bind-ciphers PROFILE=SYSTEM
#ssl-default-server-ciphers PROFILE=SYSTEM
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
listen stats
bind :9000
mode http
stats enable
stats uri /
monitor-uri /healthz
frontend api
bind *:6443
default_backend api
mode http
backend api
balance source
server bootstrap.cl.ops.local 192.168.61.22:6443 check
# server master0 192.168.61.23:6443 check
server master0.cl.ops.local 192.168.61.23:6443 check
server master1 192.168.61.24:6443 check
server master2 192.168.61.25:6443 check
mode http
frontend api-int
bind *:22623
default_backend api-int
mode http
backend api-int
balance source
server bootstrap.cl.ops.local 192.168.61.22:22623 check # Can be removed or commented out after install completes
server master0.cl.ops.local 192.168.61.23:22623 check
# server master0 192.168.61.23:22623 check
server master1 192.168.61.24:22623 check
server master2 192.168.61.25:22623 check
mode http
frontend secure
bind *:443
default_backend secure
mode http
backend secure
balance source
server worker0 192.168.61.65:443 check
server worker1 192.168.61.66:443 check
server worker2 192.168.61.67:443 check
mode http
frontend insecure
bind *:80
default_backend insecure
mode http
backend insecure
balance source
server worker0 192.168.61.65:80 check
server worker1 192.168.61.66:80 check
server worker2 192.168.61.67:80 check
mode h 14,3 11%

HAProxy with SSL passthrough to multiple domains with multiple backends

I need to setup a load balancer for all our applications.
At the moment all our applications are clustered (2-node appservers, and 1 apache on each node as well) and we do not have a LB so we just point our DNS alias to the first webserver of each node, making the second node useless (have to manually do a DNS switch in case of a failure of node1, and we don't have load balanced https queries).
Each application uses SSL with a specific domain & SSL certificate. we cannot accept to decrypt SSL and send unencrypted traffic to the backends as the LB might be located in another country etc. so we need to use passthrough.
Before anything, i just wanted to know if this is actually possible in HAProxy or not ?
I am talking about ~50 different applications. Our LB configuration would have to be HA so i guess we'll use something like keepalived with a shared VIP for HAProxy itself.
The setup would look like this i suppose :
domain-a.com-' '-> backend_dom_a -> 1.1.1.1 (app node1 dom a)
| | 1.1.1.2 (app node2 dom a)
domain-b.com-' '-> backend_dom_b -> 2.1.1.1 (app node1 dom b)
| | 2.1.1.2 (app node2 dom b)
domain-c.com-' '-> backend_dom_c -> 3.1.1.1 (app node1 dom c)
| | 3.1.1.2 (app node2 dom c)
domain-N.com-' '-> backend_dom_N -> 4.1.1.1 (app node1 dom N)
| | 4.1.1.2 (app node2 dom N)
+-> haproxy -+
Thanks for your support, best regards
FYI i'm using this configuration that works like a charm.
i have replaced the values in the files to hide our domains & hostnames, and limited the numbers of urls/backends but we have about 50 running now with the load balancer forwarding requests to many apache servers (and each apache forwards requests to tomcat servers behind)
feel free if you have any question
we use balance source to ensure session stickyness
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
daemon
user haproxy
group haproxy
log /dev/log local6 notice
log /dev/log local5 info
maxconn 50000
#chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode tcp
option tcplog
log global
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
#---------------------------------------------------------------------
# dedicated stats page
#---------------------------------------------------------------------
listen stats
mode http
bind :22222
stats enable
stats uri /haproxy?stats
stats realm Haproxy\ Statistics
stats auth <mylogin>:<mypass>
stats refresh 30s
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main_https_listen
bind <ip address>:443
mode tcp
option tcplog
log global
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
#---------------------------------------------------------------------
# Common HAProxy nodes configuration
#---------------------------------------------------------------------
# -------------------------------
# ACLs
# -------------------------------
acl acl_SIT_AT35073 req.ssl_sni -i <app_url1>.my.domain.net # SIT_AT35073 is just an internal code we use, but you can use any alias
acl acl_SIT_AT34305 req.ssl_sni -i <app_url2>.my.domain.net
acl acl_SIT_AT28548 req.ssl_sni -i <app_urlN>.my.domain.net
# -------------------------------
# Conditions
# -------------------------------
use_backend backend_SIT_AT35073 if acl_SIT_AT35073 # same here
use_backend backend_SIT_AT34305 if acl_SIT_AT34305
use_backend backend_SIT_AT28548 if acl_SIT_AT28548
#---------------------------------------------------------------------
# Backends
#---------------------------------------------------------------------
# APP 1
backend backend_SIT_AT35073
description APPNAME1
mode tcp
balance source
option ssl-hello-chk
server server_SIT_AT35073_1 <apache_server1>.my.domain.net:443 check
server server_SIT_AT35073_2 <apache_server2>.my.domain.net:443 check
# APP 2
backend backend_SIT_AT34305
description APPNAME2
mode tcp
balance source
option ssl-hello-chk
server server_SIT_AT34305_1 <apache_server3>.my.domain.net:443 check
server server_SIT_AT34305_2 <apache_server4>.my.domain.net:443 check
# APP N
backend backend_SIT_AT28548
description APPNAMEN
mode tcp
balance source
option ssl-hello-chk
server server_SIT_AT28548_1 <apache_server5>.my.domain.net:443 check
server server_SIT_AT28548_2 <apache_server6>.my.domain.net:443 check
I think you have two options:
pass the traffic through to the backend by using the TCP mode in haproxy frontend and backend. This has the benefit that your backend SSL certificate is passed through. Though you lose the possibility to have one SSL termination in your site. So I present you
Have one (usual) SSL certificate, acting as termination for your site and enable SSL between your backend and haproxy instance. This gives you the advantage that you still have only one entry point but different backends with unique certificates.
The second option might look like this:
frontend f_foo
bind :443 ssl crt /path/to/bundle
mode http
log global
use_backend b2_foo
backend be_foo
mode http
timeout connect 5s
server FOO address:port ssl check crt /path/to/client/bundle force-tlsv10 verify none
The drawback is that you need a client certificate for each backend server but that should be easily automatable.
AS more of an update answer for multi domain configs I use the below for routing different domains.
in the frontend is where you bind the port and add the certs which multiple have to be on the same line afaik.
frontend https_in
bind *:443 ssl crt /link/to/cert+key-file.pem crt /link/to/cert+key-file.pem
The acl host is where you specify the domain name and which backend to use based on that domain name.
acl host_example.com hdr(host) -i example.com
use_backend BACKEND_NAME if host_example.com
The backend where you specify the server that domain is running on.
backend BACKEND_NAME
mode http
option httpclose
option forwardfor
cookie JSESSIONID prefix
server server-name server-ip:443 check ssl verify none

HAPROXY roundrobin DNS on backend server domain

I have read allot of posts and tried several things, but can't seem to get what I want working and stable.
I have HAproxy setup as a pure proxy. The IP/domain of the HAproxy passes ALL to the backend server.
My issues is that the backend server domain has 2 IPs in DNS:
1.1.1.1
2.2.2.2
When the provider switches or removes an IP, HAproxy does not update to the "new" IP and gives a backend not reachable error in the logs:
Message from syslogd#localhost at Jul 18 16:15:02 ...
haproxy[3233]: backend b-http has no server available!
But there is a valid and working server on one of the ips. A restart which forces HAproxy to do a lookup normally fixes this, but I'd prefer for it to be automatic.
On HAproxy version haproxy-1.5.18 I have:
frontend f-http
bind :80
default_backend b-http
backend b-http
option forwardfor
server web-1 domain.com:80 check
I have tried on HAproxy version haproxy-1.7.8-1 I have:
resolvers public-dns
nameserver dns2 8.8.8.8:53
nameserver dns1 8.8.4.4:53
hold valid 10s
frontend f-http
bind :80
default_backend b-http
backend b-http
option forwardfor
server web-1 domain.com:80 resolvers public-dns check
As above dig on domain.com would return 2 A records. I'm thinking that there must be some config which will continue to check the IPs for a valid/working IP and start to use that one on the fly.
Any help is very much appreciated.

HAProxy health check in tcp mode on https 404 status code

I have two servers each running one Wildfly application server with one service available via https. The service is taking care of the https encryption. In front of the two servers I have an HAProxy as a load balancer in tcp mode to pass the ssl traffic through to the two services.
The HAProxy health check only checks if the server is online, not the service. If the service is not running Wildfly returns:
<html><head><title>Error</title></head><body>404 - Not Found</body></html>
which HAProxy interprets as healthy.
HAProxy config:
global
maxconn 2000
defaults
log global
mode http
option dontlognull
retries 3
option redispatch
timeout connect 5000
timeout client 10000
timeout server 10000
listen backend
bind *:8443
mode tcp
balance roundrobin
option httpclose
server backend1 wildfly:8443 check
server backend2 xxx.xxx.xxx.xxx:8443 check
How can I make HAProxy understand that 404 - Not Found is not healthy.
Two lines did the trick:
option httpchk /server
httpchk tells HAProxy to send an http request and check the response status
/server specifies the URI / Subdomain of my service
server backend1 wildfly:8443 check check-ssl verify none
check-ssl tells HAProxy to check via https instead of http
verify none tells HAProxy to trust the ssl certificate of the service (alternativly you can specify a .pem file)
Full HAProxy config:
global
maxconn 2000
defaults
log global
mode http
option dontlognull
retries 3
option redispatch
timeout connect 5000
timeout client 10000
timeout server 10000
listen backend
bind *:8443
mode tcp
balance roundrobin
option httpchk /server
server backend1 xxx.xxx.xxx.xxx:8443 check check-ssl verify none
server backend2 xxx.xxx.xxx.xxx:8443 check check-ssl verify none