Yet another trojan-gfw implementation in Rust.
- Server mode only (for now).
- Supports Redis auth & flow stat.
- Uses OpenSSL as crypto backend.
- Uses tokio as async runtime.
- Accurate flow stat (includes TLS overhead).
- Not a TLS connection or TLS handshake failed: Connection Reset. (including SNI mismatch if not present in cert SAN)
- SNI mismatch: Redirect to fallback
- Expected TLS but not a trojan request: Redirect to fallback.
- Trojan request but password incorrect: Redirect to fallback.
- Trojan request and password correct: Work as a proxy tunnel.
- Not HTTP Request: 400 Bad Request
- HTTP Request:
- GET: 404 Not Found
- Other: 405 Methon Not Allowed
This is like most cdn endpoints' behavior if you don't have a correct resource path.
cargo build --release
USAGE:
trojan-rust [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --config <config> [default: config.toml]
--log-level <log-level> [env: LOGLEVEL=] [default: info]
docker run -p 443:443 llc1123/trojan-rust example.toml
# or use github container registry
docker run -p 443:443 ghcr.io/llc1123/trojan-rust example.toml
example.toml
# mode = "server" # optional
## uses default values if not present
# [trojan]
# password = [] # optional
## uses built-in if not present
# fallback = "baidu.com:80" # optional
[tls]
# listen = "0.0.0.0:443" # optional
# tcp_nodelay = false # optional
# sni = [] # optional
cert = "fullchain.pem" # required
key = "privkey.pem" # required
## uses default values if not present
# [outbound]
## Useful when you don't want your clients have access to your local network especially the redis server.
# block_local = false # optional
## doesn't use redis if not present
# [redis]
# server = "127.0.0.1:6379" # optional
You can use as many hostnames as they are contained in the certificate provided. Or use all hostnames in the certificate SAN if left absent or empty.
For example:
SAN in cert: a.example.com b.example.com
SNI: []
a.example.com ✔️
b.example.com ✔️
other.com ❌
SAN in cert: a.example.com b.example.com
SNI: ["a.example.com"]
a.example.com ✔️
b.example.com ❌
other.com ❌
SAN in cert: a.example.com b.example.com
SNI: ["a.example.com", "b.example.com"]
a.example.com ✔️
b.example.com ✔️
other.com ❌
SAN in cert: a.example.com b.example.com
SNI: ["c.example.com"]
Error on startup
Trojan-rust supports wildcard certificates.
For example:
SAN in cert: *.example.com
SNI: []
a.example.com ✔️
b.example.com ✔️
example.com ❌ // doesn't match wildcard
a.b.example.com ❌ // doesn't match wildcard
other.com ❌
SAN in cert: *.example-a.com, *.example-b.com
SNI: []
a.example-a.com ✔️
a.example-b.com ✔️
other.com ❌
SAN in cert: *.example.com, example.com
SNI: []
example.com ✔️
a.example.com ✔️
other.com ❌
SAN in cert: *.example.com, example.com
SNI: ["example.com"]
example.com ✔️
a.example.com ❌
other.com ❌
SAN in cert: *.example.com
SNI: ["a.example.com"]
a.example.com ✔️
b.example.com ❌
other.com ❌
SAN in cert: *.example.com, example.com
SNI: ["*.example.com"]
a.example.com ✔️
b.example.com ✔️
example.com ❌
other.com ❌
Add a user:
HSET [sha224(password)] download 0 upload 0
Trojan-rust checks if the hash exists in redis on each connection. If true, the user is authenticated and the flow will be recorded.
Trojan-rust DOES NOT offer a method adding or removing a user. Please do it by yourself.
Don't forget to enable block_local
feature to avoid attacks.
Enabled by setting environment variable SSLKEYLOGFILE=filename
.
For debug use only. Never use in production.
- Client mode
- TPROXY mode
- Benchmarks
- Wildcards in SNI config
PRs welcome
Trojan-rust is MIT licensed.