A simple, high performance relay server written in rust.
lib | doc |
---|---|
realm-core | |
realm-io | |
realm-lb | |
realm-hook | |
realm-syscall |
- Zero configuration. Setup and run in one command.
- Concurrency. Bidirectional concurrent traffic leads to high performance.
- Low resources cost.
Realm can be run in a container with OCI (like Docker, Podman, Kubernetes, etc), see guides here.
Install rust toolchain with rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Clone this repository:
git clone https://github.com/zhboner/realm && cd realm
Build:
cargo build --release
You can also pass target_cpu=native
to allow more possible optimizations:
RUSTFLAGS='-C target_cpu=native' cargo build --release
The realm
binary will be available in target/release
.
udp: enable udp relaybuiltin.tfo: enable tcp-fast-opendeprecated.trust-dns: enable trust-dns's async dns resolverbuiltin.zero-copy: enable zero-copy on linuxbuiltin.- brutal-shutdown: see realm_io/brutal-shutdown.
- hook: see realm_hook.
- proxy: enable proxy-protocol.
- balance: enable load balance.
- transport: enable ws/tls/wss.
- batched-udp: enable more efficient udp on linux.
- multi-thread: enable tokio's multi-threaded IO scheduler.
- mi-malloc: custom memory allocator.
- jemalloc: custom memory allocator.
- page-alloc: custom memory allocator.
Default: proxy + balance + transport + batched-udp + brutal-shutdown + multi-thread.
See also: Cargo.toml.
Examples:
# simple tcp
cargo build --release --no-default-features
# enable other options
cargo build --release --features 'jemalloc'
# fully customized
cargo build --release
--no-default-features
--features 'transport, multi-thread, jemalloc'
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.
A high efficiency relay tool
Usage: realm [FLAGS] [OPTIONS]
Commands:
convert convert your legacy configuration into an advanced one
FLAGS:
-h, --help show help
-v, --version show version
-d, --daemon run as a unix daemon
-u, --udp force enable udp forward
-t, --ntcp force disable tcp forward
-6, --ipv6 force disable ipv6 mapped ipv4
-f, --tfo force enable tcp fast open -- deprecated
-z, --splice force enable tcp zero copy -- deprecated
OPTIONS:
-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
SYS OPTIONS:
-n, --nofile <limit> set nofile limit
-p, --pipe-page <number> set pipe capacity
-j, --pre-conn-hook <path> set pre-connect hook
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> send proxy protocol header
--send-proxy-version <version> send proxy protocol version
--accept-proxy <accept_proxy> accept proxy protocol header
--accept-proxy-timeout <second> accept proxy protocol timeout
TIMEOUT OPTIONS:
--tcp-timeout <second> override tcp timeout(5s)
--udp-timeout <second> override udp timeout(30s)
--tcp-keepalive <second> override default tcp keepalive interval(15s)
--tcp-keepalive-probe <count> override default tcp keepalive count(3)
Start from command line arguments:
realm -l 0.0.0.0:5000 -r 1.1.1.1:443
Start with config file:
# use toml
realm -c config.toml
# use json
realm -c config.json
# use configs in folder (since v2.6.2)
# all toml and json files are recursively included (e.g.: config/log.toml, config/node/n1.toml)
# hidden ones are recursively excluded (e.g.: config/.hidden_file, config/.hidden_dir/)
realm -c config/
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 = "realm.log"
[network]
no_tcp = false
use_udp = 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": {
"no_tcp": false,
"use_udp": 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
│ ├── no_tcp
│ ├── use_udp
│ ├── ipv6_only
│ ├── tcp_timeout
│ ├── udp_timeout
│ ├── tcp_keepalive
│ ├── tcp_keepalive_probe
│ ├── send_proxy
│ ├── send_proxy_version
│ ├── accept_proxy
│ └── accept_proxy_timeout
└── endpoints
├── listen
├── remote
├── extra_remotes
├── balance
├── 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.
Local address, supported formats:
- ipv4:port
- ipv6:port
Remote address, supported formats:
- ipv4:port
- ipv6:port
- example.com:port
Extra remote address, same as endpoint.remote above.
Require balance
feature.
Load balance strategy and weights of remote peers.
Format:
$strategy: $weight1, $weight2, ...
Where remote
is used as default backend server, and extra_remotes
are used as backups.
Available algorithms (provided by realm_lb):
-
iphash
-
roundrobin
Example:
[[endpoints]]
remote = "a:443"
extra_remotes = ["b:443", "c:443"]
balance = "roundrobin: 4, 2, 1"
The weight of [a, b, c] is [4, 2, 1] in turn.
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 transport
feature.
See Kaminari Options.
Require transport
feature.
See Kaminari Options.
The same as network, override global options.
values:
- off
- error
- warn
- info
- debug
- trace
default: off
values:
- stdout
- stderr
- path (e.g.
/var/log/realm.log
)
default: stdout
Require 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
Do not start a tcp relay.
default: false
Require 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
Disable ipv4-mapped-ipv6 when binding to an ipv6 address.
E.g.:
[::0]:port
with (ipv6_only=false) binds to *:port
[::0]:port
with (ipv6_only=true) binds to [::]:port
default: false
Require 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 fast-open
feature.
It is not recommended to enable this option, see The Sad Story of TCP Fast Open.
default: false
This is connect timeout. An attempt to connect to a remote peer fails after waiting for a period of time.
To disable timeout, you need to explicitly set timeout value to 0.
default: 5
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
TCP Keepalive interval.
On Linux, this is equivalent to setting both net.ipv4.tcp_keepalive_time
and net.ipv4.tcp_keepalive_intvl
.
To use system's tcp keepalive interval, you need to explicitly set this option to 0.
default: 15
TCP Keepalive retries.
On Linux, this is equivalent to ipv4.tcp_keepalive_probes
.
default: 3
Require proxy
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
Require proxy
feature.
This option has no effect unless send_proxy is enabled.
value:
- 1
- 2
default: 2
Require proxy
feature.
Wait for a 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
Require proxy
feature.
Wait for a PROXY header within a period of time, otherwise close the connection.
default: 5.