{
	"id": "60ba7ec6-88bb-4e9e-998a-edb2ebbe9273",
	"created_at": "2026-04-06T00:06:46.469784Z",
	"updated_at": "2026-04-10T03:21:40.227148Z",
	"deleted_at": null,
	"sha1_hash": "02d3814ebec23a7fd8da933b8b2176e616c9f1ef",
	"title": "GitHub - rathole-org/rathole: A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 212826,
	"plain_text": "GitHub - rathole-org/rathole: A lightweight and high-performance\r\nreverse proxy for NAT traversal, written in Rust. An alternative to\r\nfrp and ngrok.\r\nBy sjtrny\r\nArchived: 2026-04-05 15:34:08 UTC\r\nGitHub stars rreelleeaassee vv00..55..00 build ppaassssiinngg GitHub all releases ddoocckkeerr ppuullllss 456k \r\nchat on gitter\r\nEnglish | 简体中文\r\nA secure, stable and high-performance reverse proxy for NAT traversal, written in Rust\r\nrathole, like frp and ngrok, can help to expose the service on the device behind the NAT to the Internet, via a\r\nserver with a public IP.\r\nrathole\r\nFeatures\r\nQuickstart\r\nConfiguration\r\nLogging\r\nTuning\r\nBenchmark\r\nPlanning\r\nFeatures\r\nHigh Performance Much higher throughput can be achieved than frp, and more stable when handling a\r\nlarge volume of connections. See Benchmark\r\nLow Resource Consumption Consumes much fewer memory than similar tools. See Benchmark. The\r\nbinary can be as small as ~500KiB to fit the constraints of devices, like embedded devices as routers.\r\nhttps://github.com/rapiz1/rathole\r\nPage 1 of 8\n\nSecurity Tokens of services are mandatory and service-wise. The server and clients are responsible for\r\ntheir own configs. With the optional Noise Protocol, encryption can be configured at ease. No need to\r\ncreate a self-signed certificate! TLS is also supported.\r\nHot Reload Services can be added or removed dynamically by hot-reloading the configuration file. HTTP\r\nAPI is WIP.\r\nQuickstart\r\nA full-powered rathole can be obtained from the release page. Or build from source for other platforms and\r\nminimizing the binary. A Docker image is also available.\r\nThe usage of rathole is very similar to frp. If you have experience with the latter, then the configuration is very\r\neasy for you. The only difference is that configuration of a service is split into the client side and the server side,\r\nand a token is mandatory.\r\nTo use rathole , you need a server with a public IP, and a device behind the NAT, where some services that need\r\nto be exposed to the Internet.\r\nAssuming you have a NAS at home behind the NAT, and want to expose its ssh service to the Internet:\r\n1. On the server which has a public IP\r\nCreate server.toml with the following content and accommodate it to your needs.\r\n# server.toml\r\n[server]\r\nbind_addr = \"0.0.0.0:2333\" # `2333` specifies the port that rathole listens for clients\r\n[server.services.my_nas_ssh]\r\ntoken = \"use_a_secret_that_only_you_know\" # Token that is used to authenticate the client for the se\r\nbind_addr = \"0.0.0.0:5202\" # `5202` specifies the port that exposes `my_nas_ssh` to the Internet\r\nThen run:\r\n2. On the host which is behind the NAT (your NAS)\r\nCreate client.toml with the following content and accommodate it to your needs.\r\n# client.toml\r\n[client]\r\nremote_addr = \"myserver.com:2333\" # The address of the server. The port must be the same with the po\r\n[client.services.my_nas_ssh]\r\ntoken = \"use_a_secret_that_only_you_know\" # Must be the same with the server to pass the validation\r\nlocal_addr = \"127.0.0.1:22\" # The address of the service that needs to be forwarded\r\nhttps://github.com/rapiz1/rathole\r\nPage 2 of 8\n\nThen run:\r\n3. Now the client will try to connect to the server myserver.com on port 2333 , and any traffic to\r\nmyserver.com:5202 will be forwarded to the client's port 22 .\r\nSo you can ssh myserver.com:5202 to ssh to your NAS.\r\nTo run rathole run as a background service on Linux, checkout the systemd examples.\r\nConfiguration\r\nrathole can automatically determine to run in the server mode or the client mode, according to the content of\r\nthe configuration file, if only one of [server] and [client] block is present, like the example in Quickstart.\r\nBut the [client] and [server] block can also be put in one file. Then on the server side, run rathole --\r\nserver config.toml and on the client side, run rathole --client config.toml to explicitly tell rathole the\r\nrunning mode.\r\nBefore heading to the full configuration specification, it's recommend to skim the configuration examples to get a\r\nfeeling of the configuration format.\r\nSee Transport for more details about encryption and the transport block.\r\nHere is the full configuration specification:\r\n[client]\r\nremote_addr = \"example.com:2333\" # Necessary. The address of the server\r\ndefault_token = \"default_token_if_not_specify\" # Optional. The default token of services, if they don\r\nheartbeat_timeout = 40 # Optional. Set to 0 to disable the application-layer heartbeat test. The valu\r\nretry_interval = 1 # Optional. The interval between retry to connect to the server. Default: 1 second\r\n[client.transport] # The whole block is optional. Specify which transport to use\r\ntype = \"tcp\" # Optional. Possible values: [\"tcp\", \"tls\", \"noise\"]. Default: \"tcp\"\r\n[client.transport.tcp] # Optional. Also affects `noise` and `tls`\r\nproxy = \"socks5://user:passwd@127.0.0.1:1080\" # Optional. The proxy used to connect to the server. `h\r\nnodelay = true # Optional. Determine whether to enable TCP_NODELAY, if applicable, to improve the lat\r\nkeepalive_secs = 20 # Optional. Specify `tcp_keepalive_time` in `tcp(7)`, if applicable. Default: 20\r\nkeepalive_interval = 8 # Optional. Specify `tcp_keepalive_intvl` in `tcp(7)`, if applicable. Default\r\n[client.transport.tls] # Necessary if `type` is \"tls\"\r\ntrusted_root = \"ca.pem\" # Necessary. The certificate of CA that signed the server's certificate\r\nhostname = \"example.com\" # Optional. The hostname that the client uses to validate the certificate. I\r\n[client.transport.noise] # Noise protocol. See `docs/transport.md` for further explanation\r\npattern = \"Noise_NK_25519_ChaChaPoly_BLAKE2s\" # Optional. Default value as shown\r\nlocal_private_key = \"key_encoded_in_base64\" # Optional\r\nhttps://github.com/rapiz1/rathole\r\nPage 3 of 8\n\nremote_public_key = \"key_encoded_in_base64\" # Optional\r\n[client.transport.websocket] # Necessary if `type` is \"websocket\"\r\ntls = true # If `true` then it will use settings in `client.transport.tls`\r\n[client.services.service1] # A service that needs forwarding. The name `service1` can change arbitra\r\ntype = \"tcp\" # Optional. The protocol that needs forwarding. Possible values: [\"tcp\", \"udp\"]. Default\r\ntoken = \"whatever\" # Necessary if `client.default_token` not set\r\nlocal_addr = \"127.0.0.1:1081\" # Necessary. The address of the service that needs to be forwarded\r\nnodelay = true # Optional. Override the `client.transport.nodelay` per service\r\nretry_interval = 1 # Optional. The interval between retry to connect to the server. Default: inherits\r\n[client.services.service2] # Multiple services can be defined\r\nlocal_addr = \"127.0.0.1:1082\"\r\n[server]\r\nbind_addr = \"0.0.0.0:2333\" # Necessary. The address that the server listens for clients. Generally on\r\ndefault_token = \"default_token_if_not_specify\" # Optional\r\nheartbeat_interval = 30 # Optional. The interval between two application-layer heartbeat. Set to 0 to\r\n[server.transport] # Same as `[client.transport]`\r\ntype = \"tcp\"\r\n[server.transport.tcp] # Same as the client\r\nnodelay = true\r\nkeepalive_secs = 20\r\nkeepalive_interval = 8\r\n[server.transport.tls] # Necessary if `type` is \"tls\"\r\npkcs12 = \"identify.pfx\" # Necessary. pkcs12 file of server's certificate and private key\r\npkcs12_password = \"password\" # Necessary. Password of the pkcs12 file\r\n[server.transport.noise] # Same as `[client.transport.noise]`\r\npattern = \"Noise_NK_25519_ChaChaPoly_BLAKE2s\"\r\nlocal_private_key = \"key_encoded_in_base64\"\r\nremote_public_key = \"key_encoded_in_base64\"\r\n[server.transport.websocket] # Necessary if `type` is \"websocket\"\r\ntls = true # If `true` then it will use settings in `server.transport.tls`\r\n[server.services.service1] # The service name must be identical to the client side\r\ntype = \"tcp\" # Optional. Same as the client `[client.services.X.type]\r\ntoken = \"whatever\" # Necessary if `server.default_token` not set\r\nbind_addr = \"0.0.0.0:8081\" # Necessary. The address of the service is exposed at. Generally only the\r\nnodelay = true # Optional. Same as the client\r\nhttps://github.com/rapiz1/rathole\r\nPage 4 of 8\n\n[server.services.service2]\r\nbind_addr = \"0.0.0.1:8082\"\r\nLogging\r\nrathole , like many other Rust programs, use environment variables to control the logging level. info , warn ,\r\nerror , debug , trace are available.\r\nRUST_LOG=error ./rathole config.toml\r\nwill run rathole with only error level logging.\r\nIf RUST_LOG is not present, the default logging level is info .\r\nTuning\r\nFrom v0.4.7, rathole enables TCP_NODELAY by default, which should benefit the latency and interactive\r\napplications like rdp, Minecraft servers. However, it slightly decreases the bandwidth.\r\nIf the bandwidth is more important, TCP_NODELAY can be opted out with nodelay = false .\r\nBenchmark\r\nrathole has similar latency to frp, but can handle a more connections, provide larger bandwidth, with less memory\r\nusage.\r\nFor more details, see the separate page Benchmark.\r\nHowever, don't take it from here that rathole can magically make your forwarded service faster several\r\ntimes 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\r\nmany users. In that case, the main benefit is lower resource consumption, while the bandwidth and the latency\r\nmay not improved significantly.\r\nhttps://github.com/rapiz1/rathole\r\nPage 5 of 8\n\nhttps://github.com/rapiz1/rathole\r\nPage 6 of 8\n\nPlanning\r\nHTTP APIs for configuration\r\nhttps://github.com/rapiz1/rathole\r\nPage 7 of 8\n\nOut of Scope lists features that are not planned to be implemented and why.\r\nSource: https://github.com/rapiz1/rathole\r\nhttps://github.com/rapiz1/rathole\r\nPage 8 of 8",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA"
	],
	"references": [
		"https://github.com/rapiz1/rathole"
	],
	"report_names": [
		"rathole"
	],
	"threat_actors": [],
	"ts_created_at": 1775434006,
	"ts_updated_at": 1775791300,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/02d3814ebec23a7fd8da933b8b2176e616c9f1ef.pdf",
		"text": "https://archive.orkl.eu/02d3814ebec23a7fd8da933b8b2176e616c9f1ef.txt",
		"img": "https://archive.orkl.eu/02d3814ebec23a7fd8da933b8b2176e616c9f1ef.jpg"
	}
}