rathole
A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.
Top Related Projects
A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.
Minimal, self-hosted, 0-config alternative to ngrok. Caddy+OpenSSH+50 lines of Python.
一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。a lightweight, high-performance, powerful intranet penetration proxy server, with a powerful web management terminal.
Unified ingress for developers
GO Simple Tunnel - a simple tunnel written in golang
Quick Overview
Rathole is a lightweight and high-performance reverse proxy tool designed for NAT traversal. It allows users to expose local servers behind NATs and firewalls to the internet, making it easier to access services remotely or host applications from home networks.
Pros
- Fast and efficient, with low resource usage
- Supports both TCP and UDP protocols
- Encrypted communication for enhanced security
- Cross-platform compatibility (Windows, macOS, Linux)
Cons
- Limited documentation, especially for advanced use cases
- Lacks some features found in more comprehensive reverse proxy solutions
- May require additional configuration for complex network setups
Getting Started
To get started with Rathole, follow these steps:
- Download the latest release from the GitHub repository.
- Create a configuration file for both the server and client sides.
- Run the Rathole server on a machine with a public IP address:
./rathole server.toml
- Run the Rathole client on the machine with the local service you want to expose:
./rathole client.toml
- Configure your firewall and port forwarding settings as needed.
For a basic TCP forwarding setup, use the following configuration files:
Server configuration (server.toml):
[server]
bind_addr = "0.0.0.0:2333"
[server.services.my_service]
token = "your_secret_token"
bind_addr = "0.0.0.0:8080"
Client configuration (client.toml):
[client]
remote_addr = "your_server_ip:2333"
[client.services.my_service]
token = "your_secret_token"
local_addr = "127.0.0.1:80"
This configuration will forward traffic from the server's port 8080 to the client's local port 80.
Competitor Comparisons
A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.
Pros of frp
- More mature project with a larger community and ecosystem
- Supports a wider range of protocols and features
- Offers a web-based dashboard for easier management
Cons of frp
- Higher resource usage and larger binary size
- More complex configuration and setup process
- Slower startup time compared to rathole
Code Comparison
frp configuration example:
[common]
server_addr = x.x.x.x
server_port = 7000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
rathole configuration example:
[client]
remote_addr = "x.x.x.x:2333"
[client.services.ssh]
type = "tcp"
local_addr = "127.0.0.1:22"
Both projects aim to provide NAT traversal and intranet penetration solutions, but they differ in their approach and feature set. frp offers a more comprehensive set of features and supports a wider range of protocols, making it suitable for complex setups. However, this comes at the cost of increased resource usage and complexity.
rathole, on the other hand, focuses on simplicity and efficiency, providing a lightweight alternative with faster startup times and lower resource consumption. It may be more suitable for simpler setups or resource-constrained environments.
Minimal, self-hosted, 0-config alternative to ngrok. Caddy+OpenSSH+50 lines of Python.
Pros of SirTunnel
- Simple setup with minimal configuration required
- Built-in web interface for easy management
- Supports WebSocket connections, making it suitable for web applications
Cons of SirTunnel
- Limited protocol support compared to rathole
- Less actively maintained with fewer recent updates
- May have lower performance for high-traffic scenarios
Code Comparison
SirTunnel (JavaScript):
const tunnel = new SirTunnel({
localPort: 8080,
remotePort: 80,
hostname: 'example.com'
});
tunnel.start();
rathole (Rust):
let config = Config::load("config.toml")?;
let server = Server::new(config)?;
server.run().await?;
Key Differences
- SirTunnel is written in JavaScript, while rathole is implemented in Rust
- rathole offers more advanced features like TCP/UDP forwarding and encryption
- SirTunnel focuses on simplicity and ease of use for web-based applications
- rathole provides better performance and resource efficiency due to its Rust implementation
Both projects aim to provide tunneling solutions, but they cater to different use cases and levels of complexity. SirTunnel is more suitable for quick setups and web-focused applications, while rathole offers a more comprehensive and performant solution for various tunneling needs.
一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。a lightweight, high-performance, powerful intranet penetration proxy server, with a powerful web management terminal.
Pros of nps
- More comprehensive feature set, including web management interface and multi-protocol support
- Better suited for complex networking scenarios and enterprise environments
- Offers built-in encryption and compression options
Cons of nps
- Higher resource usage and complexity compared to rathole
- Steeper learning curve for configuration and setup
- Less focus on simplicity and lightweight operation
Code Comparison
nps (Go):
bridge := bridge.NewTcpBridge(tp.vKey, tp.bridgeConnType, tp.sendChan, tp.linkMap, tp.runList)
go bridge.StartTcpServer(config.CommonConfig.ProxyPort)
rathole (Rust):
let server = Server::new(config)?;
server.run().await?;
Summary
nps is a more feature-rich and versatile solution, offering a wide range of networking capabilities and management tools. It's better suited for complex scenarios but comes with increased complexity and resource usage. rathole, on the other hand, focuses on simplicity and lightweight operation, making it easier to set up and use for basic port forwarding needs. The code comparison highlights the difference in complexity, with nps requiring more setup and configuration compared to rathole's more straightforward approach.
Unified ingress for developers
Pros of ngrok
- More established and widely used, with a larger community and ecosystem
- Offers a user-friendly web interface for managing tunnels and inspecting traffic
- Provides additional features like OAuth and custom domains out of the box
Cons of ngrok
- Closed-source and proprietary, limiting customization and self-hosting options
- Free tier has limitations on concurrent tunnels and connection duration
- Can be more resource-intensive, especially for simple tunneling needs
Code Comparison
ngrok (Python client):
import ngrok
# Start a tunnel
public_url = ngrok.connect(8000)
print(f"Public URL: {public_url}")
rathole (Rust configuration):
[client]
remote_addr = "example.com:2333"
[client.services.http]
local_addr = "127.0.0.1:8000"
Key Differences
- ngrok offers a more comprehensive solution with built-in features and a web interface, while rathole focuses on lightweight, efficient tunneling
- rathole is open-source and self-hostable, providing more flexibility for custom deployments
- ngrok has a simpler setup process for basic use cases, while rathole requires more configuration but offers greater control
Both projects aim to solve similar problems, but cater to different user needs and preferences. ngrok is better suited for quick setups and feature-rich environments, while rathole is ideal for users who prioritize customization, efficiency, and self-hosting capabilities.
GO Simple Tunnel - a simple tunnel written in golang
Pros of gost
- More comprehensive feature set, including support for multiple protocols (HTTP, SOCKS4, SOCKS5, etc.)
- Offers a wider range of encryption and obfuscation options
- Includes a built-in web interface for easier management
Cons of gost
- More complex configuration due to its extensive feature set
- Potentially higher resource usage compared to rathole's lightweight design
- May have a steeper learning curve for new users
Code Comparison
rathole configuration example:
[client]
remote_addr = "example.com:2333"
[client.services.ssh]
local_addr = "127.0.0.1:22"
gost configuration example:
gost -L=:8080 -F=ss://method:password@server_ip:server_port
Both projects aim to provide secure tunneling solutions, but they differ in their approach and complexity. rathole focuses on simplicity and ease of use, while gost offers a more feature-rich experience with support for various protocols and advanced configurations. The choice between the two depends on the specific requirements of the user's project and their level of expertise in networking and tunneling technologies.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
rathole
A secure, stable and high-performance reverse proxy for NAT traversal, written in Rust
rathole, like frp and ngrok, can help to expose the service on the device behind the NAT to the Internet, via a server with a public IP.
Features
- High Performance Much higher throughput can be achieved than frp, and more stable when handling a large volume of connections. See Benchmark
- Low Resource Consumption Consumes much fewer memory than similar tools. See Benchmark. The binary can be as small as ~500KiB to fit the constraints of devices, like embedded devices as routers.
- Security Tokens of services are mandatory and service-wise. The server and clients are responsible for their own configs. With the optional Noise Protocol, encryption can be configured at ease. No need to create a self-signed certificate! TLS is also supported.
- Hot Reload Services can be added or removed dynamically by hot-reloading the configuration file. HTTP API is WIP.
Quickstart
A full-powered rathole
can be obtained from the release page. Or build from source for other platforms and minimizing the binary. A Docker image is also available.
The usage of rathole
is very similar to frp. If you have experience with the latter, then the configuration is very easy for you. The only difference is that configuration of a service is split into the client side and the server side, and a token is mandatory.
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:
- On the server which has a public IP
Create server.toml
with the following content and accommodate it to your needs.
# server.toml
[server]
bind_addr = "0.0.0.0:2333" # `2333` specifies the port that rathole listens for clients
[server.services.my_nas_ssh]
token = "use_a_secret_that_only_you_know" # Token that is used to authenticate the client for the service. Change to an arbitrary value.
bind_addr = "0.0.0.0:5202" # `5202` specifies the port that exposes `my_nas_ssh` to the Internet
Then run:
./rathole server.toml
- On the host which is behind the NAT (your NAS)
Create client.toml
with the following content and accommodate it to your needs.
# client.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.my_nas_ssh]
token = "use_a_secret_that_only_you_know" # Must be the same with the server to pass the validation
local_addr = "127.0.0.1:22" # The address of the service that needs to be forwarded
Then run:
./rathole client.toml
- Now the client will try to connect to the server
myserver.com
on port2333
, and any traffic tomyserver.com:5202
will be forwarded to the client's port22
.
So you can ssh myserver.com:5202
to ssh to your NAS.
To run rathole
run as a background service on Linux, checkout the systemd examples.
Configuration
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 explicitly tell rathole
the running mode.
Before heading to the full configuration specification, it's recommend to skim the configuration examples to get a feeling of the configuration format.
See Transport for more details about encryption and the transport
block.
Here is the full configuration specification:
[client]
remote_addr = "example.com:2333" # Necessary. The address of the server
default_token = "default_token_if_not_specify" # Optional. The default token of services, if they don't define their own ones
heartbeat_timeout = 40 # Optional. Set to 0 to disable the application-layer heartbeat test. The value must be greater than `server.heartbeat_interval`. Default: 40 seconds
retry_interval = 1 # Optional. The interval between retry to connect to the server. Default: 1 second
[client.transport] # The whole block is optional. Specify which transport to use
type = "tcp" # Optional. Possible values: ["tcp", "tls", "noise"]. Default: "tcp"
[client.transport.tcp] # Optional. Also affects `noise` and `tls`
proxy = "socks5://user:passwd@127.0.0.1:1080" # Optional. The proxy used to connect to the server. `http` and `socks5` is supported.
nodelay = true # Optional. Determine whether to enable TCP_NODELAY, if applicable, to improve the latency but decrease the bandwidth. Default: true
keepalive_secs = 20 # Optional. Specify `tcp_keepalive_time` in `tcp(7)`, if applicable. Default: 20 seconds
keepalive_interval = 8 # Optional. Specify `tcp_keepalive_intvl` in `tcp(7)`, if applicable. Default: 8 seconds
[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/transport.md` for further explanation
pattern = "Noise_NK_25519_ChaChaPoly_BLAKE2s" # Optional. Default value as shown
local_private_key = "key_encoded_in_base64" # Optional
remote_public_key = "key_encoded_in_base64" # Optional
[client.transport.websocket] # Necessary if `type` is "websocket"
tls = true # If `true` then it will use settings in `client.transport.tls`
[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
nodelay = true # Optional. Override the `client.transport.nodelay` per service
retry_interval = 1 # Optional. The interval between retry to connect to the server. Default: inherits the global config
[client.services.service2] # Multiple services can be defined
local_addr = "127.0.0.1:1082"
[server]
bind_addr = "0.0.0.0:2333" # Necessary. The address that the server listens for clients. Generally only the port needs to be change.
default_token = "default_token_if_not_specify" # Optional
heartbeat_interval = 30 # Optional. The interval between two application-layer heartbeat. Set to 0 to disable sending heartbeat. Default: 30 seconds
[server.transport] # Same as `[client.transport]`
type = "tcp"
[server.transport.tcp] # Same as the client
nodelay = true
keepalive_secs = 20
keepalive_interval = 8
[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 = "Noise_NK_25519_ChaChaPoly_BLAKE2s"
local_private_key = "key_encoded_in_base64"
remote_public_key = "key_encoded_in_base64"
[server.transport.websocket] # Necessary if `type` is "websocket"
tls = true # If `true` then it will use settings in `server.transport.tls`
[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" # Necessary if `server.default_token` not set
bind_addr = "0.0.0.0:8081" # Necessary. The address of the service is exposed at. Generally only the port needs to be change.
nodelay = true # Optional. Same as the client
[server.services.service2]
bind_addr = "0.0.0.1:8082"
Logging
rathole
, like many other Rust programs, use environment variables to control the logging level. info
, warn
, error
, debug
, trace
are available.
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
.
Tuning
From v0.4.7, rathole enables TCP_NODELAY by default, which should benefit the latency and interactive applications like rdp, Minecraft servers. However, it slightly decreases the bandwidth.
If the bandwidth is more important, TCP_NODELAY can be opted out with nodelay = false
.
Benchmark
rathole has similar latency to frp, but can handle a more connections, provide larger bandwidth, with less memory usage.
For more details, see the separate page Benchmark.
However, don't take it from here that rathole
can magically make your forwarded service faster several times than before. The benchmark is done on local loopback, indicating the performance when the task is cpu-bounded. One can gain quite a improvement if the network is not the bottleneck. Unfortunately, that's not true for many users. In that case, the main benefit is lower resource consumption, while the bandwidth and the latency may not improved significantly.
Planning
- HTTP APIs for configuration
Out of Scope lists features that are not planned to be implemented and why.
Top Related Projects
A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.
Minimal, self-hosted, 0-config alternative to ngrok. Caddy+OpenSSH+50 lines of Python.
一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。a lightweight, high-performance, powerful intranet penetration proxy server, with a powerful web management terminal.
Unified ingress for developers
GO Simple Tunnel - a simple tunnel written in golang
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot