Conversation
Implement TCP as an alternative to UDP for remote syslog forwarding, providing reliable delivery for environments where message loss is unacceptable. Forwarding syntax: - @@host:port (double-at prefix) - tcp://host:port Receiving syntax: - listen tcp://addr:port Uses octet counting framing for sending per RFC 6587. Supports both octet counting and LF-delimited framing for receiving to interoperate with various syslog implementations. Also fixes a use-after-free bug in socket_poll() where LIST_FOREACH was used while callbacks could remove entries from the socket list. Changed to LIST_FOREACH_SAFE to handle this correctly. Fixes #91 Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Verify TCP forwarding between two syslogd instances using both the @@ and tcp:// configuration syntax. Tests that messages are correctly forwarded after config reload. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Update syslog.conf(5) with TCP forwarding syntax (@@, tcp://) and TCP listener configuration (listen tcp://). Add examples showing typical usage patterns. Update syslogd(8) STANDARDS section to reference RFC 6587 for syslog over TCP. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Implements cryptographic signing of syslog messages per RFC 5848, providing origin authentication, message integrity, replay resistance, and detection of missing messages. Requires OpenSSL >= 1.1.0 and ./configure --with-openssl to enable. New configuration options: sign_sg, sign_delim_sg2, sign_keyfile, sign_certfile. Follows NetBSD's configuration syntax for compatibility. Features: - Signature blocks (ssign) with SHA-256 hashes and digital signatures - Certificate blocks (ssign-cert) for public key distribution - Four signature group modes (SG=0,1,2,3) per RFC 5848 Section 4.2.5 - Compiles cleanly with stub macros when OpenSSL is not available Fixes #21 Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Implements TLS-encrypted syslog forwarding and receiving per RFC 5425, building on the existing TCP infrastructure (RFC 6587) and reusing OpenSSL from RFC 5848 signing support. Configuration syntax: - Forwarding: tls://host:port or @@@host:port - Listening: listen tls://addr:port - Global: tls_keyfile, tls_certfile, tls_cafile, tls_capath - Per-action: verify=off|optional|required|hostname, fingerprint=SHA256:... Key implementation details: - TLS 1.2 minimum per RFC 5425 requirements - Default port 6514 for TLS syslog - Certificate verification: chain, fingerprint, or hostname - Optional mutual TLS authentication with client certificates - Deferred TLS connection until after tls_init() completes - Reuses F_FORW_TLS/F_FORW_TLS_SUSP/F_FORW_TLS_UNKN state machine Fixes #22 Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Verifies TLS forwarding between two syslogd instances using both @@@ and tls:// configuration syntax. Generates self-signed test certificates and validates message delivery through encrypted channel. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add documentation for TLS configuration options including new global settings: tls_keyfile, tls_certfile, tls_cafile, tls_capath, listener syntax: listen tls://, forwarding syntax: tls:// and @@@, and per-action options: verify=, fingerprint=. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Inspired by OpenBSD syslogd, introduce a double-prefix syntax for block headers that stops rule evaluation once a matching rule fires, preventing a message from being logged twice. !!prog -- like !prog but stops on match ++host -- like +host but stops on match ::filter -- like :filter but stops on match (sysklogd extension) Use !*, +*, or :* as usual to reset and resume normal evaluation for subsequent blocks. The STOP_FLAG (0x040) is set on all filed entries created within a double-prefix block. The logmsg() dispatch loop breaks out of the SIMPLEQ_FOREACH as soon as it processes a rule carrying that flag, so no further rules see the message. Example -- route nftables firewall logs exclusively to their own file: ::msg, contains, "[nftables" kern.* -/var/log/nftables.log :* *.warn;authpriv.none -/var/log/syslog Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Stop-processing block prefixes (!!, ++, ::) can only suppress rules that follow in the parsed order. A snippet in /etc/syslog.d/ cannot gate rules that were already parsed from the main config file above the include line. Fix this by moving the include directive in the shipped syslog.conf to sit before the general catch-all rules, so snippets are evaluated first and their stop-blocks take effect. Document the ordering constraint in two places in syslog.conf(5): in the include description, where the interaction is explained and the shipped file's structure is called out; and in the Stop Processing example section, where a direct note warns users who place stop-blocks in syslog.d/ snippets. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Fix .Sh DESCRIPTIOMN typo in man page - Fix chomp() indentation, spaces -> tabs - Fix nslookup() EAI_SERVICE warning, drop hardcoded "/udp" suffix - Bump message buffer from 512 to 2048 bytes (MAXLINE), matching syslogd's own limit to avoid silent truncation of long messages Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The -h option now accepts a transport prefix, matching the forwarding action syntax used in syslog.conf: logger -h tcp://logserver:514 "test" logger -h udp://logserver "test" # explicit UDP, same as before logger -h logserver "test" # plain host, UDP (backward compat) IPv6 addresses require bracket notation: tcp://[::1]:514 An optional port embedded in the URL overrides -P. The TCP path bypasses the syslog library entirely and handles DNS resolution (SOCK_STREAM), connection, message formatting (RFC5424 by default, RFC3164 with -b), and RFC 6587 octet-count framing directly, matching the framing used by syslogd's own TCP forwarding path. A tls:// prefix is recognised and rejected with a clear error for forward compatibility. Also change struct sockaddr to sockaddr_storage throughout to correctly handle IPv6 addresses in the UDP path as well. Note: bare IPv6 address literals (e.g. ::1) passed to -h are not supported; bracket notation must be used. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When -V is given, diagnostic output is written to stderr showing
what logger is actually doing, making it easy to verify a remote
syslogd configuration:
TCP:
connecting to 192.0.2.1 port 514 (tcp) ... connected
sending (82 bytes): <28>1 2026-03-20T14:30:00.123456+01:00 ...
UDP:
sending to 192.0.2.1 port 514 (udp)
For TCP, the exact RFC 6587-framed syslog message is shown, allowing
the user to confirm the message content matches the filter rules in
syslog.conf. Connection failures are reported on the same line as
the connect attempt, giving a clear pass/fail result.
For UDP only the resolved peer is shown; delivery cannot be confirmed
since the transport is fire-and-forget.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add two steps to the existing TCP forwarding test: - verify_direct_tcp: send directly from logger to the receiver's TCP listener using logger -h tcp://[::1]:PORT, bypassing the forwarding syslogd entirely. Confirms the RFC 6587 framing and message delivery end-to-end. - verify_verbose_tcp: invoke logger -V and check that "connected" appears on stderr, exercising the new verbose mode added alongside the TCP transport feature. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Verify that the :: (propfilter), !! (program), and ++ (hostname) stop-block prefixes prevent a matched message from reaching subsequent rules, while non-matching messages continue to fall through normally. Eight steps cover both positive (message lands in the right log) and negative (message absent from the wrong log) assertions for the propfilter and program-filter variants. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When a TCP receiver goes down, the sender previously dropped all messages
for the full suspension window (default 180 s). This change retrofits a
per-destination FIFO queue so that messages accumulate during outages and
are flushed automatically on reconnect (inspired by the NetBSD GSoC 2008
work).
New data structures (syslogd.h):
- struct fwd_qentry / fwd_qhead -- RFC 6587 framed queue entries
- FORW_QUEUE_MAX_LEN (1000) and FORW_QUEUE_MAX_SIZE (1 MiB) limits
- Four new fields on struct filed: f_queue, f_qlen, f_qsize, f_qoverflow
New helpers (syslogd.c):
- tcp_build_frame() flatten iovec into a single "LEN SP MSG" frame
- forw_queue_enqueue() add a frame; evict oldest on overflow
- forw_queue_flush() drain the queue over a live socket
- forw_queue_clear() discard all entries (SIGHUP / shutdown)
Behaviour changes:
- F_FORW_TCP_SUSP: enqueue instead of drop during the backoff window
- F_FORW_TCP_UNKN: enqueue when DNS is still unresolved
- F_FORW_TCP: flush any backlog before/after a successful send
- close_open_log_files(): always call forw_queue_clear() to prevent leaks
New syslog.conf global directive:
tcp_suspend_time N override the per-TCP-destination backoff (default
INET_SUSPEND_TIME = 180 s); useful in tests and for
operators who want faster failover.
Two bugs found and fixed during testing:
1. fprintlog_first() was resetting f_time for all filed types except the
two original UDP suspended/unknown states (F_FORW_SUSP, F_FORW_UNKN).
The TCP and TLS equivalents were missing from the guard, so the
suspension start timestamp was clobbered on every arriving message,
making fwd_suspend always 0 and the backoff window never expire.
Fixed by extending the exclusion to F_FORW_TCP_SUSP/UNKN and
F_FORW_TLS_SUSP/UNKN.
2. The SUSP → reconnect path transitioned through F_FORW_TCP_UNKN /
forw_lookup(), which silently skips re-resolution (and thus
tcp_connect()) when timer_now() - f_time < INET_DNS_DELAY (60 s).
With a tcp_suspend_time shorter than 60 s the reconnect never fired.
Fixed by jumping directly to f_forw_tcp (bypassing forw_lookup) when
the suspension window expires; the stored f_addr is still valid.
New regression test: test/tcp-queue.sh
Kills the receiver, injects three messages during the outage, restarts
the receiver, sends a trigger after tcp_suspend_time expires, and verifies
that all four messages arrive in order.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
syslog.conf(5): - Add tcp_suspend_time to the synopsis block - Document the directive in the global options section: default value, suspension/queue/flush cycle, queue bounds (1000 msgs / 1 MiB), overflow eviction policy, and the SIGHUP/exit discard caveat - Add a paragraph in the Remote Machine action section explaining the queue from the operator's perspective when configuring @@ / tcp:// forwarding targets syslogd(8): - Note in the HUP signal entry that queued TCP messages are discarded on reload - Extend the RFC 6587 TCP sentence in STANDARDS to mention the per-destination send queue and cross-reference tcp_suspend_time Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- bump GitHub Actions to Node.js 24 compatible versions - simplify, skip apt update - prevent duplicate jobs Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Testing of
next