haproxy ACLs configuration - haproxy

I am trying to setup haproxy as a load balancer for Hashicorp Vault using ACLs. Basically, I what I am trying to do is satisfy
the following conditions. First, go to the server that is initialized, unsealed, and active (status code 200). If that server
does not exist, go to unsealed and standby server (status code 429). Lastly, check if servers are sealed.
I currently have the following configuration. Any advice would be greatly appreciated.
#---------------------------------------------------------------------
Hashicorp Vault Frontend
#---------------------------------------------------------------------
frontend vault_frontend
bind xxx.xxx.xxx.xxx:443
mode tcp
# ACLs
acl active_node_absent nbsrv(vault_active_node) lt 1
use_backend vault_standby_node if active_node_absent
# Options
option tcplog
default_backend vault_active_node
##############
#---------------------------------------------------------------------
Hashicorp Vault Backend
#---------------------------------------------------------------------
backend vault_active_node
mode tcp
balance roundrobin
# Options
option httpchk HEAD /v1/sys/health
http-check expect status 200
# Servers
server vault01.xxx.xxx.xxx vault01.xxx.xxx.xxx:8200 check check-ssl verify none
server vault02.xxx.xxx.xxx vault02.xxx.xxx.xxx:8200 check check-ssl verify none
backend vault_standby_node
mode tcp
balance roundrobin
# Options
option httpchk HEAD /v1/sys/health
http-check expect status 429
# Servers
server vault01.xxx.xxx.xxx vault01.xxx.xxx.xxx:8200 check check-ssl verify none
server vault02.xxx.xxx.xxx vault02.xxx.xxx.xxx:8200 check check-ssl verify none
backend vault_standby_node
mode tcp
balance roundrobin
# Options
option httpchk HEAD /v1/sys/health
http-check expect status 429
# Servers
server vault01.xxx.xxx.xxx vault01.xxx.xxx.xxx:8200 check check-ssl verify none
server vault02.xxx.xxx.xxx vault02.xxx.xxx.xxx:8200 check check-ssl verify none
backend vault_sealed_nodes
mode tcp
# Options
option httpchk HEAD /v1/sys/health
http-check expect status 503
# Servers
server vault01.xxx.xxx.xxx vault01.xxx.xxx.xxx:8200 check check-ssl verify none
server vault02.xxx.xxx.xxx vault02.xxx.xxx.xxx:8200 check check-ssl verify none

Related

Send real Host header for httpchk in HAProxy

I'm trying to make http (layer 7) checks to monitor backend state in HAProxy load balancer. I have 3 backends configured, each having it's own name. Current configuration looks like this:
backend apiservers
balance leastconn
mode http
option httpchk GET /healthz HTTP/1.0\r\nAuthorization:\ Bearer\ SOME_TOKEN_HERE
http-check disable-on-404
http-check expect rstring ^ok
server core1 core1.cloud:443 ssl check
server core2 core2.cloud:443 ssl check
server core3 core3.cloud:443 ssl check
The problem is I can't switch to HTTP/1.1 because I wasn't able to find a way to pass a real Host header with httpchk requests. Using some random dummy Host string may cause problems in the feature, so I need to pass the corresponding backend hostname to the Host header. Options like http-request add-header Host %[src] and http-send-name-header Host in the backend section seem not affect httpchk mechanism.
Any ideas?
Updated thanks to borellini.
Per the haproxy docs you can configure the header in the httpchk line. The example from the docs is:
# check HTTP and HTTPs services on a server.
# first open port 80 thanks to server line port directive, then
# tcp-check opens port 443, ciphered and run a request on it:
option httpchk
http-check connect
http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu
http-check expect status 200-399
http-check connect port 443 ssl sni haproxy.1wt.eu
http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu
http-check expect status 200-399
server www 10.0.0.1 check port 80
You should then be able to replace the host value with your variable and have it sent.

how to prevent 502 status code as response by haproxy as load balancer

I have 3 server:
server (A)= a nginx(port 80) as reverse proxy to kestler (5000 port)
server (B)= a nginx(port 80) as reverse proxy to kestler (5000 port)
server (C)= a HAProxy as load balancer for port 80 of server (A) and (B)
and server A & B are quite similar.
every things works very well and haproxy forwards requests to server (A) & (B), but if kestrel in one of servers (e.g. A) be killed, nginx respond 502 bad gateway error and haproxy not detect this issue and still redirect requests to it, and this is mistake! it must redirect requests to server (B) in this time.
global
log 127.0.0.1 local2 info
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
option redispatch
retries 3
timeout connect 5s
timeout client 50s
timeout server 50s
stats enable
stats hide-version
stats auth admin:admin
stats refresh 10s
stats uri /stat?stats
frontend http_front
bind *:80
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto:\ http
default_backend http_back
backend http_back
balance roundrobin
mode http
cookie SERVERID insert indirect nocache
server ServerA 192.168.1.2:80 check cookie ServerA
server ServerB 192.168.1.3:80 check cookie ServerB
How Can I resolve this issue?
thanks very much.
You are only checking whether nginx is running, not whether the application is healthy enough to use.
In the backend, add option httpchk.
option httpchk GET /some/path HTTP/1.1\r\nHost:\ example.com
Replace some path with a path that will prove whether the application is usable on that server if it returns 200 OK (or any 2xx or 3xx response), and replace example.com with the HTTP Host header the application expects.
option httpchk
By default, server health checks only consist in trying to establish a TCP connection. When option httpchk is specified, a complete HTTP request is sent once the TCP connection is established, and responses 2xx and 3xx are
considered valid, while all other ones indicate a server failure, including the lack of any response.
This will mark the server as unhealthy if the app is not healthy, so HAProxy will stop sending traffic to it. You will want to configure a check interval for each server using inter and downinter and fastinter options on each server entey to specify how often HAProxy should perform the check.

FTP Connection in the HAproxy

I use HAproxy for the first time. This is my HAproxy conf. file and everything works right without FTP connection.
Also, Installed pure-ftp on other guest servers, do I have to make a change in guest machines?
I can not access the servers via FTP.
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
#log loghost local0 info
maxconn 4096
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
#debug
#quiet
stats socket /var/lib/haproxy/stats
defaults
log global
mode http
option httplog
option dontlognull
retries 3
redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen stats
bind *:8080
mode http
option forwardfor
option httpclose
stats enable
stats show-legends
stats refresh 5s
stats uri /stats
stats realm Haproxy\ Statistics
stats auth hello:world
stats admin if TRUE
frontend MAIN
bind *:21
bind *:80
bind *:143
bind *:443
bind *:993
mode http
acl server1_URL hdr_dom(host) -i domain1.com
acl server2_URL hdr_dom(host) -i domain2.com
use_backend server1 if server1_URL
use_backend server2 if server2_URL
backend server1
mode http
server web-first 192.168.1.2:80
backend server2
mode http
server web-first 192.168.1.3:80
I tried this: it did not work
listen FTP :21,:10000-10250
mode tcp
server ftp01 192.168.1.2 check port 21
server ftp01 192.168.1.3 check port 21
What should I do for it?
Thank you.
You'll need to set the ForcePassiveIP setting in the pure-ftpd configuration file. It should be set to the ip of the frontend proxy. Also, make sure the PassivePortRange setting matches what you have in your HAproxy configuration.
The FTP protocol is not straightforward to proxy as it makes multiple connections, though doing it at the tcp layer ought to be okay.

Send request with self signed certificates to backend

The Haproxy documentation (http://cbonte.github.io/haproxy-dconv/1.7/intro.html#3.3.2) lists as a basic feature:
authentication with the backend server lets the backend server it's really the expected haproxy node that is connecting to it
I have been attempting to do just that and have been unable to. So here's the question:
How do I send a request off to a backend with self signed certificates for authentication. The front-end request that uses this backend, is just http.
Here's my haproxy.cfg file:
global
maxconn 4096
daemon
log 127.0.0.1 local0
defaults
log global
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5s
timeout client 15min
timeout server 15min
frontend public
bind *:8213
use_backend api if { path_beg /api/ }
default_backend web
backend web
mode http
server blogweb1 127.0.0.1:4000
backend api
mode tcp
acl clienthello req.ssl_hello_type 1
tcp-request inspect-delay 5s
tcp-request content accept if clienthello
server blogapi 127.0.0.1:8780
I eventually got this to start working. I believe what was throwing me off was the fact that after doing a haproxy -f <configFile> -st it didn't actually close the process like I thought it would. So, none of my changes/updates took. I kill -9 the tens of haproxy service and reran the command (haproxy -f ) and now it's working.
Now, this is a hypothesis, albeit one I am very confident in. I will still present my final configuration just in case someone will glean something from here. I used https://www.haproxy.com/doc/aloha/7.0/deployment_guides/tls_layouts.html. That link answers the question I had of "how do you authenticate to the backend using ssl" like the docs say you can.
global
maxconn 4096
daemon
log 127.0.0.1 local0
defaults
log global
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5s
timeout client 15min
timeout server 15min
frontend public
bind *:443
mode http
use_backend api if { path_beg /api/ }
backend api
mode http
option httplog
server blogapi 127.0.0.1:4430 ssl ca-file <caFile.Pem> crt <clientCert.pem> verify required

HAProxy redirect scheme not working as documented

I'm running HAProxy 1.4.24 behind LB. SSL terminates on LB. I want to redirect http requests to https. I have following config:
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
defaults
mode http
log global
option httplog
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
frontend httpIn *:7258
maxconn 100000
option forwardfor header x-forwarded-for
acl is_http hdr(X-Forwarded-Proto) http
redirect scheme https code 301 if is_http
default_backend app
backend app
balance roundrobin
cookie LBSTICKY insert indirect nocache httponly secure maxlife 8h
server app1 10.10.10.10:8080 cookie app1
server app2 10.10.10.11:8080 cookie app2
My problem is the line
redirect scheme https code 301 if is_http
which generates the following error when running haproxy -f /etc/haproxy/haproxy.cfg -c :
[ALERT] 026/210541 (8482) : parsing [/etc/haproxy/haproxy.cfg:67] : 'redirect' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was 'scheme').`
I rechecked documentation which says I'm using correct syntax for redirect. Any ideas?
redirect scheme is indeed not available in HAProxy 1.4.24. Right now, it is available in HAProxy 1.5-dev13 and newer as well as in HAProxy 1.4.25 and newer, including the haproxy-1.4 master.
The documentation you had a look at was probably the one by Cyril Bonté which currently is generated from the 1.4 master, not the 1.4.24 release.
As such, you could either upgrade to one of the named versions or work around the limitation. A common workaround is to use redirect prefix like this
redirect prefix https://domain.com if is_http { hdr(host) -i domain.com }
This rule has to be enumerated for each hostname where you want the redirect to happen.
This option is available on HAProxy 1.5...
You have to use redirect location in 1.4 branch for this purpose.
Baptiste