itsusinn/tuic-server

By itsusinn

Updated 2 months ago

Successor of offcial TUIC implementation

Image
Networking
0

1.1K

itsusinn/tuic-server repository overview

tuic-server

Minimalistic TUIC server implementation as a reference.


Table of Contents


Overview

tuic-server is a robust and actively developed implementation of the TUIC protocol server. It is a fork of the original TUIC project with significant enhancements and additional features. While it started as a reference implementation, it has evolved to include many production-ready capabilities.

This fork includes advanced features such as Docker support, self-signed certificate capabilities, automatic certificate hot-reloading, updated dependencies, and improved performance through more relaxed locks. It is suitable for both learning and production environments.


Features

  • Minimal TUIC protocol server implementation
  • TOML and legacy JSON configuration support
  • Flexible ACL (Access Control List) system
  • Multiple outbound proxy modes (direct, SOCKS5, etc.)
  • TLS support with auto-provisioning and self-signed certificates
  • RESTful API for monitoring and management
  • Docker and Docker Compose deployment options

Installation

Download Prebuilt Binary

Get the latest release from GitHub Releases.

Install via Cargo
cargo install --git https://github.com/Itsusinn/tuic.git tuic-server

Usage

Run the TUIC server with a configuration file:

# Specify config file directly
tuic-server -c PATH/TO/CONFIG

# Specify config directory (automatically finds first config file)
tuic-server -d PATH/TO/CONFIG_DIR

# Generate example configuration file
tuic-server --init

The -d/--dir option searches for the first recognizable configuration file (.toml, .json, .json5, .yaml, .yml) in the specified directory, sorted alphabetically. This provides flexibility in Docker deployments and multi-environment setups.

Docker
docker run --name tuic-server \
  --restart always \
  --network host \
  -v /PATH/TO/CONFIG_FILE:/etc/tuic/config.toml \
  -v /PATH/TO/CERTIFICATE:/PATH/TO/CERTIFICATE \
  -v /PATH/TO/PRIVATE_KEY:/PATH/TO/PRIVATE_KEY \
  -dit ghcr.io/itsusinn/tuic-server:latest
  ## or -dit docker.io/itsusinn/tuic-server:latest

Note: The Docker image now uses -d /etc/tuic by default, allowing you to mount your config directory.

Docker Compose
services:
  tuic:
    image: ghcr.io/itsusinn/tuic-server:latest
    ## or image: docker.io/itsusinn/tuic-server:latest
    restart: always
    container_name: tuic
    network_mode: host
    volumes:
      - ./config.toml:/etc/tuic/config.toml:ro  # Mount config file
      #- ./config:/etc/tuic:ro # Mount config directory
      - ./cert.crt:/PATH/TO/CERT:ro
      - ./key.crt:/PATH/TO/KEY:ro

The server will automatically detect and use the first config file found in /etc/tuic.


Configuration

  • TOML format: Use .toml file extension (recommended for new configurations)
  • JSON5 format: Use .json or .json5 file extension (legacy format, still supported)
  • Yaml format: Use .yaml or .yml file extension

The format is automatically detected based on the file extension. You can also force TOML parsing by setting the TUIC_FORCE_TOML environment variable. Or use TUIC_CONFIG_FORMAT environment variable to explicitly specify the format (toml or json5).

Example configuration
# Logging level: trace, debug, info, warn, error, off
log_level = "info"

# Socket address to listen on
server = "[::]:443"

# Working directory for tuic-server (used for relative certificate/key paths)
data_dir = ""

# Create separate UDP sockets for relaying IPv6 UDP packets
udp_relay_ipv6 = true
# Enable 0-RTT QUIC handshake (recommended: false for security)
zero_rtt_handshake = false
# Set if listening socket should be dual-stack (IPv4/IPv6)
dual_stack = true
# How long to wait for client authentication command
auth_timeout = "3s"
# Maximum duration for task negotiation
task_negotiation_timeout = "3s"
# Interval between UDP packet fragment garbage collection
gc_interval = "10s"
# How long to keep UDP packet fragments before dropping
gc_lifetime = "30s"
# Maximum packet size received from outbound UDP sockets (bytes)
max_external_packet_size = 1500
# How long to preserve TCP and UDP I/O tasks
stream_timeout = "60s"

# Access Control List (ACL) rules - can be specified in two formats:

# Format 1: Array of tables format
[[acl]]
# Address: IPv4/IPv6, CIDR, domain, wildcard, localhost, or private
addr = "127.0.0.1"

# Ports: comma-separated list, can specify protocol (e.g. "udp/53,tcp/80,udp/10000-20000,443")
ports = "udp/53"
# Outbound: direct / default / drop / <custom_outbound_name>
outbound = "default"
# Hijack: optional, redirect to specified address
hijack = "1.1.1.1"

[[acl]]
addr = "localhost"
outbound = "drop"

# You can also use 'private' to match all LAN/private IP addresses
# This includes: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 (IPv4)
# and fc00::/7, fe80::/10 (IPv6)
[[acl]]
addr = "private"
outbound = "drop"

# Format 2: Multi-line string format (more concise)
acl = '''
# Format: <outbound_name> <address> [<ports>] [<hijack_address>]
direct localhost tcp/80,tcp/443,udp/443
drop localhost
drop private
default 8.8.4.4 udp/53 1.1.1.1
'''

[users]
# User list: UUID = password
f0e12827-fe60-458c-8269-a05ccb0ff8da = "password"

[tls]
# Use auto-generated self-signed certificate and key
self_sign = false
# Path to certificate file (relative to data_dir if not absolute)
certificate = ""
# Path to private key file (relative to data_dir if not absolute)
private_key = ""
# ALPN protocols (e.g. ["h3"])
alpn = []
# Domain name for certificate issuance or self-sign
hostname = "localhost"
# Enable built-in ACME automatic SSL certificate provisioning
auto_ssl = false

[restful]
# Address to bind RESTful API server
addr = "127.0.0.1:8443"
# Bearer token for API authentication
secret = "YOUR_SECRET_HERE"
# Limit for simultaneous clients per user UUID (0 = unlimited)
maximum_clients_per_user = 0

[quic]
# Congestion control configuration
[quic.congestion_control]
# Congestion control algorithm: bbr, cubic, new_reno
controller = "bbr"
# Initial congestion window size in bytes
initial_window = 1048576

# Initial UDP payload size before MTU discovery
initial_mtu = 1200
# The maximum UDP payload size guaranteed to be supported by the network.
# Must be at least 1200, which is the default, and lower than or equal to initial_mtu
min_mtu = 1200
# Enable Generic Segmentation Offload
gso = true
# Enable Path MTU Discovery
pmtu = true
# Max bytes to transmit to peer without acknowledgment
send_window = 16777216
# Max bytes peer may transmit without acknowledgment per stream
receive_window = 8388608
# How long to wait before closing idle connection
max_idle_time = "30s"

# Experimental features
[experimental]
# Drop connections to loopback addresses (127.0.0.1, ::1) when no explicit ACL rule matches
# This is a built-in safety feature to prevent accidental exposure of localhost services
# Set to false to allow connections to loopback addresses by default
drop_loopback = true

# Drop connections to private/LAN addresses when no explicit ACL rule matches
# This prevents proxying to RFC 1918 private networks:
# - IPv4: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 (link-local)
# - IPv6: fc00::/7 (unique local), fe80::/10 (link-local)
# Set to false to allow connections to private addresses by default
drop_private = true

# Outbound configuration
[outbound]
# Default outbound rule used when no name is specified
[outbound.default]
# Outbound type: direct or socks5
type = "direct"
# IP mode: v4first (prefer IPv4), v6first (prefer IPv6), v4only (IPv4 only), v6only (IPv6 only)
# Legacy aliases: prefer_v4, prefer_v6, only_v4, only_v6
ip_mode = "v4first"

# Named outbound rules - these are referenced from ACL rules
# The named outbound rules get merged into [outbound.named] map in the config
[outbound.prefer_v4]
type = "direct"
ip_mode = "v4first"
# Local addresses to bind for direct connections
bind_ipv4 = "1.2.3.4"
bind_ipv6 = "0:0:0:0:0:ffff:0102:0304"
# Network interface to bind for direct connections
bind_device = "eth1234"

[outbound.through_socks5]
type = "socks5"
# SOCKS5 proxy address
addr = "127.0.0.1:1080"
# SOCKS5 username (optional)
username = "optional"
# SOCKS5 password (optional)
password = "optional"
# Allow UDP when using SOCKS5 outbound (default: false)
allow_udp = false

RESTful API

The server exposes a RESTful API for monitoring and management. Authenticate using the Authorization: Bearer header.

Example:

curl -H 'Authorization: Bearer YOUR_SECRET_HERE' http://ip:port/online

Endpoints:

  • GET /online: List online clients' count.
  • GET /detailed_online: List online clients' IP addresses and ports.
  • POST /kick: Kick specified users (clients can reconnect).
  • GET /traffic: Get current traffic stats.
  • GET /reset_traffic: Reset and return previous traffic stats.

Traffic data is lost when the server restarts.


TLS Certificates

TLS is required for secure connections.

Built-in ACME Support

tuic-server includes built-in ACME support for automatic SSL certificate provisioning via Let's Encrypt. This allows the server to automatically obtain and renew certificates without external tools.

To enable built-in ACME, set the following options in your configuration:

[tls]
auto_ssl = true
hostname = "your.domain.com" # The domain name for certificate issuance

Notes:

  • The server must be accessible from the public internet on port 80 for ACME HTTP-01 challenge.
  • If running as a non-root user on Linux, you may need to allow binding to privileged ports:
    setcap CAP_NET_BIND_SERVICE=+eip <path to tuic-server binary>
    
  • If ACME provisioning fails, tuic-server will fall back to self-signed certificates if configured.

You can also use acme.sh or other tools to manually obtain certificates:

acme.sh --issue -d www.yourdomain.org --standalone
acme.sh --install-cert -d www.yourdomain.org \
  --key-file       /CERT_PATH/key.crt  \
  --fullchain-file /CERT_PATH/cert.crt

Alternatively, you may use self-signed certificates or provide your own.


Contributing

Contributions, bug reports, and feature requests are welcome! Please open issues or pull requests on GitHub.


License

GNU General Public License v3.0. See LICENSE for details.

Tag summary

Content type

Image

Digest

sha256:91f32f229

Size

8 MB

Last updated

2 months ago

docker pull itsusinn/tuic-server