haproxy speaks syslog
For the longest time, if you wanted to use haproxy in front of syslog servers, you were limited to syslog over TCP, and you weren’t load balancing messages but connections because that’s all “mode tcp” would allow you.
This is going to change with haproxy 2.3: it will support message based load balancing and forwarding, with the ability to send and receive messages over TCP, UDP, or UNIX domain sockets. Each message being processed individually.
This blog post will detail the new configuration options available to implement syslog forwarding and load balancing, as well as provide sample configurations for different use cases.
Log forwarding
The usual way of proxying a service with haproxy is to use listen or frontend/backend blocks to define entry point and exit points for the service.
For syslog, there is a new kind of section called “log-forward”. This section contains the definition of listeners to receive incoming syslog messages, and a list of servers to forward messages to. There can be multiple “log-forward” sections in a configuration. An example “log-forward” definition would be:
log-forward syslog-lb
To receive incoming syslog messages, one can define UNIX or TCP listeners with the “bind” keyword, and UDP listeners with the “dgram-bind” keyword. The “bind” keyword is the same used in “frontend”, “listen”, or “peers” sections, and all associated keywords can be used, which means things such as TLS with client authentication can be configured. There is no such option for “dgram-bind”.
bind :514
dgram-bind :514
The list of servers to forward messages to consists in a list of log lines. The same log lines that can be used in “global”, “listen” or “frontend” section. An example server would be one of the following:
log 192.168.122.10:514 local0
The target for the log line can be either a UDP syslog server, a UNIX domain socket, or a TCP syslog server, the latter being addressed through a local ring.
A “log-forward” listener can be used as log target for a “frontend”, “listen” or “global” section. Similarly, a “log-forward” can contain a “log global” line, and forward logs to the server defined in the “global” section.
Playing with Severity
While a facility must be set on the log server lines when an address is also set, the facility is ignored, unless the message has no facility (eg: raw message), in which case the configured facility will be set for outgoing messages.
Severities on the other hand can be used to filter messages under a certain severity, and/or set a maximum severity for forwarded messages. When the severity exceeds the configured max, it is set to the configured maximum severity. To give an example:
log 192.168.122.10:514 local0 info notice
With this, any message with a severity of debug will not be forwarded, and any message with a severity exceeding notice will have its severity set to notice.
Format translation
An optional format can be configured on log server lines, and messages will be translated to that format when needed, before being sent to the log target.
log 192.168.122.10:514 format rfc5424 local0 info notice
This can be used to translate messages received from clients using different formats to a unique one.
Message based load balancing
When haproxy receives a message, it will send a copy of this message to all the servers defined in the “log-forward” section.
It is possible to do message based load balancing using the “sample” keyword on a log server line. The following would balance messages between 3 servers in a round robin fashion:
log 192.168.122.11:514 sample 1:3 local0 info notice
log 192.168.122.12:514 sample 2:3 local0 info notice
log 192.168.122.13:514 sample 3:3 local0 info notice
Not available (yet?)
There is currently no support for traffic processing rules, or content switching rules in a “log-forward” section, meaning it’s not possible to route messages based on content, or rewrite the content of the messages.
There is no support for load balancing other than by abusing “sample”, and it is not possible to persist clients.
Sample configurations
Basic round robin
log-forward syslog-lb-rr
# UDP listener
dgram-bind *:514
# log targets
log 192.168.122.185:514 sample 1:2 local2 info warning
log 192.168.122.212:514 sample 2:2 local2 info warning
Weighted round robin
log-forward syslog-lb-wrr
# UDP listener
dgram-bind *:514
# log targets 25/75 split
log 192.168.122.185:514 sample 1:4 local2 info warning
log 192.168.122.212:514 sample 2-4:4 local2 info warning
Mixing protocols
ring syslogtcpsrv
format rfc3164
size 32764
maxlen 1200
server log1 192.168.122.133:10514
log-forward syslog-lb-dualproto
# TCP listener
bind *:514
# UDP listener
dgram-bind *:514
# UDP log targets 25/75 split
log 192.168.122.185:514 sample 1:4 local2 info warning
log 192.168.122.212:514 sample 2-4:4 local2 info warning
# TCP log target gets all messages
log ring@syslogtcpsrv local2 info warning
TLS
ring syslogtcpsrv
format rfc3164
size 32764
maxlen 1200
server log1 192.168.122.133:10514
log-forward syslog-lb-tls-in
# TCP listener
bind *:1514 ssl crt /path/to/cert.pem verify required ca-file /path/to/ca.pem
# UDP log targets 25/75 split
log 192.168.122.185:514 sample 1:4 local2 info warning
log 192.168.122.212:514 sample 2-4:4 local2 info warning
# TCP log target gets all messages
log ring@syslogtcpsrv local2 info warning