A VMess relay written in Rust.
TOBIRA accepts plain VMess+TCP inbound traffic, validates only the VMess Auth ID, and relays encrypted streams to upstream nodes without full payload inspection/decryption.
- π Subscription Aggregation: Load VMess subscriptions from multiple HTTP(S) and local file sources
- π§© Dual VMess Parsing: Supports both
vmess://base64(json)(v2rayN) andvmess://uuid@host:port?...URL format - π οΈ Processing Pipeline: Filter/remove/rename/remove-emoji/override-security by node name and source
- π Basic Auth for Subscriptions: Optional HTTP Basic Auth with per-user output restrictions
- π Multiple Output Views: Expose multiple
/sub/<name>outputs with independent host/port rewrite + pipeline - β‘ Inspect-free Relay Path: Route by Auth ID and forward bytes directly (TCP Fast Open on inbound/outbound TCP)
- π‘ TCP + gRPC Upstream: Relay to classic VMess TCP upstreams and VMess over TLS+gRPC upstreams (connection pool + stream reuse)
- β»οΈ Hot Reload: Full reload by
SIGUSR1or config-file change; periodic subscription-only refresh by timer - πΎ Cache Fallback: Per-source cache fallback when subscription fetch fails
- β Safety Checks: Duplicate UUID detection during routing table build
ββββββββββββββββββββββββββββ
β Subscription Sources β
β (HTTP/HTTPS or files) β
ββββββββββββββ¬ββββββββββββββ
β load + parse VMess
βΌ
ββββββββββββββββββββββββββββ
β Process Pipeline β
β β’ filter/source filter β
β β’ remove/rename β
β β’ remove_emoji/security β
ββββββββββββββ¬ββββββββββββββ
β build nodes + cache
βΌ
ββββββββββββββββββββββββββββ
β Validator (UUID/Auth ID) β
ββββββββββββββ¬ββββββββββββββ
β route by first 16 bytes
βΌ
ββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
β TOBIRA Relay Inbound βββββββΆβ Upstream Relay β
β β’ VMess + TCP β β β’ TCP (TFO) β
β β’ inspect-free forwarding β β β’ TLS + gRPC (pooled H2) β
ββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββ
β HTTP Subscription Server β
β /sub /sub/<name> ... β
ββββββββββββββββββββββββββββ
cd tobira
cargo build --releaseBinary path:
./target/release/tobiracd tobira
docker build -t tobira:latest .Create config.toml (see config.example.toml).
listen: relay bind address (default:[::])port: relay inbound port (required)
Note: relay listener bind fields are not re-bound by hot reload. Changing relay.listen/relay.port requires process restart.
listen: HTTP bind address (default:[::])port: HTTP port (default:8080)[[http.users]]: Basic Auth usersusername,password- optional
outputs = ["main", ...]to restrict visible outputs
[[http.outputs]]: named subscription outputsname: output name for/sub/<name>host,port: rewritten relay endpoint written into exported linkssni: optional TLS SNI for gRPC/TLS relay linksskip-cert-verify: optional TLS certificate verification skip for gRPC/TLS relay links[[http.outputs.process]]: per-output processing pipeline
cache_file: JSON cache path used as source fallbackupdate_interval: periodic subscription refresh interval in seconds (0disables timer)[[subscription.sources]]: source definitionsname: source nameurl: HTTP/HTTPS subscription URLpath: local subscription file path- relative
pathvalues are resolved from the directory containingconfig.toml - exactly one of
urlorpathis required user_agent: optional HTTP User-Agent forurlsources[[subscription.sources.process]]: per-source processing pipeline
Each process step supports:
filter: regex list matched against node namefilter_source: regex list matched against source nameinvert: invert selection resultremove: remove selected nodesrename: regex rename rules ([[pattern, replacement], ...])remove_emoji: remove emoji characters from node nameoverride_security: override VMess encryption/security fieldpacket_encoding: override packet encoding ("","none","packetaddr", or"xudp")
./target/release/tobira --config config.tomlShort form:
./target/release/tobira -c config.toml- Full reload (re-read config + refetch subscriptions):
SIGUSR1- config file modify/create event
- Subscription-only reload (uses in-memory config):
- periodic timer controlled by
subscription.update_interval
- periodic timer controlled by
Manual full reload:
kill -USR1 <pid>RUST_LOG overrides log_level in config.toml.
Supported endpoints:
GET /sub: all allowed outputs, format auto-selected fromUser-Agent(v2rayN/...orv2rayNG/...β v2rayN,Shadowrocket/...β Shadowrocket)GET /sub/base64andGET /sub/v2rayn: all allowed outputs, VMess JSON link formatGET /sub/standard: all allowed outputs, raw VMess URL link format (/sub/urlkept as compatibility alias)GET /sub/shadowrocket: all allowed outputs, Shadowrocket VMess link format with a base64 envelopeGET /sub/<name>: one named output, format auto-selected fromUser-AgentGET /sub/<name>/base64andGET /sub/<name>/v2rayn: one named output, VMess JSON link formatGET /sub/<name>/standard: one named output, raw VMess URL link format (/sub/<name>/urlkept as compatibility alias)GET /sub/<name>/shadowrocket: one named output, Shadowrocket VMess link format with a base64 envelope
Authentication:
- If
[[http.users]]is configured, Basic Auth is required. - If no users are configured, anonymous access is allowed.
Examples:
# JSON-format links (base64 envelope)
curl -u alice:s3cr3t http://127.0.0.1:8080/sub/main | base64 -d
# URL-format links (raw newline-separated vmess:// URLs)
curl -u alice:s3cr3t http://127.0.0.1:8080/sub/main/standard
# Shadowrocket-format links (base64 envelope)
curl -u alice:s3cr3t http://127.0.0.1:8080/sub/main/shadowrocket | base64 -d[[subscription.sources]]
name = "local"
path = "subscriptions/local.txt"[[subscription.sources.process]]
filter_source = ["free_sub"]
remove = true[[http.outputs.process]]
filter = ["(?i)premium"]
invert = true
remove = true[[http.outputs.process]]
remove_emoji = true
rename = [["^US\\s*", "US-"], ["^HK\\s*", "HK-"]]
override_security = "aes-128-gcm"TOBIRA requires each upstream node UUID to be unique across all loaded sources. Remove duplicates or filter them out in process pipeline steps.
Check your Basic Auth credentials, or remove [[http.users]] entries to allow anonymous access.
This repository is licensed under GNU Affero General Public License v3.0 or later.
SPDX-License-Identifier: AGPL-3.0-or-later