A fast, secure and stable reverse proxy for NAT traversal, written in Rust
rathole, like frp, can help to expose the service on the device behind the NAT to the Internet, via a server with a public IP.
To use rathole, you need a server with a public IP, and a device behind the NAT, where some services that need to be exposed to the Internet.
Assuming you have a NAS at home behind the NAT, and want to expose its ssh service to the Internet:
Create server.toml
with the following content and accommodate it to your needs.
```toml
[server]
bind_addr = "0.0.0.0:2333" # 2333
specifys the port that rathole listens for clients
[server.services.mynasssh]
token = "useasecretthatonlyyouknow" # Token that is used to authenticate the client for the service. Change to a arbitrary value.
bind_addr = "0.0.0.0:5202" # 5202
specifys the port that exposes my_nas_ssh
to the Internet
```
Then run:
bash
./rathole server.toml
Create client.toml
with the following content and accommodate it to your needs.
``toml
[client]
remote_addr = "myserver.com:2333" # The address of the server. The port must be the same with the port in
server.bind_addr`
[client.services.mynasssh] token = "useasecretthatonlyyouknow" # Must be the same with the server to pass the validataion local_addr = "127.0.0.1:22" # The address of the service that needs to be forwarded ```
Then run:
bash
./rathole client.toml
myserver.com
on port 2333
, and any traffic to myserver.com:5202
will be forwarded to the client's port 22
.So you can ssh myserver.com:5202
to ssh to your NAS.
rathole
can automatically determine to run in the server mode or the client mode, according to the content of the configuration file, if only one of [server]
and [client]
block is present, like the example in Quickstart.
But the [client]
and [server]
block can also be put in one file. Then on the server side, run rathole --server config.toml
and on the client side, run rathole --client config.toml
to explictly tell rathole
the running mode.
Some configuration examples are provided under examples.
The Noise Protocol can be easily used to secure the traffic, see Security.
Here is the full configuration specification: ```toml [client] remoteaddr = "example.com:2333" # Necessary. The address of the server defaulttoken = "defaulttokenifnotspecify" # Optional. The default token of services, if they don't define their own ones
[client.transport] # The whole block is optional. Specify which transport to use type = "tcp" # Optional. Possible values: ["tcp", "tls", "noise"]. Default: "tcp"
[client.transport.tls] # Necessary if type
is "tls"
trusted_root = "ca.pem" # Necessary. The certificate of CA that signed the server's certificate
hostname = "example.com" # Optional. The hostname that the client uses to validate the certificate. If not set, fallback to client.remote_addr
[client.transport.noise] # Noise protocol. See docs/security.md
for further explanation
pattern = "NoiseNK25519ChaChaPolyBLAKE2s" # Optional. Default value as shown
localprivatekey = "keyencodedinbase64" # Optional
remotepublickey = "keyencodedinbase64" # Optional
[client.services.service1] # A service that needs forwarding. The name service1
can change arbitrarily, as long as identical to the name in the server's configuration
type = "tcp" # Optional. The protocol that needs forwarding. Possible values: ["tcp", "udp"]. Default: "tcp"
token = "whatever" # Necessary if client.default_token
not set
local_addr = "127.0.0.1:1081" # Necessary. The address of the service that needs to be forwarded
[client.services.service2] # Multiple services can be defined local_addr = "127.0.0.1:1082"
[server] bindaddr = "0.0.0.0:2333" # Necessary. The address that the server listens for clients. Generally only the port needs to be change. defaulttoken = "defaulttokenifnotspecify" # Optional
[server.transport] # Same as [client.transport]
type = "tcp"
[server.transport.tls] # Necessary if type
is "tls"
pkcs12 = "identify.pfx" # Necessary. pkcs12 file of server's certificate and private key
pkcs12_password = "password" # Necessary. Password of the pkcs12 file
[server.transport.noise] # Same as [client.transport.noise]
pattern = "NoiseNK25519ChaChaPolyBLAKE2s"
localprivatekey = "keyencodedinbase64"
remotepublickey = "keyencodedinbase64"
[server.services.service1] # The service name must be identical to the client side
type = "tcp" # Optional. Same as the client [client.services.X.type]
token = "whatever" # Necesary if
server.defaulttoken` not set
bindaddr = "0.0.0.0:8081" # Necessary. The address of the service is exposed at. Generally only the port needs to be change.
[server.services.service2] bind_addr = "0.0.0.1:8082" ```
rathole
, like many other Rust programs, use environment variables to control the logging level. info
, warn
, error
, debug
, trace
are avialable.
RUST_LOG=error ./rathole config.toml
will run rathole
with only error level logging.
If RUST_LOG
is not present, the default logging level is info
.
rathole has similiar latency to frp, but can handle more connections. Also it can provide much better bandwidth than frp.
See also Benchmark.
rathole
is in active development. A load of features is on the way:
- [x] TLS support
- [x] UDP support
- [ ] Hot reloading
- [ ] HTTP APIs for configuration