Convert Figma logo to code with AI

rathole-org logorathole

A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.

10,989
573
10,989
101

Top Related Projects

93,182

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.

10,972

A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.

16,679

GO Simple Tunnel - a simple tunnel written in golang

32,970

一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。a lightweight, high-performance, powerful intranet penetration proxy server, with a powerful web management terminal.

Quick Overview

Rathole is a lightweight and high-performance reverse proxy tool for NAT traversal. It allows users to expose services behind NAT or firewalls to the public internet, similar to frp and ngrok, but with a focus on simplicity and efficiency.

Pros

  • High performance and low resource consumption
  • Simple configuration and easy to use
  • Supports both TCP and UDP protocols
  • Cross-platform compatibility (Windows, macOS, Linux)

Cons

  • Limited advanced features compared to some alternatives
  • Requires manual port forwarding on the server side
  • Documentation could be more comprehensive
  • Relatively new project, which may lead to potential stability concerns

Getting Started

  1. Download the latest release for your platform from the GitHub releases page.
  2. Create a configuration file for the server (e.g., server.toml):
[server]
bind_addr = "0.0.0.0:2333"

[server.services.my_service]
token = "your_secret_token"
  1. Create a configuration file for the client (e.g., client.toml):
[client]
remote_addr = "your_server_ip:2333"

[client.services.my_service]
token = "your_secret_token"
local_addr = "127.0.0.1:8080"
  1. Run the server:
./rathole server.toml
  1. Run the client:
./rathole client.toml

Your local service running on port 8080 will now be accessible through the server's public IP address.

Competitor Comparisons

93,182

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

Pros of frp

  • More mature and feature-rich project with a larger community
  • Supports multiple protocols (TCP, UDP, HTTP, HTTPS, STCP)
  • Offers a web-based dashboard for monitoring and management

Cons of frp

  • Written in Go, which may have higher resource usage
  • Configuration can be more complex due to extensive features
  • Larger codebase, potentially making it harder to audit

Code Comparison

frp (server configuration):

[common]
bind_port = 7000
vhost_http_port = 80

[web]
type = http
custom_domains = www.example.com
local_port = 80

rathole (server configuration):

[server]
bind_addr = "0.0.0.0:2333"

[server.services.http]
token = "password"
bind_addr = "0.0.0.0:8080"

Both projects aim to provide reverse proxy and NAT traversal solutions, but they differ in their approach and feature set. frp offers a more comprehensive solution with support for multiple protocols and a web dashboard, making it suitable for complex setups. However, this comes at the cost of increased resource usage and configuration complexity.

rathole, on the other hand, focuses on simplicity and efficiency. Written in Rust, it aims to provide a lightweight alternative with lower resource consumption. Its configuration is more straightforward, making it easier to set up for basic use cases. However, it may lack some advanced features found in frp.

The choice between the two depends on the specific requirements of the project, with frp being more suitable for feature-rich, complex deployments, and rathole offering a simpler, more resource-efficient solution for basic reverse proxy needs.

Minimal, self-hosted, 0-config alternative to ngrok. Caddy+OpenSSH+50 lines of Python.

Pros of SirTunnel

  • Simpler setup and configuration process
  • Built-in web interface for easier management
  • Supports WebSocket connections out of the box

Cons of SirTunnel

  • Less actively maintained (fewer recent updates)
  • Limited documentation compared to rathole
  • Fewer advanced features and customization options

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?;

Both projects aim to provide tunneling solutions, but they differ in implementation and features. SirTunnel offers a more user-friendly approach with its web interface and simpler configuration, making it suitable for users who prefer ease of use. However, it lacks some of the advanced features and customization options that rathole provides.

rathole, being more actively maintained and written in Rust, potentially offers better performance and security. It also provides more extensive documentation and a wider range of configuration options, making it more suitable for advanced users or those requiring fine-tuned control over their tunneling setup.

The code comparison shows that SirTunnel uses a more straightforward JavaScript API, while rathole employs a Rust-based configuration approach, reflecting their different design philosophies and target audiences.

10,972

A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.

Pros of rathole

  • Actively maintained with regular updates and bug fixes
  • Comprehensive documentation and usage examples
  • Cross-platform support for various operating systems

Cons of rathole

  • May have a steeper learning curve for beginners
  • Requires more configuration compared to simpler alternatives
  • Could have higher resource usage in certain scenarios

Code Comparison

rathole:

let server = TcpListener::bind(&addr).await?;
while let Ok((stream, _)) = server.accept().await {
    let transport = Transport::from((stream, None));
    tokio::spawn(handle_client(transport, token.clone()));
}

rathole>:

// No direct code comparison available as rathole> is not a valid repository

Note: The comparison is not possible as "rathole>" is not a valid GitHub repository name. The comparison provided is based solely on the rathole repository, as there is no counterpart to compare it against.

16,679

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.)
  • Built-in web interface for easier management and monitoring
  • Supports chaining and forwarding between different protocols

Cons of gost

  • More complex configuration due to its extensive feature set
  • Potentially higher resource usage compared to rathole's lightweight design
  • Less focused on specific use cases, which may lead to unnecessary overhead for simpler setups

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=socks5://example.com:1080

While both projects aim to provide tunneling solutions, rathole focuses on simplicity and efficiency for specific use cases, whereas gost offers a more versatile and feature-rich approach. rathole's configuration is typically more straightforward, using TOML format, while gost uses command-line flags or a JSON configuration file for its more complex setup options.

32,970

一款轻量级、高性能、功能强大的内网穿透代理服务器。支持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
  • Built-in load balancing and health checks for improved reliability
  • Supports multiple clients and servers, allowing for more complex network setups

Cons of nps

  • More complex setup and configuration due to its extensive features
  • Potentially higher resource usage compared to rathole's lightweight design
  • Less focus on security, as it doesn't prioritize encryption as much as rathole

Code Comparison

nps (Go):

bridge := bridge.NewTcpBridge(tp.bridgeConnType, CompressEncode, CompressDecode)
bridge.StartTunnel(config.CommonConfig.ProxyBridgePort, config.CommonConfig.TunnelBridgePort)

rathole (Rust):

let server = Server::new(config)?;
server.run().await?;

The code snippets show that nps uses a more complex bridge setup, while rathole has a simpler server initialization process. This reflects the overall design philosophy of each project, with nps offering more features and rathole focusing on simplicity and security.

Both projects aim to provide network tunneling solutions, but nps offers a broader range of features and protocols, making it suitable for more complex setups. Rathole, on the other hand, prioritizes simplicity, security, and performance, making it a good choice for users who need a lightweight and secure tunneling solution.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

rathole

rathole-logo

GitHub stars GitHub release (latest SemVer) GitHub Workflow Status (branch) GitHub all releases Docker Pulls Join the chat at https://gitter.im/rapiz1/rathole

English | 简体中文

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:

  1. 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
  1. 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
  1. Now the client will try to connect to the server 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.

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.

http_throughput tcp_bitrate udp_bitrate mem

Planning

  • HTTP APIs for configuration

Out of Scope lists features that are not planned to be implemented and why.