[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-5458":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":23,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":38,"readmeContent":39,"aiSummary":40,"trendingCount":16,"starSnapshotCount":16,"syncStatus":41,"lastSyncTime":42,"discoverSource":43},5458,"rathole","rathole-org\u002Frathole","rathole-org","A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.","",null,"Rust",13740,781,73,91,0,10,37,220,39,43.68,"Apache License 2.0",false,"main",true,[27,28,29,30,31,32,33,34,35,36,37],"firewall","frp","http","nat","network","ngrok","noise","noise-protocol","proxy","rust","tunnel","2026-06-12 02:01:10","# rathole\n\n![rathole-logo](.\u002Fdocs\u002Fimg\u002Frathole-logo.png)\n\n[![GitHub stars](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002Frapiz1\u002Frathole)](https:\u002F\u002Fgithub.com\u002Frapiz1\u002Frathole\u002Fstargazers)\n[![GitHub release (latest SemVer)](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002Frapiz1\u002Frathole)](https:\u002F\u002Fgithub.com\u002Frapiz1\u002Frathole\u002Freleases)\n![GitHub Workflow Status (branch)](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Frapiz1\u002Frathole\u002Frust.yml?branch=main)\n[![GitHub all releases](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fdownloads\u002Frapiz1\u002Frathole\u002Ftotal)](https:\u002F\u002Fgithub.com\u002Frapiz1\u002Frathole\u002Freleases)\n[![Docker Pulls](https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fpulls\u002Frapiz1\u002Frathole)](https:\u002F\u002Fhub.docker.com\u002Fr\u002Frapiz1\u002Frathole)\n[![Join the chat at https:\u002F\u002Fgitter.im\u002Frapiz1\u002Frathole](https:\u002F\u002Fbadges.gitter.im\u002Frapiz1\u002Frathole.svg)](https:\u002F\u002Fgitter.im\u002Frapiz1\u002Frathole?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n[English](README.md) | [简体中文](README-zh.md)\n\nA secure, stable and high-performance reverse proxy for NAT traversal, written in Rust\n\nrathole, like [frp](https:\u002F\u002Fgithub.com\u002Ffatedier\u002Ffrp) and [ngrok](https:\u002F\u002Fgithub.com\u002Finconshreveable\u002Fngrok), can help to expose the service on the device behind the NAT to the Internet, via a server with a public IP.\n\n\u003C!-- TOC -->\n\n- [rathole](#rathole)\n  - [Features](#features)\n  - [Quickstart](#quickstart)\n  - [Configuration](#configuration)\n    - [Logging](#logging)\n    - [Tuning](#tuning)\n  - [Benchmark](#benchmark)\n  - [Planning](#planning)\n\n\u003C!-- \u002FTOC -->\n\n## Features\n\n- **High Performance** Much higher throughput can be achieved than frp, and more stable when handling a large volume of connections. See [Benchmark](#benchmark)\n- **Low Resource Consumption** Consumes much fewer memory than similar tools. See [Benchmark](#benchmark). [The binary can be](docs\u002Fbuild-guide.md) **as small as ~500KiB** to fit the constraints of devices, like embedded devices as routers.\n- **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.\n- **Hot Reload** Services can be added or removed dynamically by hot-reloading the configuration file. HTTP API is WIP.\n\n## Quickstart\n\nA full-powered `rathole` can be obtained from the [release](https:\u002F\u002Fgithub.com\u002Frapiz1\u002Frathole\u002Freleases) page. Or [build from source](docs\u002Fbuild-guide.md) **for other platforms and minimizing the binary**. A [Docker image](https:\u002F\u002Fhub.docker.com\u002Fr\u002Frapiz1\u002Frathole) is also available.\n\nThe 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.\n\nTo 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.\n\nAssuming you have a NAS at home behind the NAT, and want to expose its ssh service to the Internet:\n\n1. On the server which has a public IP\n\nCreate `server.toml` with the following content and accommodate it to your needs.\n\n```toml\n# server.toml\n[server]\nbind_addr = \"0.0.0.0:2333\" # `2333` specifies the port that rathole listens for clients\n\n[server.services.my_nas_ssh]\ntoken = \"use_a_secret_that_only_you_know\" # Token that is used to authenticate the client for the service. Change to an arbitrary value.\nbind_addr = \"0.0.0.0:5202\" # `5202` specifies the port that exposes `my_nas_ssh` to the Internet\n```\n\nThen run:\n\n```bash\n.\u002Frathole server.toml\n```\n\n2. On the host which is behind the NAT (your NAS)\n\nCreate `client.toml` with the following content and accommodate it to your needs.\n\n```toml\n# client.toml\n[client]\nremote_addr = \"myserver.com:2333\" # The address of the server. The port must be the same with the port in `server.bind_addr`\n\n[client.services.my_nas_ssh]\ntoken = \"use_a_secret_that_only_you_know\" # Must be the same with the server to pass the validation\nlocal_addr = \"127.0.0.1:22\" # The address of the service that needs to be forwarded\n```\n\nThen run:\n\n```bash\n.\u002Frathole client.toml\n```\n\n3. 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`.\n\nSo you can `ssh myserver.com:5202` to ssh to your NAS.\n\nTo run `rathole` run as a background service on Linux, checkout the [systemd examples](.\u002Fexamples\u002Fsystemd).\n\n## Configuration\n\n`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](#quickstart).\n\nBut 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.\n\nBefore heading to the full configuration specification, it's recommend to skim [the configuration examples](.\u002Fexamples) to get a feeling of the configuration format.\n\nSee [Transport](.\u002Fdocs\u002Ftransport.md) for more details about encryption and the `transport` block.\n\nHere is the full configuration specification:\n\n```toml\n[client]\nremote_addr = \"example.com:2333\" # Necessary. The address of the server\ndefault_token = \"default_token_if_not_specify\" # Optional. The default token of services, if they don't define their own ones\nheartbeat_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\nretry_interval = 1 # Optional. The interval between retry to connect to the server. Default: 1 second\n\n[client.transport] # The whole block is optional. Specify which transport to use\ntype = \"tcp\" # Optional. Possible values: [\"tcp\", \"tls\", \"noise\"]. Default: \"tcp\"\n\n[client.transport.tcp] # Optional. Also affects `noise` and `tls`\nproxy = \"socks5:\u002F\u002Fuser:passwd@127.0.0.1:1080\" # Optional. The proxy used to connect to the server. `http` and `socks5` is supported.\nnodelay = true # Optional. Determine whether to enable TCP_NODELAY, if applicable, to improve the latency but decrease the bandwidth. Default: true\nkeepalive_secs = 20 # Optional. Specify `tcp_keepalive_time` in `tcp(7)`, if applicable. Default: 20 seconds\nkeepalive_interval = 8 # Optional. Specify `tcp_keepalive_intvl` in `tcp(7)`, if applicable. Default: 8 seconds\n\n[client.transport.tls] # Necessary if `type` is \"tls\"\ntrusted_root = \"ca.pem\" # Necessary. The certificate of CA that signed the server's certificate\nhostname = \"example.com\" # Optional. The hostname that the client uses to validate the certificate. If not set, fallback to `client.remote_addr`\n\n[client.transport.noise] # Noise protocol. See `docs\u002Ftransport.md` for further explanation\npattern = \"Noise_NK_25519_ChaChaPoly_BLAKE2s\" # Optional. Default value as shown\nlocal_private_key = \"key_encoded_in_base64\" # Optional\nremote_public_key = \"key_encoded_in_base64\" # Optional\n\n[client.transport.websocket] # Necessary if `type` is \"websocket\"\ntls = true # If `true` then it will use settings in `client.transport.tls`\n\n[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\ntype = \"tcp\" # Optional. The protocol that needs forwarding. Possible values: [\"tcp\", \"udp\"]. Default: \"tcp\"\ntoken = \"whatever\" # Necessary if `client.default_token` not set\nlocal_addr = \"127.0.0.1:1081\" # Necessary. The address of the service that needs to be forwarded\nnodelay = true # Optional. Override the `client.transport.nodelay` per service\nretry_interval = 1 # Optional. The interval between retry to connect to the server. Default: inherits the global config\n\n[client.services.service2] # Multiple services can be defined\nlocal_addr = \"127.0.0.1:1082\"\n\n[server]\nbind_addr = \"0.0.0.0:2333\" # Necessary. The address that the server listens for clients. Generally only the port needs to be change.\ndefault_token = \"default_token_if_not_specify\" # Optional\nheartbeat_interval = 30 # Optional. The interval between two application-layer heartbeat. Set to 0 to disable sending heartbeat. Default: 30 seconds\n\n[server.transport] # Same as `[client.transport]`\ntype = \"tcp\"\n\n[server.transport.tcp] # Same as the client\nnodelay = true\nkeepalive_secs = 20\nkeepalive_interval = 8\n\n[server.transport.tls] # Necessary if `type` is \"tls\"\npkcs12 = \"identify.pfx\" # Necessary. pkcs12 file of server's certificate and private key\npkcs12_password = \"password\" # Necessary. Password of the pkcs12 file\n\n[server.transport.noise] # Same as `[client.transport.noise]`\npattern = \"Noise_NK_25519_ChaChaPoly_BLAKE2s\"\nlocal_private_key = \"key_encoded_in_base64\"\nremote_public_key = \"key_encoded_in_base64\"\n\n[server.transport.websocket] # Necessary if `type` is \"websocket\"\ntls = true # If `true` then it will use settings in `server.transport.tls`\n\n[server.services.service1] # The service name must be identical to the client side\ntype = \"tcp\" # Optional. Same as the client `[client.services.X.type]\ntoken = \"whatever\" # Necessary if `server.default_token` not set\nbind_addr = \"0.0.0.0:8081\" # Necessary. The address of the service is exposed at. Generally only the port needs to be change.\nnodelay = true # Optional. Same as the client\n\n[server.services.service2]\nbind_addr = \"0.0.0.1:8082\"\n```\n\n### Logging\n\n`rathole`, like many other Rust programs, use environment variables to control the logging level. `info`, `warn`, `error`, `debug`, `trace` are available.\n\n```shell\nRUST_LOG=error .\u002Frathole config.toml\n```\n\nwill run `rathole` with only error level logging.\n\nIf `RUST_LOG` is not present, the default logging level is `info`.\n\n### Tuning\n\nFrom 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.\n\nIf the bandwidth is more important, TCP_NODELAY can be opted out with `nodelay = false`.\n\n## Benchmark\n\nrathole has similar latency to [frp](https:\u002F\u002Fgithub.com\u002Ffatedier\u002Ffrp), but can handle a more connections, provide larger bandwidth, with less memory usage.\n\nFor more details, see the separate page [Benchmark](.\u002Fdocs\u002Fbenchmark.md).\n\n**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.\n\n![http_throughput](.\u002Fdocs\u002Fimg\u002Fhttp_throughput.svg)\n![tcp_bitrate](.\u002Fdocs\u002Fimg\u002Ftcp_bitrate.svg)\n![udp_bitrate](.\u002Fdocs\u002Fimg\u002Fudp_bitrate.svg)\n![mem](.\u002Fdocs\u002Fimg\u002Fmem-graph.png)\n\n## Planning\n\n- [ ] HTTP APIs for configuration\n\n[Out of Scope](.\u002Fdocs\u002Fout-of-scope.md) lists features that are not planned to be implemented and why.\n","rathole是一个用Rust编写的轻量级高性能反向代理工具，用于NAT穿透。其核心功能包括高吞吐量、低资源消耗以及强大的安全性，支持Noise协议和TLS加密，并且可以动态热加载配置文件以添加或移除服务。相比同类工具如frp和ngrok，rathole在处理大量连接时更加稳定，同时其二进制文件大小可压缩至约500KiB，非常适合嵌入式设备等资源受限场景使用。此外，它还提供了Docker镜像，方便用户快速部署。",2,"2026-06-11 03:03:26","top_language"]