Load balancers¶
Several Signalith servers that share one OpenSearch can sit behind one address: a load balancer, or a DNS name over all of them. Agents, browsers and syslog devices then use that one address, and keep working when a server stops. This page shows how to set one up with the samples in deploy/loadbalancer. For the servers themselves see Servers.
A single server needs none of this: both settings below are off unless you turn them on, and nothing changes while they are off.
How it fits together¶
agents, browsers ──► 8443 ┐ ┌─► siem-a :8080 web, :6514/:5514 syslog
syslog TLS ────────► 6514 ├─ load balancer┤
syslog TCP ────────► 514 ┘ (PROXY v2) └─► siem-b
syslog UDP ────────► virtual IP (keepalived) or one server
The balancer passes each TCP connection through unchanged, so HTTPS and syslog over
TLS end at Signalith and agents keep checking Signalith's certificate. It checks each
server's /readyz (see Load balancers: /readyz and /livez)
and sends nothing to a server that is starting, restarting, stopping or cut off from
OpenSearch.
Passing connections through hides who made them: every client would seem to be the balancer. So the balancer starts each connection with a PROXY protocol header (version 1 or 2) that names the client, and Signalith reads it.
Settings¶
On every server (the Settings page, or signalith.yaml):
| Setting | Where on the Settings page | What to set |
|---|---|---|
server.trusted_proxies |
HTTPS: Trusted reverse proxies | The balancers' own addresses, such as 10.0.0.20 and 10.0.0.21 |
server.proxy_protocol |
Web server: PROXY protocol from load balancers | On. Applies after a restart; SIGNALITH_PROXY_PROTOCOL=true sets it too |
syslog.proxy_protocol |
Syslog: PROXY protocol from load balancers | On, when syslog over TCP or TLS goes through the balancer. Applies after a restart; SIGNALITH_SYSLOG_PROXY_PROTOCOL=true sets it too |
server.public_url |
Web server: Public address | The balancer's address, such as https://siem.example.com:8443, so Add data gives it to agents |
server:
public_url: https://siem.example.com:8443
trusted_proxies: [10.0.0.20, 10.0.0.21]
proxy_protocol: true
syslog:
tcp: 0.0.0.0:514
tls: 0.0.0.0:6514
proxy_protocol: true
Only the trusted proxies may send a header. They may also connect without one, as a health check does. A header from any other address closes the connection: otherwise anyone could pick the address they are counted and logged under. The header must come within 5 seconds of connecting, and a malformed one closes the connection too.
A trusted proxy counts as many clients: it is never held to one client's share of connections and requests. The clients behind it each get their own share, by the address the header names.
signalith validate and the Health page warn when PROXY protocol is on but no trusted
proxy is listed (then no header is accepted), and when server.trusted_proxies
trusts every address (0.0.0.0/0 or ::/0).
The samples¶
haproxy.cfg: HAProxy in TCP mode for the web port (8443), syslog over TLS (6514) and syslog over TCP (514), withsend-proxy-v2,/readyzchecks andbalance leastconn. Change theserverlines to your servers' addresses.nginx-stream.conf: the same with nginx's stream module andproxy_protocol on. Open source nginx only notices a stopped server when a connection to it fails; it cannot read/readyz.keepalived.conf: one virtual IP shared by two balancer machines, so the balancer is not a single point of failure, and syslog over UDP balanced to the servers (UDP has no PROXY protocol).
The folder's README has notes for Windows Network Load Balancing, AWS and Azure load balancers, F5 and Citrix, and balancers that end TLS themselves.
Try it on one machine¶
deploy/docker/docker-compose.cluster.yml runs two servers, one OpenSearch and
HAProxy with the sample configuration, on one computer with Docker:
docker compose -f deploy/docker/docker-compose.cluster.yml up -d
docker compose -f deploy/docker/docker-compose.cluster.yml exec signalith-a signalith initial-password
Open https://localhost:8443 and sign in as admin. The Servers page lists both
servers, and the Health page's All servers card shows what each received. Stop one
(docker compose -f deploy/docker/docker-compose.cluster.yml stop signalith-b) and
keep working. Each server still has its own certificate authority there, so the
browser may ask about the certificate again when HAProxy picks the other server.
Remove the lab with down -v.
Agents¶
On Add data, Where do agents send? offers the shared address and each server's own, and says which servers the shared address reaches (see Where agents send). Use the shared address: agents then carry on with another server when one stops.
Checking it works¶
- Health page, All servers: agent batches and syslog messages per server, and in
total. Both servers should get some. A server that runs an older version shows
"No figures" instead of zero.
GET /api/health?scope=clustergives the same. - Health and Servers pages, "receives no agent traffic": a server running for 15 minutes got no agent batch in the last 10 while another did. Add it to the load balancer or the DNS name.
- Syslog senders on the Health page list devices by their own address. If they all
show the balancer's address,
syslog.proxy_protocolis off, or the balancer sends no header.
Troubleshooting¶
"closed a connection that sent a PROXY header from a peer that is not a trusted
proxy" in the log (at most once a minute), and syslog connections "with a PROXY
header from an untrusted peer" among those turned away on the Health page: a header came from an
address not under server.trusted_proxies. If that address is your balancer, add it.
Check the address Signalith sees: a balancer with several addresses (or a NAT between
it and Signalith) may connect from one you did not list.
Every client shows the balancer's address: PROXY protocol is off on that port, or the balancer does not send the header. Both sides must agree: a balancer that sends a header to a server that does not read it breaks every connection (the header is taken for the start of the request), and a server that reads it while the balancer sends none works, but sees only the balancer.
Sign-ins fail behind the balancer: once the servers share their users, any server takes any request. Until then (servers of an older version), turn on source address affinity or sticky sessions (see Load balancers: /readyz and /livez).