Releases: renaudallard/sniproxy
Release list
sniproxy 0.13.5
Fixes and one new option from a deep security audit.
Highlights:
-
New per_ip_ipv6_prefix option (default 64): the per-IP rate limit
and connection cap now group native IPv6 clients by prefix, so a
client cannot rotate through its allocation (typically a /64) to
evade them. IPv4 is unaffected; set the prefix to 128 for the old
per-address behaviour. -
The per-IP connection cap now fails closed when its hash chain is
full, closing a bypass where the count check kept allowing colliding
addresses that it could no longer track. -
Smaller robustness fixes: the encrypted logger channel is torn down
on a partial send instead of desyncing, and backend lists are
swapped safely on reload. See the ChangeLog for details.
sniproxy 0.13.4
Fixes from a deep source, documentation, build and CI audit.
Highlights:
-
Linux seccomp: helper processes restarted at runtime were killed by
the inherited main filter before they could install their own, so a
single resolver crash permanently disabled DNS resolution. -
DNS over TLS: resolver sockets are now non-blocking, so an
unreachable or stalling DoT server can no longer freeze all DNS
resolution, failover and shutdown. -
The privileged binder confines root-created unix sockets to /run
and /var/run only when actually binding, so unix listeners in
user-writable directories start again. Unix listeners clean up
their socket files, stale leftovers are replaced on the next start,
and reuseport now works for listeners bound through the binder. -
Configuration handling: the last directive of a file without a
trailing newline is no longer dropped, duplicate table names and
undefined table references are rejected at load, a failed reload
no longer switches the error log, and invalid dot:// nameserver
entries fail config test instead of crash-looping the resolver
child. -
Released tarballs ship the Perl integration tests again, plus many
smaller logger, pidfile, HTTP/2, idle timer, buffer limit,
documentation and CI fixes; see the ChangeLog for the full list.
sniproxy 0.13.3
Security and correctness fixes from a multi-pass source audit.
Highlights:
-
Reject "source client" combined with proxy_protocol: the untrusted
PROXY header must not drive the IP_TRANSPARENT source bind, which
would otherwise allow source-address spoofing toward backends. -
IPC channels now derive per-instance keys, so a restarted logger,
resolver or binder child no longer reuses the previous instance's
ChaCha20-Poly1305 (key, nonce) keystream. -
UDP/DTLS resolution now honors the global and per-client DNS query
limits, and UDP sessions are matched per receiving listener. -
Numerous resolver, sandbox (seccomp/pledge) and file-descriptor
hardening fixes; see the ChangeLog for the full list.
sniproxy 0.13.2
OpenBSD fixes:
- Initialize the IPC master key in the parent before forking the
logger and binder children. The children pledged before calling
ipc_crypto_channel_init(), and the first call would try to mlock
the master key, which is not covered by any pledge promise and
aborts the child. Pre-initializing in the parent lets the
children inherit the locked state and avoid the mlock path.
sniproxy 0.13.1
Build fixes for 0.13.0:
-
Include libgen.h unconditionally so dirname() and basename() are
declared on FreeBSD. The 0.13.0 Capsicum pidfile-cleanup code
guarded the include behind #ifdef OpenBSD, breaking the
FreeBSD build. -
Require seccomp.h to be present before defining HAVE_SECCOMP. On
distros where libseccomp ships its header in a separate package
(notably SUSE BCI), 0.13.0 detected the library, defined
HAVE_SECCOMP, then failed to compile seccomp.c when the header
was missing. -
Tests / CI:
- Add a logger_post_fork_child_disinherit stub to
resolver_response_fuzz; without it the harness fails to link
after the 0.13.0 disinherit hook in resolv.c. - The continuous-fuzzing workflow only files an issue when
actual crash/leak/timeout artifacts exist, so build failures
no longer auto-file false-positive 'fuzzer crash' issues.
- Add a logger_post_fork_child_disinherit stub to
No source changes affect the daemon's runtime behavior.
sniproxy 0.13.0
Security:
-
TLS parser: reject renegotiation_info even when the SNI extension
appears earlier in the ClientHello extension list. The parser used
to return immediately on SNI, bypassing the renegotiation rejection
check. A client could place a non-empty renegotiated_connection
alongside SNI and get the connection routed instead of rejected. -
TLS parser: reject empty SNI server_name list (RFC 6066 section 3)
and validate the inner length matches the remaining bytes. -
PROXY protocol v2: reject unknown command values (only LOCAL and
PROXY are defined by the spec). -
IPC channel: close orphan fds in SCM_RIGHTS ancillary data so a
malformed peer cannot exhaust the receiver's fd table. Validate
cmsg_len before extracting fd, check MSG_CTRUNC on the prefix
recvmsg, wipe partial ciphertext on seal failure.
Reliability:
-
Logger: stop the binder and resolver children from SIGKILLing the
parent's logger child via inherited IPC state. The resolver child's
first notice() at startup triggered this on every launch when file
or syslog logging was configured. -
Logger: do not SIGKILL the logger PID on waitpid ECHILD - the PID
may have been recycled to an unrelated process. -
HTTP/2: return -1 (incomplete, wait for more data) instead of -2
(no host) when the buffer ends mid-request, so clients that split
preface, SETTINGS and HEADERS across TCP segments are not aborted. -
Configuration tokenizer: reject embedded NUL bytes (raw or via
backslash escape) so tokens cannot silently truncate.
FreeBSD / Capsicum:
-
Connect to syslog at openlog() time with LOG_NDELAY so the syslog
socket is open before cap_enter() forbids path-based connect. -
Pre-open the pidfile parent directory; remove on shutdown via
unlinkat. Register cleanup via atexit so fatal() also removes it. -
Use unlinkat for connection-dump cleanup paths.
-
Limit cap_rights on parent-side IPC sockets.
-
Warn (rather than silently drop) when the logger child cannot
open a new file sink in capability mode.
OpenBSD:
- Keep cpath in the post-tightening pledge so the pidfile can be
removed at exit. Otherwise the daemon SIGABRTed on every shutdown.
Configuration:
- dot://ADDRESS/SNI/tls1.2|tls1.3 syntax now parses correctly
(previously the documented third URI segment was rejected by the
parent before reaching the resolver child).
Packaging:
-
Add libseccomp build dependency to debian/control,
redhat/sniproxy.spec, alpine/APKBUILD, and the matching install
lines in release-packages.yml. Without this, every Linux package
release was being built without the seccomp sandbox. -
Detect libssl in configure instead of hardcoding -lssl.
-
Actually clear hardening flags when sanitizers are enabled
(the conflict-resolution branch had no effect). -
Point package metadata at the renaudallard fork.
Tests / CI:
-
Tighten resolv_test, ipc_crypto_debug_test and tls_test
assertions so silent regressions are caught. The lenient tls_test
assertion is what previously masked the renegotiation_info bypass. -
Wire ipc_crypto_debug_test, ipc_crypto_rekey_test, and
ipc_crypto_time_rekey_test into TESTS / check_PROGRAMS. -
Cover dtls and ipc_crypto tests in the valgrind workflow.
-
Fix functional_test connection-dump file lookup, xmpp_test
off-by-one length, config_test TMPDIR honoring. -
Remove broken orphan test files.
Other:
-
Rate limit buckets now track is_v4 to mirror ConnCountBucket and
avoid v4/v6 cross-match on hash collision. -
Skip destructive sink swap when REOPEN produced no new file.
-
Avoid double ev_timer_again in UDP validating fast-path.
-
Use _exit in manual daemonize fork-and-exit fallback.
-
Forward-declare struct Logger in listener.h.
-
Parenthesize IS_TEMPORARY_SOCKERR macro argument.
sniproxy 0.12.0
-
FreeBSD Capsicum sandboxing: mainloop, resolver, and logger processes
enter capability mode after initialization. IPC sockets are restricted
to minimum required rights. Config reload and log rotation use
pre-opened directory fds with openat(). Binder is excluded (needs VFS
for bind). Set SNIPROXY_DISABLE_CAPSICUM=1 to disable. -
FreeBSD rc.d startup script (scripts/sniproxy.rc) for service
management via rc.subr. -
Build system fix: AC_CANONICAL_HOST was missing, so seccomp (Linux)
and Capsicum (FreeBSD) were never detected. Also link libm for
isfinite() on FreeBSD. -
FreeBSD package added to release workflow.
sniproxy 0.11.1
- Bugfix: Fix IPV6_V6ONLY not effective when binding privileged ports
via binder child process. On Linux, setsockopt(IPV6_V6ONLY) after
bind() is rejected with EINVAL, so the option must be set before
bind(). The ipv6_v6only flag is now passed to the binder child which
sets it before calling bind().
sniproxy 0.11.0
- Feature: Add DTLS (TLS over UDP) protocol support. Proxies DTLS
connections by extracting the SNI extension from the DTLS ClientHello
datagram, enabling hostname-based routing for WebRTC, OpenConnect VPN,
CoAP, and other UDP/DTLS protocols without decrypting traffic.
Configure withprotocol dtlsin listener blocks. - Security: Add DTLS source validation to prevent UDP reflection and
amplification attacks. New UDP sessions require a retransmission
from the client before the backend is contacted. Spoofed sources
never retransmit and are silently dropped after 3 seconds. This
eliminates ~10-20x amplification via backend ServerHello responses. - Security: Add per-IP rate limiting and connection counting to UDP
sessions, matching the TCP path. Previously an attacker from a single
IP could exhaust all UDP sessions and file descriptors. - Security: Tighten seccomp filter for the logger child process,
restricting it to syslog and IPC-only network syscalls instead of the
full network set. - Security: Disable TLS session tickets for DNS-over-TLS connections
to preserve forward secrecy. - Security: Add missing
sendfdandrecvfdpledge promises on
OpenBSD for binder fd passing during SIGHUP reload. Thesendfd
promise must also be in the parent's pledge set so the binder child
can inherit it after fork. - Security: Cap UDP pending datagram size to 4KB to limit memory when
many sessions are in RESOLVING state simultaneously. - Hardening: Detect explicit_bzero in configure so secure_memzero uses
the compiler-safe variant instead of the volatile pointer loop
fallback. - Hardening: Wipe IPC send buffer before free to prevent ciphertext
lingering in freed memory. - Hardening: Set SOCK_CLOEXEC on DoT sockets in resolver child.
- Hardening: Add bounds check on Huffman tree int16_t cast.
- Hardening: Add compiler flags -Wshadow, -Wimplicit-fallthrough,
-Wnull-dereference, -Wundef, -fno-delete-null-pointer-checks. - Hardening: Harden systemd service with ProtectKernelTunables,
ProtectKernelModules, ProtectKernelLogs, ProtectControlGroups,
ProtectClock, ProtectHostname, PrivateDevices, RestrictNamespaces,
RestrictRealtime, RestrictSUIDSGID, MemoryDenyWriteExecute, and
LockPersonality. - Hardening: Use memcpy for IPv6 address hashing in UDP session lookup
for strict-alignment portability. - Fix: Add underflow guard on conn_count_free_count in connection rate
limiter, matching the existing guard in rate_limit_bucket_acquire. - Fix: Check for partial writes in resolver child send, matching the
parent-side pattern. - Fix: Hold resolver_queries_lock across both resolver_attach_query and
resolver_emit_query in query resubmission, matching the documented
atomicity invariant. - Fix: Exit resolver child on ev_loop_new failure instead of falling
back to the parent's event loop. - Fix: Check sock->failed early in DoT read/write callbacks to avoid
calling SSL on known-broken connections. - Fix: Warn when reuseport or ipv6_v6only changes on SIGHUP reload
since these socket options cannot be changed on a live bound socket. - Fix: Warn when resolver config changes on SIGHUP reload since the
resolver child is not restarted. - Fix: Annotate intentional switch fallthroughs for clang
-Wimplicit-fallthrough compatibility.
sniproxy 0.10.0
- Feature: Add
per_ip_max_connectionsglobal directive to limit the
number of simultaneously active connections from a single source IP.
Prevents a single client from exhausting all connection slots. The
default is 0 (disabled). Distinct fromper_ip_connection_ratewhich
limits the rate of new connections. - Feature: Add
tcp_fastopen onglobal directive to enable TCP Fast Open
on listener sockets (server side, Linux/FreeBSD) and backend connect
sockets (client side, Linux 4.11+). Reduces connection latency for
clients and backends that support TFO. - Feature: Add
backend_aclglobal directive to restrict which backend
addresses sniproxy may connect to after DNS resolution. Supports
allow_exceptanddeny_exceptpolicies with CIDR ranges, preventing
abuse as an open proxy to reach internal hosts. - Feature: Randomly select from multiple DNS results when resolving
backend hostnames, distributing connections across DNS round-robin
backends instead of always using the first record. - Feature: Add
backend_affinity ontable directive for session
persistence. When DNS returns multiple records for a backend, the
client IP is hashed to consistently select the same backend. - Feature: Auto-anchor literal hostname patterns in table entries.
Bare hostnames likeexample.comare now compiled as^example\.com$
so they match exactly, not as substrings of other hostnames. Patterns
containing regex metacharacters are left as-is. - Feature: Accept incoming PROXY protocol headers (v1 text and v2 binary
auto-detected) on listeners viaproxy_protocol ondirective. - Feature: Add PROXY protocol v2 (binary) output support for table backends
and fallback addresses viaproxy_protocol_v2keyword. - Feature: Add Minecraft Java Edition protocol support for routing
Minecraft connections by hostname without decrypting traffic. - Feature: Add SIGCHLD handler to reap zombie child processes.
- Doc: Document HTTP/2 connection coalescing limitation and workarounds.
- Security: Fix broken binary search and missing host header detection
in HPACK decoder. The static name index was sorted incorrectly for the
binary search comparator, and literal Host headers were only detected
by pointer comparison instead of string comparison. - Security: Add missing
recvfdpledge promise in logger child on
OpenBSD. Without this, the kernel kills the logger child with SIGABRT
when it receives file descriptors via SCM_RIGHTS. - Security: Fix use-after-free in resolve_server_address on synchronous
DNS failure. - Security: Fix per-IP conn_count mismatch when PROXY protocol is used
(connections were counted under the proxy address, not the real client). - Fix: Enforce RFC 7541 dynamic table size update limits in HPACK decoder.
- Fix: Restart logger child on health check failure instead of fatal exit.
- Fix: Use non-blocking poll in logger health check to avoid stalling the
event loop for up to 100ms every 30 seconds. - Fix: Close unexpected file descriptors in logger child NEW_SINK handler.
- Fix: Handle ECHILD when killing logger child after daemonize.
- Fix: Fix stderr log messages silently lost when routed via logger child.
- Fix: Resolve relative config path before daemonize so SIGHUP reload
works after chdir("/"). - Fix: Check pidfile write for errors.
- Fix: Fix -T 1.3 rejecting all TLS connections (legacy_version check
blocked before supported_versions extension was examined). - Fix: Fix fallback address losing port number on SIGHUP reload.
- Fix: Reject stray closing brace at config top level.
- Fix: Fix EAGAIN on logger IPC permanently killing logger child.
- Fix: Fix server buffer growing 4x instead of intended 2x on resize.
- Fix: Fix IPC crypto context leak in resolver init on socketpair/fork
failure. - Fix: Preserve errno across accept cleanup so EMFILE backoff triggers.
- Fix: Fix resolver IPC max payload length to include header.
- Fix: Use TOCTOU-safe directory validation for /var/run/sniproxy.
- Fix: Wipe all derived keys on IPC channel init failure.
- Fix: Fix resource leak on strdup failure in DoT server registration.
- Fix: Add overflow check to iovec total length in DoT send path.
- Fix: Snapshot protocol at accept time to prevent mismatch during reload.
- Fix: Fail backend init when literal pattern anchoring malloc fails.
- Fix: Fix ensure_logger_process return value after resend failure.
- Fix: Chown log files before dropping privileges so SIGHUP log rotation
works. - Fix: Emit PROXY TCP4 instead of TCP6 for IPv4-mapped IPv6 addresses.
- Hardening: Use reallocarray() for overflow-safe allocation throughout.
- Hardening: Replace assert() with proper runtime error handling.
- Hardening: Check setsockopt, fcntl, and inet_ntop return values.
- Hardening: Add closefrom to AC_CHECK_FUNCS for efficient fd cleanup.
- Build: Add missing OpenSSL and libbsd build dependencies.
- Build: Clean up unused functions, dead code, and redundant includes.