Realm is a simple, high performance relay server written in rust.
- Zero configuration. Setup and run in one command.
- Concurrency. Bidirectional concurrent traffic leads to high performance.
- Low resources cost.
With transport
feature, Realm is able to handle [ws/tls/wss] on both sides. This is powered by libkaminari, which is dramatically faster in comparison to other implements. Here are some benchmark results.
Realm can be run in a container with OCI (like Docker, Podman, Kubernetes, etc), see guides here.
Install rust nightly toolchains with rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Clone this repository:
git clone https://github.com/zhboner/realm
Enter the directory and build:
cd realm
git submodule sync && git submodule update --init --recursive
# build release
cargo build --release
# allow more possible optimizations, make it even faster
RUSTFLAGS='-C target_cpu=native' cargo build --release
- udp: enable udp relay.
- trust-dns: enable trust-dns's async dns resolver.
- zero-copy: enable zero-copy on linux.
- transport: enable ws/tls/wss.
- transport-boost: enable optimizations for transport, at the cost of increasing binary size.
- multi-thread: enable tokio's multi-threaded IO scheduler.
- brutal-shutdown: see realm_io/brutal-shutdown.
- tfo: enable tcp-fast-open.
- mi-malloc: custom memory allocator.
- jemalloc: custom memory allocator.
Default: udp + trust-dns + zero-copy + multi-thread + transport + transport-boost.
See also: Cargo.toml
.
Examples:
# simple tcp
cargo build --release --no-default-features
# enable other options
cargo build --release --no-default-features --features udp,tfo,zero-copy,trust-dns..
Please refer to https://rust-lang.github.io/rustup/cross-compilation.html. You may need to install cross-compilers or other SDKs, and specify them when building the project.
Or have a look at Cross, it makes things easier.
Realm 2.x [udp][zero-copy][trust-dns][proxy-protocol][transport][multi-thread]
A high efficiency relay tool
USAGE:
realm [FLAGS] [OPTIONS]
FLAGS:
-h, --help show help
-v, --version show version
-d, --daemon run as a unix daemon
-u, --udp force enable udp forward
-f, --tfo force enable tcp fast open
-z, --splice force enable tcp zero copy
OPTIONS:
-n, --nofile <limit> set nofile limit
-p, --page <number> set pipe capacity
-c, --config <path> use config file
-l, --listen <address> listen address
-r, --remote <address> remote address
-x, --through <address> send through ip or address
-i, --interface <device> bind to interface
-a, --listen-transport <options> listen transport
-b, --remote-transport <options> remote transport
LOG OPTIONS:
--log-level <level> override log level
--log-output <path> override log output
DNS OPTIONS:
--dns-mode <mode> override dns mode
--dns-min-ttl <second> override dns min ttl
--dns-max-ttl <second> override dns max ttl
--dns-cache-size <number> override dns cache size
--dns-protocol <protocol> override dns protocol
--dns-servers <servers> override dns servers
PROXY OPTIONS:
--send-proxy send proxy protocol header
--send-proxy-version <version> send proxy protocol version
--accept-proxy accept proxy protocol header
--accept-proxy-timeout <second> accept proxy protocol timeout
TIMEOUT OPTIONS:
--tcp-timeout <second> override tcp timeout
--udp-timeout <second> override udp timeout
SUBCOMMANDS:
convert convert your legacy configuration into an advanced one
Start from command line arguments:
realm -l 0.0.0.0:5000 -r 1.1.1.1:443
Start with a config file:
# use toml
realm -c config.toml
# use json
realm -c config.json
Start with environment variables:
REALM_CONF='{"endpoints":[{"local":"127.0.0.1:5000","remote":"1.1.1.1:443"}]}' realm
# or
export REALM_CONF=`cat config.json | jq -c `
realm
Convert a legacy config file:
realm convert old.json
TOML Example
[log]
level = "warn"
output = "/var/log/realm.log"
[network]
use_udp = true
zero_copy = true
[[endpoints]]
listen = "0.0.0.0:5000"
remote = "1.1.1.1:443"
[[endpoints]]
listen = "0.0.0.0:10000"
remote = "www.google.com:443"
JSON Example
{
"log": {
"level": "warn",
"output": "/var/log/realm.log"
},
"network": {
"use_udp": true,
"zero_copy": true
},
"endpoints": [
{
"listen": "0.0.0.0:5000",
"remote": "1.1.1.1:443"
},
{
"listen": "0.0.0.0:10000",
"remote": "www.google.com:443"
}
]
}
├── log
│ ├── level
│ └── output
├── dns
│ ├── mode
│ ├── protocol
│ ├── nameservers
│ ├── min_ttl
│ ├── max_ttl
│ └── cache_size
├── network
│ ├── use_udp
│ ├── zero_copy
│ ├── fast_open
│ ├── tcp_timeout
│ ├── udp_timeout
│ ├── send_proxy
│ ├── send_proxy_version
│ ├── accept_proxy
│ └── accept_proxy_timeout
└── endpoints
├── listen
├── remote
├── through
├── interface
├── listen_transport
├── remote_transport
└── network
You should provide at least endpoint.listen and endpoint.remote, the left fields will take their default values.
Option priority: cmd override > endpoint config > global config
values:
- off
- error
- warn
- info
- debug
- trace
default: off
values:
- stdout
- stderr
- path (e.g.
/var/log/realm.log
)
default: stdout
Require the trust-dns
feature
Dns resolve strategy.
values:
- ipv4_only
- ipv6_only
- ipv4_then_ipv6
- ipv6_then_ipv4
- ipv4_and_ipv6
default: ipv4_and_ipv6
Dns transport protocol.
values:
- tcp
- udp
- tcp_and_udp
default: tcp_and_udp
Custom upstream servers.
format: ["server1", "server2" ...]
default:
If on unix/windows, read from the default location.(e.g. /etc/resolv.conf
).
Otherwise, use google's public dns(8.8.8.8:53
, 8.8.4.4:53
and 2001:4860:4860::8888:53
, 2001:4860:4860::8844:53
).
The minimum lifetime of a positive dns cache
default: 0
The maximum lifetime of a positive dns cache
default: 86400 (1 day)
The maximum count of dns cache
default: 32
Require the udp
feature
Start listening on a udp endpoint and forward packets to the remote peer.
It will dynamically allocate local endpoints and establish udp associations. Once timeout, the endpoints will be deallocated and the association will be terminated. See also: network.udp_timeout
Due to the receiver side not limiting access to the association, the relay works like a full-cone NAT.
default: false
Require the zero-copy
feature
Use splice
instead of send/recv
while handing tcp connection. This will save a lot of memory copies and context switches.
default: false
Require the fast-open
feature
It is not recommended to enable this option, see The Sad Story of TCP Fast Open.
default: false
Close the connection if the peer does not send any data during timeout
.
This option remains unimplemented! (since ce5213)
To disable timeout, you need to explicitly set timeout value to 0.
default: 300
Terminate udp association after timeout
.
The timeout value must be properly configured in case of memory leak. Do not use a large timeout
!
default: 30
Requires the proxy-protocol
feature
Send haproxy PROXY header once the connection established. Both v1
and v2
are supported, see send_proxy_version.
You should make sure the remote peer also speaks proxy-protocol.
default: false
Requires the proxy-protocol
feature
This option has no effect unless send_proxy is enabled.
value:
- 1
- 2
default: 2
Requires the proxy-protocol
feature
Wait for PROXY header once the connection established.
If the remote sender does not send a v1
or v2
header before other contents, the connection will be closed.
default: false
Local address, supported formats:
- ipv4:port
- ipv6:port
Remote address, supported formats:
- ipv4:port
- ipv6:port
- example.com:port
TCP: Bind a specific ip
before opening a connection
UDP: Bind a specific ip
or address
before sending packet
Supported formats:
- ipv4/ipv6 (tcp/udp)
- ipv4/ipv6:port (udp)
Bind to a specific interface
Require the transport
feature
See Kaminari Options
Require the transport
feature
See Kaminari Options
The same as network, override global options.