Skip to content

Instantly share code, notes, and snippets.

@haproxytechblog
Last active January 9, 2025 23:04
Show Gist options
  • Select an option

  • Save haproxytechblog/5983bba177ee8a8722563d9828f2b617 to your computer and use it in GitHub Desktop.

Select an option

Save haproxytechblog/5983bba177ee8a8722563d9828f2b617 to your computer and use it in GitHub Desktop.
Reviewing Every New Feature in HAProxy 3.1
log-profile syslog
log-tag "haproxy"
on close format "$HAPROXY_HTTP_LOG_FMT"
log-profile json
on close format "%{+json}o %(client_ip)ci %(client_port)cp %(request_date)tr %(frontend_name)ft %(backend_name)b %(server_name)s %(time_to_receive)TR %(time_waiting)Tw %(time_to_connect)Tc %(time_server_response)Tr %(time_active)Ta %(status_code)ST %(bytes_read)B %(request_cookies)CC %(response_cookies)CS %(termination_state)tsc %(process_active_connections)ac %(frontend_active_connections)fc %(backend_active_connections)bc %(server_active_connections)sc %(retries)rc %(server_queue)sq %(backend_queue)bq %(request_headers)hr %(response_headers)hs %(request_line)r"
frontend mysite
bind :80
log 10.0.0.10:514 format rfc5424 profile syslog local0 info
log 10.0.0.11:9200 format raw profile json local0 info
log-profile syslog
on accept format "Client connected. IP: %ci"
on request format "Request received. %r"
on connect format "Connected to backend server. %b / %s"
on response format "Response received."
on close format "$HAPROXY_HTTP_LOG_FMT"
on error format "Error!"
frontend mysite
bind :80
log-steps all
log 10.0.0.10:514 format rfc5424 profile syslog local0 info
frontend mysite
bind :80
log 10.0.0.10:514 format rfc5424 profile syslog local0 info
acl is_evil_client req.hdr(user-agent) -m sub evil
http-request set-var(req.log_msg) str("Blocking evil client") if is_evil_client
http-request do-log
http-request deny if is_evil_client
log-profile syslog
log-tag "haproxy"
on close format "$HAPROXY_HTTP_LOG_FMT"
on http-req format "%[var(req.log_msg)]"
Blocking evil client
backend webservers
balance roundrobin
retry-on all-retryable-errors
retries 3
http-request set-retries 10 if { nbsrv(webservers) 1 }
server web1 172.16.0.10:80 check maxconn 30
server web2 172.16.0.11:80 check maxconn 30
server web3 172.16.0.12:80 check maxconn 30
frontend mysite
bind :80
bind :443 ssl crt /etc/haproxy/certs/example.com.pem ssl-min-ver TLSv1.3
bind quic4@:443 ssl crt /etc/haproxy/certs/example.com.pem ssl-min-ver TLSv1.3
http-response set-header alt-svc 'h3=":443"; ma=900'
http-request redirect scheme https unless { ssl_fc }
# Reject QUIC packets from IP range
quic-initial reject if { src 0.0.0.0/0 }
docker run -ti --rm alpine/curl-http3 curl -v -k --http3 -sI https://example.com
* Host example.com:443 was resolved.
* IPv6: (none)
* IPv4: 192.168.56.20
* Trying 192.168.56.20:443...
* connect to 192.168.56.20 port 443 failed: Weird server reply
* Trying 192.168.56.20:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
backend webservers
balance roundrobin
server web1 172.16.0.11:8080 check maxconn 30 init-state fully-down inter 5s fall 10 rise 10
echo "set server webservers/web1 state maint" | \
sudo socat stdio tcp4-connect:127.0.0.1:9999
echo "set server webservers/web1 state ready" | \
sudo socat stdio tcp4-connect:127.0.0.1:9999
frontend web
bind :80
# Set a variable here that lets you get the
# URL parameter 'target_server'
tcp-request content set-var(req.target_server) url_param(target_server)
# The filter configures the SPOA on each request
filter spoe engine my-spoa config /etc/haproxy/spoa.conf
# Get result from the SPOA
http-request set-header "ip_score" %[var(sess.myspoe.ip_score)]
# Requests continue to the 'web' backend
default_backend web
backend agents
mode tcp
balance roundrobin
option spop-check
# Try to read request variables - this does not work!
use-server agent1 if { var(req.target_server) -m str "agent1" }
use-server agent2 if { var(req.target_server) -m str "agent2" }
server agent1 agent1:12345 check inter 30s maxconn 30
server agent2 agent2:12345 check inter 30s maxconn 30
# Try to read request variables - this works!
use-server agent1 if { var(preq.target_server) -m str "agent1" }
use-server agent2 if { var(preq.target_server) -m str "agent2" }
log-format "%{Q}o %{-Q}ci - - [%T] \"TCP \" 000 %B \"\" \"\" %cp %ms %ft %b %s %Th %Tw %Tc %Tt %U %ts-- %ac %fc %bc %sc %rc %sq %bq \"\" \"\" "
backend servers
option httpchk
http-check send meth HEAD uri /health ver HTTP/1.1 hdr Host example.com
backend servers
option httpchk HEAD /health HTTP/1.1\r\nHost:\ example.com
backend servers
option httpchk HEAD /health HTTP/1.1 example.com
backend example
# send traffic on abstract namespace
server target_app abnsz@myname
frontend example
# receives traffic on abstract namespace
bind abnsz@myname
echo "debug counters all" | socat stdio tcp4-connect:127.0.0.1:9999
Count Type Location function(): "condition" [comment]
0 CHK ev_epoll.c:61 __fd_clo(): "tgid != tgrp && !thread_isolated()"
0 BUG ssl_sock.c:6236 ssl_sock_set_servername(): "!(conn->flags & CO_FL_SSL_WAIT_HS)"
0 CNT mux_h1.c:5104 h1_fastfwd(): "h1m->state < H1_MSG_DONE" [H1C ERROR before the end of the message]
[...]
dump ssl cert <certfile>
echo "echo 'expert-mode on; echo FDs from fdtab; show fd; echo wild FDs; debug dev hash fd'" | socat stdio tcp4-connect:127.0.0.1:9999
echo "show dev" | socat stdio tcp4-connect:127.0.0.1:9999
HAProxy version 3.1.0-f2b9791
Features
[...]
Build options
[...]
Platform info
[...]
Process info
pid: 8
cmdline: haproxy -W -db -f /usr/local/etc/haproxy/haproxy.cfg
boot uid: 0
runtime uid: 0
boot gid: 0
runtime gid: 0
boot capabilities:
CapEff: 0x00000000a80425fb
CapPrm: 0x00000000a80425fb
CapInh: 0x0000000000000000
runtime capabilities:
CapEff: 0x00000000a80425fb
CapPrm: 0x00000000a80425fb
CapInh: 0x0000000000000000
boot limits:
fd limit (soft): 1048576
fd limit (hard): 1048576
ram limit (soft): unlimited
ram limit (hard): unlimited
runtime limits:
fd limit (soft): 1048576
fd limit (hard): 1048576
ram limit (soft): unlimited
ram limit (hard): unlimited
echo "show env HAPROXY_UID" | socat stdio tcp4-connect:127.0.0.1:9999
HAPROXY_UID=haproxy
Name: HAProxy
Version: 3.1.0-f2b9791
Release_date: 2024/11/26
CurrStreams: 1
CumStreams: 22
BlockedTrafficWarnings: 0
traces
trace h2 sink stdout level user event +any verbosity clean start now
sudo journalctl --follow --unit haproxy
haproxy[39455]: [01|h2|1|mux_h2.c:1332] new H2 connection
haproxy[39455]: [01|h2|1|mux_h2.c:3384] rcvd H2 request : [1] H2 REQ: GET https://example.com/ HTTP/2.0
haproxy[39455]: [01|h2|1|mux_h2.c:6304] sent H2 response : [1] H2 RES: HTTP/1.0 200 OK
log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[fs.debug_str,when(!normal)]}"
172.18.0.1:49698 [05/Dec/2024:18:45:41.631] myfrontend webservers/s1 0/0/1/39/40 200 206 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1" dbg={ h1s=0x791735bcf080 h1s.flg=0x14010 .sd.flg=0x50404601 .req.state=MSG_DONE .res.state=MSG_DONE .meth=GET status=200 .sd.flg=0x50404601 .sc.flg=0x00034482 .sc.app=0x791735ae6400 .subs=0 h1c.flg=0x0 .sub=0 .ibuf=0@0+0/0 .obuf=0@0+0/0 .task=0x791735bbe400 .exp=<NEVER> conn.flg=0x80000300}
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[last_entity,when(error)]
global
# use as many FDs as possible but no more than 50000
fd-hard-limit 50000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment