Releases: cfal/tobaru
v0.9.4
TLS Passthrough
Connections can now be forwarded to upstream targets without TLS termination.
The proxy parses the ClientHello to extract SNI and ALPN, then either
terminates or passes through the raw TCP stream based on target configuration.
Passthrough targets cannot use HTTP actions or client_tls (validated at
config load time). A new example is provided in examples/sni_passthrough.yml.
Wildcard SNI Matching
SNI-based routing now supports wildcard patterns (*.example.com) via a new
DomainTrie data structure, replacing the previous HashMap<TlsOption, ...>
lookup. The trie supports exact matches, wildcard subdomains, dot-shorthand
(.example.com), and catch-all (*). A new example is provided in
examples/wildcard_sni.yml.
Host Header Wildcard Routing
HTTP host header matching supports the same wildcard patterns as SNI routing.
A Hostnames variant was added for the Host header config, enabling pattern-based
virtual hosting. See examples/host_header_routing.yml.
TLS Fingerprint Verification
Both client and server certificate fingerprints (SHA-256) can now be verified:
- Client fingerprints: The server can require connecting clients to present
certificates matching configured SHA-256 fingerprints, optionally combined
with CA chain validation. - Server fingerprints: Outbound connections can pin upstream server
certificates by fingerprint, with optional WebPKI verification.
Client CA Certificate Authentication
Server listeners can require client certificates signed by specified CA
certificates via the new client_ca_certs config option. This works alongside
or independently of fingerprint-based verification.
Client ALPN and SNI Control
Outbound TLS connections now support explicit ALPN protocol negotiation and
SNI hostname configuration. SNI can be set to a specific hostname, disabled
entirely (YAML null), or left to default behavior.
TCP Keepalive
Both server-side (client-facing) and target-side (upstream) TCP keepalive can
be configured with idle and interval durations. Implemented via socket2 using
raw file descriptor manipulation. Failures are logged but do not abort
connections.
Hostname Validation
A new hostname_util module provides strict validation for SNI hostnames
(per RFC 6066 section 3) and HTTP Host headers. Rejects empty strings, overlength
labels, trailing/leading/consecutive dots, non-ASCII bytes in SNI, control
characters, and IP address literals in SNI. Pattern normalization strips FQDN
trailing dots and validates wildcard placement at deserialization time.
TLS ClientHello Parser
A custom TLS ClientHello parser (tls_parser and tls_reader modules)
replaces the previous peek-based TLS detection heuristic. This enables full
extraction of SNI and ALPN from the ClientHello before deciding whether to
terminate or pass through, and eliminates the polling sleep loop.
Replay Stream Removal
The LazyConfigAcceptor-based flow was replaced with direct ClientHello
parsing and manual feeding of buffered bytes into the rustls ServerConnection.
For non-TLS fallback, already-read bytes are passed as initial_data through
to the HTTP parser via a new LineReader::new_with_data() constructor, so no
bytes are lost.
Cooperative Task Scheduling
The bidirectional copy loop now participates in Tokio's cooperative task
budgeting (tokio::task::coop), preventing high-throughput streams from
starving other tasks on the runtime.
Rustls and Crypto Backend Migration
- Migrated from
ringtoaws_lc_rsas the cryptographic backend. - Updated to the rustls 0.23 API:
CertificateDer<'static>,
PrivateKeyDer<'static>, explicitCryptoProvider,dangermodule
verifier traits, simplified key/cert loading. - Server config now sets
ignore_client_order = true, preferring the server's
cipher suite order. - Max log level is capped in release builds via
Cargo.tomlfeature flags.
Config and API Changes
TlsOptionsplit into purpose-specificAlpnValueandSniValuetypes,
withSniValueperforming hostname validation at deserialization time.required_request_headerschanged fromOption<HashMap<...>>to
HashMap<...>(empty map replacesNone).NoneOrSome/OneOrSomeiterators now requireSend/Syncbounds for
async task compatibility.- Header path fields may now be empty.
Documentation
- Added
CONFIG.mdwith full configuration reference. - Updated
README.mdwith sections on wildcard SNI matching, host header
routing, and new TLS features. - Added example configs:
host_header_routing.yml,sni_passthrough.yml,
wildcard_sni.yml.
Minor Improvements
- Replaced
std::io::Error::new(ErrorKind::Other, ...)with
std::io::Error::other(...)(Rust 1.74+) throughout the codebase. - Replaced
line.find(x).is_some()withline.contains(x). - Simplified task spawning in
main.rsto idiomatic iterator collect. NoneOrSomenow derivesDefaultvia enum#[default]attribute.- Simplified
is_unspecified()methods usingmatches!()macro.
v0.9.3
Full Changelog: 0.9.0...v0.9.3
0.9.0
Full Changelog: 0.7.1...0.9.0
Breaking changes: The config format has changed. See https://github.com/cfal/tobaru/blob/master/UPGRADING.md for details.