Skip to content

Releases: cfal/tobaru

v0.9.4

24 Feb 04:07

Choose a tag to compare

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 ring to aws_lc_rs as the cryptographic backend.
  • Updated to the rustls 0.23 API: CertificateDer<'static>,
    PrivateKeyDer<'static>, explicit CryptoProvider, danger module
    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.toml feature flags.

Config and API Changes

  • TlsOption split into purpose-specific AlpnValue and SniValue types,
    with SniValue performing hostname validation at deserialization time.
  • required_request_headers changed from Option<HashMap<...>> to
    HashMap<...> (empty map replaces None).
  • NoneOrSome/OneOrSome iterators now require Send/Sync bounds for
    async task compatibility.
  • Header path fields may now be empty.

Documentation

  • Added CONFIG.md with full configuration reference.
  • Updated README.md with 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() with line.contains(x).
  • Simplified task spawning in main.rs to idiomatic iterator collect.
  • NoneOrSome now derives Default via enum #[default] attribute.
  • Simplified is_unspecified() methods using matches!() macro.

v0.9.3

21 Jun 16:13

Choose a tag to compare

Full Changelog: 0.9.0...v0.9.3

0.9.0

23 Aug 16:25

Choose a tag to compare

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.

0.7.1

13 Mar 20:55

Choose a tag to compare

  • Bugfix: Allow common IP masks across TLS configs

0.7.0

12 Mar 20:33

Choose a tag to compare

0.7.0

0.2.0

27 Jun 16:04

Choose a tag to compare

  • Fix for copy_bidirectional causing CLOSE_WAIT sockets
  • Defaults to rustls

0.1.0

28 May 13:23

Choose a tag to compare

disable TCP nodelay until it can be configurable