Send real Host header for httpchk in HAProxy - 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.

Related

haproxy ACLs configuration

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

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.

modify http response (not header) in haproxy

i want to make one website(lets say blocked.com) that is not accessible from my country to be accessible for my clients throue the custom url like notblocked.com using haproxy.
i have my haproxy box configured on the vps outside of the country. the main problem is,that website sending url redirection on the response body using javascript function and my clients getting redirected to the original web address.
how can i intersept the response body and change the domain name in the java scrip to my domain (notblocked.com) .
haproxy configuration
global
log 127.0.0.1 local0
maxconn 4000
maxsslconn 256
tune.ssl.default-dh-param 2048
daemon
uid 99
gid 99
defaults
log global
mode http
option httplog
option dontlognull
timeout server 5s
timeout connect 5s
timeout client 5s
stats enable
stats refresh 10s
stats uri /stats
frontend https_frontend
bind *:443 ssl crt /etc/ssl/certs/kstore.pem
no option http-server-close
mode http
default_backend web_server
http-request set-header Host blocked.com
backend web_server
mode http
balance roundrobin
server srv01 1.2.3.4:443 weight 1 maxconn 100 check ssl verify none
thanks

Haproxy ability for multiple port 80, 443 frontends

I have the need to have both layer7 and layer4. An api where i divert requests two 2 different backends. one backend for GET requests and one backend for PUT,GET & DELETE requests. That being my layer 7 front end.
The layer4 front to handle websites who make the api requests. They just split round robin.
Layer7 was working consistently before I add in this layer4 section, ie just did our loadbalancing for the api. As i migrate the websites w/ the layer4 frontend, api requests, ie layer7, get lost sometimes but not always.
As you can see, sometimes request is lost, sometimes works:
[richv#lb2 ~]$ curl api
curl: (52) Empty reply from server <-- this is not ok, http 503
[richv#lb2 ~]$ curl api
{"error_code":256,"error_message":"No Site specified"} <-- this is ok, cause didnt give all the headers.
Front ends are:
frontend layer7-http-listener
bind *:80
bind *:443 ssl crt /etc/httpd/certs/haproxy.pem
mode http
option httpclose
option httplog
option forwardfor
option accept-invalid-http-request
frontend layer4-listener
bind *:80 transparent
bind *:443 transparent
bind *:3306
mode tcp
option tcplog

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