UDP load balancing

Check the health of UDP servers

This page applies to:

  • HAProxy Enterprise 2.8r1 and newer

The UDP module supports two ways to check the health of your backend servers. The default check sends a probe datagram and watches the socket error queue for ICMP Destination Unreachable replies. With send and expect actions, available since HAProxy Enterprise 3.4r1 and HAProxy ALOHA 18.5, the load balancer sends one or more probe datagrams and verifies that the server answers each probe with an expected response. The send and expect approach detects failures that the default check misses, such as a DNS resolver that is running but returns errors for every query, or a RADIUS server that accepts datagrams but rejects authentications because its database is down.

Default health check Jump to heading

With option udp-check and no udp-check directives, the load balancer sends a probe datagram to the server’s address and port. If the kernel reports an ICMP Destination Unreachable error for the probe, the server is marked as down. If no error arrives, the server is marked as up.

Because UDP has no connection handshake, a server that is running but not answering application traffic still passes this check. Firewalls on the path must also permit ICMP Unreachable messages to reach the load balancer. See the option udp-check reference for details.

Send and expect health checks Jump to heading

This section applies to:

  • HAProxy Enterprise 3.4r1 and newer
  • HAProxy ALOHA 18.5 and newer

You can define a sequence of udp-check directives that send probe datagrams and match the replies. The check passes only when every expect action matches a reply from the server within the check timeout. The udp-check directive gives you several ways to verify that the backend UDP server is up and running:

  • Send a string in a datagram with udp-check send, then check that the server returns a datagram with an expected string by using udp-check expect string <pattern>.
  • Expect the reply to contain a certain number of bytes by adding min-recv <n> to the expectation.
  • Send binary data with udp-check send-binary and match binary replies with udp-check expect binary <hexstring> or udp-check expect rbinary <regex>.
  • Invert a match by prefixing it with !, so that the check fails when the reply matches the pattern.

For the full list of supported arguments, status values, and sequence rules, see the Reference.

In this example, the load balancer sends the datagram ping-check every 2 seconds. The server is marked as up only when it replies with a datagram that contains the string pong within 1 second.

haproxy
udp-lb echo
dgram-bind 192.168.56.25:4000
timeout check 1s
option udp-check
udp-check send ping-check
udp-check expect string pong
server server1 10.10.10.10:4000 check inter 2s
haproxy
udp-lb echo
dgram-bind 192.168.56.25:4000
timeout check 1s
option udp-check
udp-check send ping-check
udp-check expect string pong
server server1 10.10.10.10:4000 check inter 2s

Example: send and expect binary data Jump to heading

This example sends a DNS A query for example.com and expects a reply that carries the same transaction ID as the query. The transaction ID is the first two bytes of the query, so the reply must begin with 0001:

haproxy
udp-lb dns
dgram-bind 192.168.56.25:53
timeout check 1s
option udp-check
udp-check send-binary 000101000001000000000000076578616d706c6503636f6d0000010001
udp-check expect rbinary ^0001
server ns1 10.10.10.10:53 check inter 2s
haproxy
udp-lb dns
dgram-bind 192.168.56.25:53
timeout check 1s
option udp-check
udp-check send-binary 000101000001000000000000076578616d706c6503636f6d0000010001
udp-check expect rbinary ^0001
server ns1 10.10.10.10:53 check inter 2s

Breaking down the probe datagram:

Bytes Meaning
0001 Transaction ID
0100 Flags: recursion desired
0001 One question
0000 0000 0000 Zero answer, authority, and additional records
07 6578616d706c65 03 636f6d 00 QNAME: example.com
0001 QTYPE: A
0001 QCLASS: IN

Services that never reply Jump to heading

Some UDP services discard probe datagrams and never reply, for example a syslog collector used with proxy-responses 0. An expect rule requires the server to answer, so such a service fails every send and expect check. For these services, keep the default check: use option udp-check with no udp-check rules, and make sure the network path permits ICMP Unreachable messages to return to the load balancer. Alternatively, probe the service with a datagram it is known to answer.

Follow another server’s health check Jump to heading

This section applies to:

  • HAProxy Enterprise 3.4r1 and newer

A udp-lb server can depend on the health of a server in the same section, or a different udp-lb section, or a different TCP or HTTP backend section instead of running a check itself. Add the track parameter to the server line and point it at the server to monitor:

haproxy
backend service_tcp
server srv1 10.10.10.10:1111 check
udp-lb service_udp
server srv1 10.10.10.10:4444 track service_tcp/srv1
haproxy
backend service_tcp
server srv1 10.10.10.10:1111 check
udp-lb service_udp
server srv1 10.10.10.10:4444 track service_tcp/srv1

The UDP server then runs no health check of its own. Its status mirrors the tracked server’s. When the tracked server fails its check, the UDP server reports as down, and when the tracked server comes back up, the UDP server reports as up.

This is useful when a service is exposed over both TCP and UDP. The TCP side gets an application-aware health check, and the UDP side follows it, so a failure on either transport removes both from rotation.

Rules to keep in mind:

  • The tracked server must have a health check or an agent enabled. Otherwise the load balancer rejects the configuration at startup.
  • A server can’t run a health check and track another server at the same time. Don’t add a check argument to a server that has a track parameter; don’t add udp-check directives to the udp-lb section.
  • Any type of health check can be tracked: a TCP check, an HTTP check, or a udp-check send and expect sequence on another udp-lb server.

See the track reference for the full syntax.

Do you have any suggestions on how we can improve the content of this page? Please leave feedback!