Skip to content

v0.3.4

Choose a tag to compare

@cfal cfal released this 24 Oct 08:58
fb1fa5b
  • Added an opt-in Clash API controller over authenticated TCP or Unix sockets, with manual proxy selectors, optional persistent choices, connection inspection/cancellation, traffic/log streams, and delay probes. Existing groups remain round-robin; selection changes affect new flows only. Every controller requires a nonempty secret. TCP listeners serve plain HTTP; bind to loopback or terminate TLS in front. Controller settings require a restart. Browser origins require an explicit allowlist; cors_origins: ["*"] permits any origin without disabling authentication. No dashboard hosting or full Mihomo API parity is included; controller/cache entries are not supported through FFI.
  • Added multiarchitecture Docker images at ghcr.io/cfal/shoes for linux/amd64 and linux/arm64. Use v0.3.4 for this release, latest for the latest stable release, or master for current development builds.
  • Fixed payload loss after fragmented VLESS response headers, WebSocket framing after nonempty Ping frames, and preread-byte loss in ShadowTLS authentication fallback.
  • Fixed WebSocket handling of 125-byte control frames, false EOF with partly filled read buffers, and flushing buffered frames on shutdown. The shared TLS ClientHello parser now reassembles handshakes across records, and message-stream shutdown after EOF is bounded.
  • Replaced REALITY's custom TLS state machine and record crypto with a pinned cfal/rustls fork. Authentication, ML-DSA policy, transparent forwarding and Vision remain in Shoes. Outbound ClientHello now uses rustls's native fingerprint, not Chrome/uTLS emulation; clients still fail closed on non-REALITY certificates.
  • REALITY servers preserve admitted target ServerHello bytes except the key share and follow the target's cipher within the configured allowlist. Every synthetic handshake record must fit its target length. Unsupported layouts, cipher conflicts and insufficient capacity forward transparently before synthetic output; targets that previously worked only because Shoes enlarged records may now fail outbound REALITY authentication. Combined flights with observed trailing records or partial data are not synthesized; separate flights require capacity for rustls's server-name acknowledgement.
  • REALITY now reports TCP EOF without TLS close_notify as UnexpectedEof, matching ordinary rustls TLS connections rather than treating truncation as a clean close.
  • Fixed Naive HTTP/2 writes stalling on already available flow-control credit after a pending write is cancelled and retried with a smaller buffer.
  • Fixed TUN startup resets for queued TCP connections, rejected SYN admission, and stale passive listeners after handshake resets. TUN and WireGuard now defer inbound routing and hostname sniffing until TCP establishment; half-open TUN connections expire after 30 seconds instead of retaining the established-connection timeout.
  • Propagated TUN worker startup and runtime failures, including hard write errors, to the service owner. The daemon now stops with an error rather than silently continuing without TUN. Temporary Linux link-down and Apple utun queue backpressure drop packets without stopping the service. Invalid supplied descriptors are rejected before taking ownership.
  • Kept reply-only TUN UDP sessions alive while destination traffic continues.
  • Bound each iOS service's socket-protection callback to its own protector so stopping an older service cannot clear a replacement callback.
  • Released Fake DNS snapshot locks explicitly on owner teardown so concurrently starting subprocesses cannot delay reopening the state file.
  • Updated Rust dependencies, including GotaTun 0.10.2, Tokio 1.54.1, LRU 0.19.0, and ML-KEM 0.3.3, which removes secret-dependent table lookups. Tokio 1.54.1 fixes an Interval timer race on multithreaded runtimes that could cause crashes or use-after-free (GHSA-5wjr-9356-4wc8).
  • Refreshed the BLAKE3 fork with upstream buffer-alignment and AVX-512 soundness fixes while retaining the binary-context key derivation API.
  • Removed the standalone Android Kotlin/Gradle wrapper, AAR and iOS XCFramework packaging, and mobile SDK release artifacts from this repository. Mobile embedding remains supported through the Rust JNI/C interfaces; Android and iOS cross-compilation checks remain in CI. Existing SDK users must build the native libraries and supply their own com.shoesproxy.ShoesNative declarations on Android or link libshoes.a using include/shoes.h on iOS; see the README's Mobile Embedding section.
  • Updated Web PKI dependencies for the eMudhra intermediate CA compromise (CVE-2026-111943): removed emSign ECC Root CA - G3 from bundled roots and blocked the eight compromised intermediate keys, including cross-signed chains, during certificate verification. Affected deployments need certificates with an unaffected CA chain. Existing binaries must be rebuilt or upgraded to receive this protection.
  • Added opt-in native VLESS Encryption with X25519 and ML-KEM key chains, session resumption, native Vision, and the generate-vless-encryption command. A VLESS-level vision: true without native encryption, previously ignored, now fails validation; move it to the TLS/REALITY layer for legacy Vision. Older versions silently ignore native encryption settings, so roll back configuration together with the binary. Native encryption interoperates with supported Xray and Mihomo peers, not sing-box; see the README for configuration and transport limitations.
  • Added standard HTTP/2 CONNECT support to HTTP and mixed listeners and opt-in HTTP proxy clients (http_version: h2), including concurrent tunnels on eligible shared connections. HTTP/1 remains the client default; explicit H2 over TLS requires matching h2 ALPN.
  • Fixed Vision DIRECT decisions under backpressure and tightened TLS ServerHello parsing.
  • Fixed bracketed IPv6 literals in destinations and DNS upstream URLs being treated as hostnames.
  • Fixed TCP loss recovery in TUN and WireGuard through a pinned smoltcp fork.
  • Fixed XHTTP shutdown handling for complete HTTP/2 responses. Added server matching_headers for exact required-header matching, with single values or lists of allowed values for rotation. Requests must send exactly one value per required header. Header/path mismatches return plain 404s on all HTTP versions without affecting H2/H3 sibling streams, subject to request-admission limits. All XHTTP error responses now omit XHTTP padding, caching, and CORS headers; successful responses are unchanged. The development-only close_on_http1_error option is not supported and configurations containing it fail to load.
  • XHTTP client headers now reject names that differ only in case, which previously sent every value and failed exact server matching, and values with leading or trailing whitespace, which receivers strip or reject.
  • XHTTP aggregate/session admission and byte caps are now opt-in, and the per-connection request limit defaults to 250 instead of 128. Uncapped workloads can use more memory under overload. Setting only an aggregate byte or request cap derives the previous per-session safeguard (at most 4 MiB or 128 requests); explicit session caps override it. To restore all v0.3.3 XHTTP limits, set max_sessions: 1024, max_pending_sessions: 256, max_requests: 4096, max_requests_per_session: 128, max_requests_per_connection: 128, max_buffered_bytes: 67108864, and max_session_buffered_bytes: 4194304 under limits. Packet sizes, reorder windows, transport windows and timeouts are unchanged.
  • Added ordered destination predicates and shared domain/IP indexes, with local SRS, sing-box JSON, Mihomo YAML/text/MRS and Xray GeoSite/GeoIP DAT rule sets. Sources compile before listener replacement and participate in config-file watching; invalid candidates retain the running configuration. IP rules resolve only when needed and pin the judged address; DNS failures stop routing.
  • Rule migration: legacy *.example.com and .example.com masks now reject at startup; use typed domain_pattern or subdomains. Supplied hostnames must be valid ASCII A-label names, even with catch-all-only rules. Non-/0 IPv6 masks no longer implicitly match IPv4 addresses through mapped representation; mapped-only legacy prefixes migrate with a warning. Legacy /0 remains universal; typed CIDRs are family-specific.
  • Added opt-in dns.fake_ip with shared DNS-group mappings, TCP/UDP port-53 interception, hostname restoration, and optional persistent state. Other DNS records use the configured real upstreams; Android/iOS require explicit dns.servers rather than VPN system discovery.
  • Added opt-in sniff: true for route-only TLS SNI and cleartext HTTP/1 Host matching on logical TCP streams. The sniffed hostname takes precedence over Fake-DNS-restored names for hostname rules without replacing the connection target; explicitly supplied hostnames are not sniffed. Routing is fixed after initial inspection, including across later HTTP requests. HTTP/2 headers and QUIC datagram sniffing are not included.
  • Preserved original UDP reply identities across Fake DNS restoration and fixed early-data delivery in AnyTLS, H2MUX, and Naive TCP adapters.
  • Added userspace WireGuard client and server protocols using GotaTun 0.10.2. They support inbound TCP/UDP forwarding, outbound proxy chains, IPv4/IPv6, multiple server peers, PSKs, keepalives, and authenticated roaming on Unix. Identical client configurations share devices automatically; conflicting settings for the same endpoint and key pair reject.
  • WireGuard clients are supported only at the first chain hop. TCP DNS transports can use them; unsupported UDP/H3 DNS routes and tunnel-dependent bootstrap configurations are rejected instead of bypassing the tunnel.
  • Added protocol peer_client_chain for proxies before WireGuard, including nested WireGuard clients and optional inner proxy suffixes. Detours use fixed peer destinations, require a UDP-capable final carrier hop, and never fall back to direct UDP. Proxied servers omit their listen address and initiate peer associations using keepalive. Detours do not accept unsolicited public peers or support arbitrary peer roaming.
  • WireGuard reloads disconnect existing flows and explicitly release endpoint sockets before rebinding. Initial limitations include no IP fragmentation/reassembly, ICMP forwarding, or OS route management.
  • Shared TUN and WireGuard TCP streams complete write-half shutdown after queuing FIN, without waiting for the remote read half to close. Dropping a drained stream allows the FIN exchange to finish, bounded by a 60-second orphan deadline.
  • SOCKS5 outbounds now wait for each server reply during negotiation instead of sending the CONNECT request ahead, fixing timeouts with servers that drop early data, such as Cloudflare WARP's local proxy. Setup through a SOCKS5 upstream takes one more round trip, or two with username/password. Servers that select an authentication method the client did not offer are rejected.
  • SOCKS5, mixed, and WebSocket inbounds flush each handshake reply, and ShadowTLS sends records without waiting for a flush, so clients that wait for each reply, such as sing-box and now Shoes, no longer stall when these inbounds run inside ShadowTLS. Upgrade Shoes servers running SOCKS or mixed inbounds inside ShadowTLS before or together with clients; updated clients stall against older servers.

This release is distributed through GitHub Releases and GHCR, not crates.io. Crates.io publishing remains disabled while fork patches are required; cargo install shoes still installs the previously published release. Building from source requires Rust 1.95 or newer. The six Linux/macOS release tarballs contain THIRD_PARTY_NOTICES.md and licenses/ beside the binary; distributors must retain these notices and corresponding source information. Android AAR and iOS XCFramework archives are no longer provided.

Full changelog: v0.3.3...v0.3.4