cfal ee38ccc51a Reduce TUN latency and packet-processing overhead (#166)
* tun/tcp_stack_direct.rs: separate bounded ingress processing from TCP egress

Process each incoming packet without repeatedly scanning every socket for egress. Give each socket one egress turn per iteration and recheck actionable bridge work before waiting. Reconcile timer-driven closures after egress, while retaining pending reset tuples, and use a monotonic clock for stack deadlines.

* tun: wake the stack on TCP and UDP work instead of polling

Poll the TUN descriptor together with a coalescing Unix wake socket. Notify after publishing TCP buffer changes, UDP responses, setup and shutdown, then acknowledge notifications before consuming shared work. Preserve timer deadlines and bounded queue draining so idle stacks no longer need a 10-ms fallback. Propagate wake and thread startup failures to the caller.

* tun: carry owned UDP payloads through forwarding queues

Move packet storage through ingress, parsing and both destination queues instead of copying full packets and payloads. Preserve payload-byte limit semantics by compacting explicitly capped packets, and compact oversized backing storage even without a cap.

Reuse bounded pooled storage for packet construction, remove the redundant response copy, and test parsing, queue rejection and permit lifetime through flush, timeout and cancellation.

* tun/tcp_stack_direct.rs: reuse transmit storage and preserve packet-atomic writes

Borrow one initialized scratch buffer from the stack device for TCP egress. Write packet information and payload with one writev instead of allocating a framed copy.

Retry complete packets only after EINTR. Treat short writes as errors rather than emitting a malformed suffix packet, while preserving EAGAIN and ENOBUFS drops. Cover buffer reuse, framing and injected syscall outcomes.

* tun/tcp_stack_direct.rs: refresh late TCP handler setup before publishing connections

A SYN may arrive after the loop snapshots setup but after another thread has already published its handler. Refresh an absent sender at connection publication so that this race does not abandon and reset a valid connection. Add a deterministic snapshot/publication interleaving regression.

* tun/tcp_stack_direct.rs: amortize TCP egress across bounded complete sweeps

A single packet per socket per outer iteration raised loop overhead and regressed bulk TCP in shipping-profile benchmarks. Allow up to eight complete sweeps, stopping on no progress, before reconciling sockets and revisiting ingress and wakeups.

This keeps every socket eligible in each sweep, including late-index resets, without restoring an unbounded drain. Matched trials recovered throughput while preserving sparse-response latency.

* tun/wake.rs: assert progress while saturating the wake socket

Check successful write lengths in the saturation regression instead of ignoring them. This catches zero-progress writes and keeps the test compliant with Clippy while preserving its partial-write behavior.

* tun: simplify packet handling and polling control flow

Flatten UDP reader and direct-device receive paths, and make the stack's
continue-before-wait decision explicit. Name the existing egress sweep
bound and TCP/ICMP queue, and reuse pure size and state calculations.

Keep wake ordering, ownership, control checks, error reporting, and batch
limits unchanged. Add deterministic reader coverage for invalid packets
followed by Pending, valid delivery, and EOF.
2026-10-06 16:22:01 +08:00
2026-04-08 16:56:48 +08:00
2026-10-05 19:15:19 +00:00
2026-10-05 19:15:19 +00:00
2026-10-05 19:15:19 +00:00
2023-02-20 23:43:49 +09:00
2026-01-20 02:10:35 +04:00

shoes

shoes is a high-performance multi-protocol proxy server written in Rust.

Supported Protocols

Proxy Protocols

  • HTTP/HTTPS
  • SOCKS5 (with UDP ASSOCIATE)
  • Mixed (auto-detect HTTP/SOCKS5)
  • VMess AEAD
  • VLESS (with fallback support)
  • Shadowsocks
  • Trojan
  • Snell v3
  • Hysteria2
  • TUIC v5
  • AnyTLS
  • NaiveProxy
  • H2MUX (supported with VMess, VLESS, Trojan, Shadowsocks, Snell)

Transport Protocols

All server protocols plus:

  • SagerNet UDP over TCP (for Shadowsocks, SOCKS5, AnyTLS, NaiveProxy)
  • ShadowTLS v3
  • TLS
  • WebSocket (Shadowsocks SIP003)
  • XTLS Reality
  • XTLS Vision (for VLESS)

TUN/VPN Mode

  • TUN device support - Layer 3 VPN for transparent proxying
  • Supported platforms: Linux, Android, iOS

Supported Ciphers

  • VMess: aes-128-gcm, chacha20-poly1305, none
  • Shadowsocks: aes-128-gcm, aes-256-gcm, chacha20-ietf-poly1305, 2022-blake3-aes-128-gcm, 2022-blake3-aes-256-gcm, 2022-blake3-chacha20-ietf-poly1305
  • Snell v3: aes-128-gcm, aes-256-gcm, chacha20-ietf-poly1305

Features

  • Multi-transport: TCP or QUIC for all protocols
  • TLS with SNI routing: Route by Server Name Indication
  • Upstream proxy chaining: Multi-hop chains with load balancing
  • Rule-based routing: Route by IP/CIDR or hostname masks
  • Named PEM certificates: Define once, reference everywhere
  • TLS fingerprint authentication: Certificate pinning for TLS/QUIC
  • Hot reloading: Apply config changes without restart
  • Unix socket support: Bind to Unix domain sockets

For advanced access control (IP allowlist/blocklists), see tobaru.

Installation

Precompiled binaries for x86_64 and Apple aarch64 are available on Github Releases.

Or install with cargo:

cargo install shoes

Usage

shoes [OPTIONS] <config.yaml> [config.yaml...]

OPTIONS:
    -t, --threads NUM    Set the number of worker threads (default: CPU count)
    -d, --dry-run        Parse the config and exit
    --no-reload          Disable automatic config reloading on file changes

COMMANDS:
    generate-reality-keypair                  Generate a new Reality X25519 keypair
    generate-shadowsocks-2022-password <cipher>    Generate a Shadowsocks password

Examples

# Run with a single config file
shoes config.yaml

# Run with multiple config files
shoes server1.yaml server2.yaml rules.yaml

# Run with custom thread count
shoes --threads 8 config.yaml

# Validate configuration without starting
shoes --dry-run config.yaml

# Run without hot-reloading
shoes --no-reload config.yaml

# Generate Reality keypair
shoes generate-reality-keypair

# Generate Shadowsocks 2022 cipher password
shoes generate-shadowsocks-2022-password 2022-blake3-aes-256-gcm

Configuration

See CONFIG.md for the complete YAML configuration reference.

Examples

See the examples directory for all examples.

Basic VMess Server

- address: 0.0.0.0:16823
  protocol:
    type: vmess
    cipher: chacha20-poly1305
    user_id: b0e80a62-8a51-47f0-91f1-f0f7faf8d9d4
    udp_enabled: true

VLESS with Vision over TLS

- address: 0.0.0.0:443
  protocol:
    type: tls
    tls_targets:
      "vless.example.com":
        cert: cert.pem
        key: key.pem
        vision: true
        alpn_protocols: ["http/1.1"]
        protocol:
          type: vless
          user_id: b85798ef-e9dc-46a4-9a87-8da4499d36d0
          udp_enabled: true

Reality Server

- address: 0.0.0.0:443
  protocol:
    type: tls
    reality_targets:
      "www.example.com":
        private_key: "YOUR_BASE64URL_PRIVATE_KEY"
        short_ids: ["0123456789abcdef", ""]
        dest: "www.example.com:443"
        protocol:
          type: vless
          user_id: b85798ef-e9dc-46a4-9a87-8da4499d36d0
          udp_enabled: true

Reality Client

- address: 127.0.0.1:1080
  protocol:
    type: socks
  rules:
    - masks: "0.0.0.0/0"
      action: allow
      client_chain:
        address: "server.example.com:443"
        protocol:
          type: reality
          public_key: "SERVER_PUBLIC_KEY"
          short_id: "0123456789abcdef"
          sni_hostname: "www.example.com"
          protocol:
            type: vless
            user_id: b85798ef-e9dc-46a4-9a87-8da4499d36d0

Hysteria2 Server

- address: 0.0.0.0:443
  transport: quic
  quic_settings:
    cert: cert.pem
    key: key.pem
    alpn_protocols: ["h3"]
  protocol:
    type: hysteria2
    password: supersecret
    udp_enabled: true

TUIC v5 Server

- address: 0.0.0.0:443
  transport: quic
  quic_settings:
    cert: cert.pem
    key: key.pem
  protocol:
    type: tuic
    uuid: d685aef3-b3c4-4932-9a9d-d0c2f6727dfa
    password: supersecret

Mixed HTTP/SOCKS5 Server

- address: 0.0.0.0:7890
  protocol:
    type: mixed
    username: myuser
    password: mypassword

AnyTLS Server

- address: 0.0.0.0:443
  protocol:
    type: tls
    tls_targets:
      "anytls.example.com":
        cert: cert.pem
        key: key.pem
        protocol:
          type: anytls
          users:
            - name: user1
              password: secret123
          udp_enabled: true

NaiveProxy Server

- address: 0.0.0.0:443
  protocol:
    type: tls
    tls_targets:
      "naive.example.com":
        cert: cert.pem
        key: key.pem
        alpn_protocols: ["h2"]
        protocol:
          type: naiveproxy
          users:
            - username: user1
              password: secret123
          padding: true

TUN VPN

- device_name: tun0
  address: 10.0.0.1
  netmask: 255.255.255.0
  mtu: 1500
  tcp_enabled: true
  udp_enabled: true
  rules:
    - masks: "0.0.0.0/0"
      action: allow
      client_chain:
        address: "proxy.example.com:443"
        protocol:
          type: tls
          protocol:
            type: vless
            user_id: b85798ef-e9dc-46a4-9a87-8da4499d36d0

Similar Projects

S
Description
A multi-protocol proxy server written in Rust (HTTP, SOCKS5, Vmess, Vless, Shadowsocks, Trojan, Snell, Hysteria2, TUIC v5, AnyTLS, Naiveproxy, XTLS, XHTTP)
Readme MIT
14 MiB
Languages
Rust 98.7%
JavaScript 0.9%
Python 0.2%
RenderScript 0.1%