{
    "componentChunkName": "component---src-templates-issues-tsx",
    "path": "/issues/469",
    "result": {"data":{"issuesJson":{"id":"f4202156-f84b-519e-9d9d-60987c867ff9","title":"rapiz1/rathole: 安全、稳定、高性能的内网穿透工具，用 Rust 语言编写，类似frp","number":469,"bodyHTML":"<div align=\"center\" dir=\"auto\">\n<p dir=\"auto\"><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/a15b413168923d02e21292705ceaf86b92675f98e250c5c896a02ba7504a6eae/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f657279616a662f7475406d61696e2f696d672f696d6167655f32303234303432305f3231343430382e676966\"><img src=\"https://camo.githubusercontent.com/a15b413168923d02e21292705ceaf86b92675f98e250c5c896a02ba7504a6eae/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f657279616a662f7475406d61696e2f696d672f696d6167655f32303234303432305f3231343430382e676966\" width=\"100%\" height=\"3\" data-animated-image=\"\" data-canonical-src=\"https://cdn.jsdelivr.net/gh/eryajf/tu@main/img/image_20240420_214408.gif\" style=\"max-width: 100%; height: auto; max-height: 3px;\"></a><br><br></p>\n<markdown-accessiblity-table><table role=\"table\">\n<thead>\n<tr>\n<th align=\"right\">Repos</th>\n<th align=\"left\"><a href=\"https://github.com/rapiz1/rathole\">rapiz1/rathole</a></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"right\"><strong>Views</strong></td>\n<td align=\"left\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/9ce8c5102044915c087bd1f54b703cc3a3b2ea436b59f30d594d72f13b0d7860/68747470733a2f2f76696577732e77686174696c656172656e65642e746f6461792f76696577732f6769746875622f726170697a312f726174686f6c652e737667\" alt=\"views\" data-canonical-src=\"https://views.whatilearened.today/views/github/rapiz1/rathole.svg\" style=\"max-width: 100%;\"></a></td>\n</tr>\n<tr>\n<td align=\"right\"><strong>Stars</strong></td>\n<td align=\"left\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/ef77fb46cb11a489fcf09569d46955c8c51cfef2438c3242d8f7d8c30daf82c6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f726170697a312f726174686f6c653f636f6c6f723d663266303864266c6f676f3d556e64657274616c65266c6f676f436f6c6f723d656234363330\" alt=\"stars\" data-canonical-src=\"https://img.shields.io/github/stars/rapiz1/rathole?color=f2f08d&amp;logo=Undertale&amp;logoColor=eb4630\" style=\"max-width: 100%;\"></a></td>\n</tr>\n<tr>\n<td align=\"right\"><strong>Forks</strong></td>\n<td align=\"left\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/271156ce2f34f37521d8bed2e9834808882c8a183ff644073184d729dc597c9a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f726170697a312f726174686f6c653f636f6c6f723d626138366562266c6f676f3d48616e647368616b65266c6f676f436f6c6f723d656136616136\" alt=\"forks\" data-canonical-src=\"https://img.shields.io/github/forks/rapiz1/rathole?color=ba86eb&amp;logo=Handshake&amp;logoColor=ea6aa6\" style=\"max-width: 100%;\"></a></td>\n</tr>\n<tr>\n<td align=\"right\"><strong>License</strong></td>\n<td align=\"left\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/059ff07ea4387c7c2e732e8d5c920f3261e1984672060e6aaf6ff110445f438c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f726170697a312f726174686f6c653f6c6f676f3d64617461253341696d616765253246706e672533426261736536342532436956424f5277304b47676f414141414e53556845556741414144414141414177434159414141425841766d48414141414358424957584d41414173544141414c457745416d70775941414144336b6c45515652346e4f335953557a5555426748384a726f57567255474a66456d3773584e63534446784d544c327069347348456778654e526f77586770455742445552522532424e414e4f4b4f4b36366f6f4b4a4742586545475263574163455646475152484677516d483525324630774861655748493944554455354c356b6e6568644f62377a66652532423139636e434a47495243516945596c514237594a4979474c38616f73756c565a36695246516a69474b6b7564576735614c6c704f70704e586e665071773555304459524a6d56786a4367464633424c755a476d416f5655694b4541726d583744375553677351706f72674761336748664b34483663754262435644334771683141352532424c6745253242467749656e514d306a6f446f66714c6f48564e7742796d384370546e416d327a51713073676478624964515a556c416b7150415a3664676a303541446f59526f6f66792532466f5869726f376b3551586a4c6f70677a4b69514e6c4c4461716f4967754577426a7a7150355066446a45394479495879493633464d547751464d43567271774e61763451666f52673538514625324266724d485172454b3844546f434d714e4179574e4866786d54526f4c4f726d5352566747744466714345715a4f4851727a6f34706243557341333431365169364551394b476a6345465267484f724f4b6e5536574162396247455459656b4b7843766a546167394534706a653534446b3551503862624d4859762532464333756541654a6b50304f4778422532424a70426e4172595238455951516e6f4e31414e4661426e5050356c385372736559514c303641646b30464a5938484f5761424d6c6541486a683068506f73497a6c6f3876304125324633345a694f6548726130714b52504d5653493774762532423932747725324676687855654252713456454c674d376642714b354770526d6f514c584e7075625475367a6f4e52706754386e5051627138347764253246494375767978694b4871694e41664933774d367549684271476b4c696977414f734b44714f68743749747239567938536a52424557667941627225324668523142667056514664484a42253246423268683778376a36517077435665655951326b72554235436c636a3641326d3067576a25324244306d4c34397a573563517943484c4e37726a6c6d6d6174457958582532464372547a412532466f51785a6b576c39474a5443566f25324279546a3837253242346769504b6376307149486f344156344430565a727251493334706e70524d36357875652532467a417265453425324654253246536f676c664542794d7369517441546c4c3352414a355948725378365a44665337307337754d486842705225324659423573305057366f455270316236253246667252684b3353444c35546965364f515548516c5133735644752532427a50636b397657453973747225324236496a533967486d5750616861444a25324277434b364e494242587348423948796b587378774470686c436d416476706c6162554a4e6e5a504239342532464e7436784f6538587a4562503257684d335741673147756236744825324233513150673337365239713475716c6e6f36676448476a444f5139306562303141484d3672596975554a314f713472344656756a35765239427a4d3957674e764f7977446869495951467667626366774166774d764863615067425041253246447948476a50624e394138616d6562636477416444354e6633373574787165774e5552656f797677424958594c645170576c6877465771745061435044334173467541535636717171496c62304a766b564331464c39576b4c55556c55574b337a585a4c46432532423125324642726f46746f364f7358497545594a5034447a7a5732594656316f4a614141414141456c46546b5375516d4343\" alt=\"license\" data-canonical-src=\"https://img.shields.io/github/license/rapiz1/rathole?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD3klEQVR4nO3YSUzUUBgH8JroWVrUGJfEm7sXNcSDFxMTL2pi4sHEgxeNRowXgpEWBDURR%2BNANOKOK66ooKJGBXeEGRcWAcEVFGQRHFwQmH5%2F0wHaeWHI9DUDU5L5knehdOb7zfe%2B19cnCJGIRCQiEYlQB7YJIyGL8aosulVZ6iRFQjiGKkudWg5aLlpOppNXnfPqw5U0DYRJmVxjCgFF3BLuZGmAoVUiKEArmX7D7USgsQporgGa3gHfK4H6cuBbCVD3Gqh1A5%2BLgE%2BFwIenQM0joDofqLoHVNwBym8CpTnAm2zQq0sgdxbIdQZUlAkqPAZ6dgj05ADoYRoofy%2FoXiro7k5QXjLopgzKiQNlLDaqoIguEwBjzqP5PfDjE9DyIXyI63FMTwQFMCVrqwNav4QfoRg58QF%2BfrMHQrEK8DToCMqNAyWNHfxmTRoLOrmSRVgGtDfqCEqZOHQrzo4pbCUsA3416Qi6EQ9KGjcEFRgHOrOKnU6WAb9bGETYekKxCvjTag9E4pje54Dk5QP8bbMHYv%2FC3ueAeJkP0OGxB%2BJpBnArYR8EYQQnoN1ANFaBnPP5l8SrseYQL06Adk0FJY8HOWaBMleAHjh0hPosIzlo8v0A%2F34ZiOeHra0qKRPMVSI7tv%2B92tw%2FvhxUeBRq4VELgM7fBqK5GpRmoQLXNpubTu6zoNRpgT8nPQbq84wd%2FICuvyxiKHqiNAfI3wM6uIhBqGkLiiwAOsKDqOht7Itr9Vy8SjRBEWfyAbr%2FhR1BfpVQFdHJB%2FB2hh7x7j6QpwCVeeYQ2krUB5Clcj6A2m0gWj%2BD0mL49zW5cQyCHLN7rjlmmatEyXX%2FCrTzA%2FoQxZkWl9GJTCVo%2ByTj87%2B4giPKcv0qIHo4AV4D0VZrrQI34pnpRM65xue%2FzAreE4%2FT%2FSoglfEByMsiQtATlL3RAJ5YHrSx6ZDfS70s7uMHhBpR%2FYB5s0PW6oERp1b6%2FfrRhK3SDL5Tie6OQUHQlQ3sVDu%2BzPck9vWE9str%2B6IjS9gHmWPahaDJ%2BwCK6NIBBXsHB9HykXsxwDphlCmAdvplabUJNnZPB94%2FNt6xOe8XzEbP2WhM3WAg1Gub6tH%2B3Q1Pg376R9q4uqlno6gdHGjDOQ90eb01AHM6rYiuUJ1Oq4r4FVuj5vR9BzM9WgNvOywDhiIYQFvgbcfwAfwMvHcaPgBPA%2FDyHGjPbN9A8amebcdwAdD5Nf375txqewNUReoyvwBIXYLdQpWlhwFWqtPaCPD3AsFuASV6qqqIlb0JvkVC1FL9WkLUUlUWK3zXZLFC%2B1%2FBroFto6OsXIuEYJP4DzzW2YFV1oJaAAAAAElFTkSuQmCC\" style=\"max-width: 100%;\"></a></td>\n</tr>\n<tr>\n<td align=\"right\"><strong>UpdatedAt</strong></td>\n<td align=\"left\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/a0e9ecd8d51fa1de03e71a4ff8521741b0b6ffaf79cdf12c563fbc2aaefc4559/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f726170697a312f726174686f6c653f646973706c61795f74696d657374616d703d636f6d6d6974746572266c6f676f3d64617461253341696d616765253246706e672533426261736536342532436956424f5277304b47676f414141414e5355684555674141414234414141416543415941414141374d4b3669414141414358424957584d41414173544141414c457745416d7077594141414648556c45515652346e4c5658375539615678776d3236646c582532466468627825324232253246516e626b7655627264554151674a4a496655444e574454546d4f76314651554661504a346b7573725630314a7431734e70637453327533626f745a746d786439744a5346536f714b71494635625944464c436f76436c656673747a4a387758524c445a4c7a6e6b634f343535376e3364332532466e655a3472454f515a74315771462532423858467234253242664f4c4565326a6f59307a776638546f795a50766a45676b4c592532426b306d6d72584f36644b696e787a476b30666a5430782532425279723055716e6359637a4d317263347451253242497270324c4758646f344e4334567657715453373277716c632532427231334f527269364b6458646e624f484c6c776c7a4a70524b6e3657342532424b36706f4f434e6e494166486a253246253242776168495a4234764b6e715a6630714a704e49716c2532467638545530634e6c3572627963337730516e54703379324c54614a374d314e617844723266526e315370504736476961323174664533345463614f617931694d55564f5146624659714957536f31573854694156616e43306576584f4542375770313448466232327a453566714c4f433545524c515769644e614e49347545636339693768634a6c644868324e57725135674464624f6c7061756d49754c62326174415144506e7a3062384e6257636d785656524a33486d7870536377777a4f4a6d4b44524765384c6c435a444c4739673754496e5631516c376462586256316533675430574b697243466f6d6b5079767758466c5a474a4f6a563625324253743634757564445a4f55354555636f782532464d455144567674364d62634e3237593341797a687633737061557242365a3971724a534f3139657a6a387032704c426b4a792532426343484a7857493567573574636652527a31645531394766476b6f7539505a4f34736d52396a4746777065783444793362766e6d4b79706f74625531335669646a71595a68726a343972764d457425324625324659714c7a396430304e6a57253246637a67796f394f35317a7336614e6c6f354644747530445a675146686c47584a30644241446f4e6864367576703657686f617967374e394c564748386d443462253246486e667455516f4e4734764c51306769784d716c5725324234714f6a744e48446733723166365969525347785279375576714c62395534716b716e78504f4e7661356c447048723125324279794b524e4b57425a793565644d554842326d3572792532422532424551772532427a6766347a6f39253246306f634e3357527a4c4277344a2532424a7950574372716d4967475974554f735744346f785a46516f50556a4770564871493425324661666b51504336665a5165654d31253242764c7549516e6a754257514444437363726d485039656f4e5041744271664f6e5875614b25324268364a45624772732532427076764d6d78654962683836336162565065597953456f39464a48704e4d464a59253242503563575a6b6667374f3174537759436553514c54593345385130392532464256504a556c78516a7368543142736343593032723955445542667643484236367063665041336c794165336e6772332532463437584467614a7a736c7937787741364e5a746c555550437541487161536a5549502532427375653842525741432532464e6651374a5a505a35397330476a3756747049537a34685125324243706658474d4b685a63764c70554b7866574d386f68766637702532464f446a4842666356463849736b383267314648796b63564645253242555a414158343761452532464d6c34504f3530506e75683025324678346e6d637957507364774468427836436d6b4c562532466746446a594b784f4a4f4674623077517949684c39527943774b33414f664947703159464542686e4d4a634c525745624b644b516f55366e63545a6b494544696341792532463831645675454d3552775066657934784f7830496b25324649324e6e466b692532425761664f6f464959466367595a43797864376543556a626334416d46363566742532466b4d686b336f25324235686337734d4a79716a4a45477659466151464972375930775077384246415925324236253242766d6b3377367a7a5275444d6d5a5652736668385274413075455453443775434254364459514e36697665553066706b594c6a453671725672744f78654e4b553954484c5a4a396b4255324a427342685635416976422532466f4b61514e4b675043427744596149665a4334616454684f71463457454e56694c4a77566f586f62664c424b56773637414f6154734c6336355461564b32317651344c613939654b6359673576627873624f627a5451394e37554b4467554f3177446a6944494942736868357a746733396e514d4c535a4248344f7a424f55444551586d323036643366634c67737762585141345068634b336e6873775531427a3877765130395248472532466f597933656a6677424e6d746f59714c4130586741414141424a52553545726b4a676767253344253344266c6162656c3d557064617465644174\" alt=\"last-commit\" data-canonical-src=\"https://img.shields.io/github/last-commit/rapiz1/rathole?display_timestamp=committer&amp;logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHUlEQVR4nLVX7U9aVxwm26dlX%2Fdhbx%2B2%2FQnbkvUbrdUAQgJJIfUDNWDTTmOv1FQUFaPJ4kusrV01Jt1sNpctS2u3botZtmxd9tJSFSoqKqIF5bYDFLCovClefstzJ8wXRLDZLznkcO4557n3d3%2FneZ4rEOQZt1WqF%2B8XFr4%2BfOLEe2joY0zwf8ToyZPvjEgkLY%2Bk0mmrXO6dKinxzGk0fjT0x%2BRyr0UqncYczM1rc4tQ%2BIrp2LGXdo4NC4VvWqTS72wqlc%2Br13ORri6KdXdnbOHLlwlzJpRKn6W4%2BK6poOCNnIAfHj%2F%2BwahIZB4vKnqZf0qJpNIql%2Fv8TU0cNl5rbyc3w0QnTp3y2LTaJ7M1NaxDr2fRn1SpPG6Gia21tfE34TcaOay1iMUVOQFbFYqIWSo1W8TiAVanC0evXOEB7Wp14HFb22zE5fqLOC5ERLQWidNaNI4uEcc9i7hcJldHh2NWrQ5gDdbOlpaumIuLb2atAQDPnz0b8NbWcmxVVRJ3HmxpScwwzOJmKDRGe8LlCZDLG9g7TInV1Ql7dbXbV1e3gT0WKirCFomkPyvwXFlZGJOjV6%2BSt64uudDZOU5EUcox%2FMEQDVvt6MbcN27Y3Ayzhv3spaUrB6Z9qrJSO19ezj8p2pLBkJy%2BcCHJxWI5gW5tcfRRz1dU19GfGkou9PZO4smR9jGFwpex4Dy3bvnmKypotbU13VidjqYZhrj49rvMEt%2F%2FYqLz9d00NjW%2Fczgyo9O51zs6aNlo5FDtu0DZgQFhlGXJ0dBADoNhd6uvp6Whoayg7N9LVGH8mD4b%2FHnftUQoNG4vLQ0gixMqlW%2B4qOjtNHDg3r1f6YiRSGxRy7UvqLb9U4qkqnxPONva5lDpHr1%2ByyKRNKWBZy5edMUHB2m5ry%2B%2BEQw%2Bzgf4zo9%2F0ocN3WRzLBw4J%2BJyPWCrqmIgGYtUOsWD4oxZFQoPUjGpVHqI4%2FafkQPC6fZQeeM1%2BvLuIQnjuBWQDDCscrmHP9eoNPAtBqfOnXuaK%2Bh6JEbGrs%2BpvvMmxeIbh863abVPeYySEo9FJHpNMFJY%2BP5cWZkfg7O1tSwYCeSQLTY3E8Q09%2FBVPJUlxQjshT1BscCY02r9UDUBfvCHB66pcfPA3lyAe3ngr3%2F47XDgaJzsly7xwA6NZtlUUPCuAHqaSjUIP%2Bsue8BRWAC%2FNfQ7JZPZ59s0Gj7VtpISz4hQ%2BCpfXGMKhZcvLpUKxfWM8ohvf7p%2FODjHBfcVF8Isk82g1FHykcVFE%2BUZAAX47aE%2FMl4PO50Pnuh0%2Fx4nmcyWPsdwDhBx6CmkLV%2FgFDjYKxOJOFtb0wQyIhL9RyCwK3AOfIGp1YFEBhnMJcLRWEbKdKQoU6ncTZkIEDicAy%2F81dVuEM5RwPfey4xOx0Ik%2FI2NnFki%2BWafOoFIYFcgYZCyxd7eCUjbc4AmF65ft%2FkMhk3o%2B5hc7sMJyqjJEGvYFaQFIr7Y0wPw8BFAY%2B6%2Bvmk3w6zzRuDMmZVRsfh8RtA0uETSD7uCBT6DYQN6iveU0fpkYLjE6qrVrtOxeNKU9THLZJ9kBU2JBsBhV5AivB%2FoKaQNKgPCBwDYaIfZC4adThOqF4WENViLJwVoXobfLBKVw67AOaTsLc65TaVK21vQ4La99eKcYg5vbxsbObzTQ9N7UKDgUO1wDjiDIIBshh5ztg39nQMLSZBH4OzBOUDEQXm206d3fcLgswbXQA4PhcK3nhswU1Bz8wvQ09RHG%2FoYy3ejfwBNmtoYqLA0XgAAAABJRU5ErkJggg%3D%3D&amp;label=UpdatedAt\" style=\"max-width: 100%;\"></a></td>\n</tr>\n<tr>\n<td align=\"right\"><strong>CreatedAt</strong></td>\n<td align=\"left\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/6110194aa8b096256f7deb030c5a3b8b5d6d49e19813b9e42ac933dcc30693df/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f637265617465642d61742f726170697a312f726174686f6c653f6c6f676f3d64617461253341696d616765253246706e672533426261736536342532436956424f5277304b47676f414141414e5355684555674141414234414141416543415941414141374d4b3669414141414358424957584d41414173544141414c457745416d7077594141414648556c45515652346e4c5658375539615678776d3236646c582532466468627825324232253246516e626b7655627264554151674a4a496655444e574454546d4f76314651554661504a346b7573725630314a7431734e70637453327533626f745a746d786439744a5346536f714b71494635625944464c436f76436c656673747a4a387758524c445a4c7a6e6b634f343535376e3364332532466e655a3472454f515a74315771462532423858467234253242664f4c4565326a6f59307a776638546f795a50766a45676b4c592532426b306d6d72584f36644b696e787a476b30666a5430782532425279723055716e6359637a4d317263347451253242497270324c4758646f344e4334567657715453373277716c632532427231334f527269364b6458646e624f484c6c776c7a4a70524b6e3657342532424b36706f4f434e6e494166486a253246253242776168495a4234764b6e715a6630714a704e49716c2532467638545530634e6c3572627963337730516e54703379324c54614a374d314e617844723266526e315370504736476961323174664533345463614f617931694d55564f5146624659714957536f31573854694156616e43306576584f4542375770313448466232327a453566714c4f433545524c515769644e614e49347545636339693768634a6c644868324e57725135674464624f6c7061756d49754c62326174415144506e7a3062384e6257636d785656524a33486d7870536377777a4f4a6d4b44524765384c6c435a444c4739673754496e5631516c376462586256316533675430574b697243466f6d6b5079767758466c5a474a4f6a563625324253743634757564445a4f55354555636f782532464d455144567674364d62634e3237593341797a687633737061557242365a3971724a534f3139657a6a387032704c426b4a792532426343484a7857493567573574636652527a31645531394766476b6f7539505a4f34736d52396a4746777065783444793362766e6d4b79706f74625531335669646a71595a68726a343972764d457425324625324659714c7a396430304e6a57253246637a67796f394f35317a7336614e6c6f354644747530445a675146686c47584a30644241446f4e6864367576703657686f617967374e394c564748386d443462253246486e667455516f4e4734764c51306769784d716c5725324234714f6a744e48446733723166365969525347785279375576714c62395534716b716e78504f4e7661356c447048723125324279794b524e4b57425a793565644d554842326d3572792532422532424551772532427a6766347a6f39253246306f634e3357527a4c4277344a2532424a7950574372716d4967475974554f735744346f785a46516f50556a4770564871493425324661666b51504336665a5165654d31253242764c7549516e6a754257514444437363726d485039656f4e5041744271664f6e5875614b25324268364a45624772732532427076764d6d78654962683836336162565065597953456f39464a48704e4d464a59253242503563575a6b6667374f3174537759436553514c54593345385130392532464256504a556c78516a7368543142736343593032723955445542667643484236367063665041336c794165336e6772332532463437584467614a7a736c7937787741364e5a746c555550437541487161536a5549502532427375653842525741432532464e6651374a5a505a35397330476a3756747049537a34685125324243706658474d4b685a63764c70554b7866574d386f68766637702532464f446a4842666356463849736b383267314648796b63564645253242555a414158343761452532464d6c34504f3530506e75683025324678346e6d637957507364774468427836436d6b4c562532466746446a594b784f4a4f4674623077517949684c39527943774b33414f664947703159464542686e4d4a634c525745624b644b516f55366e63545a6b494544696341792532463831645675454d3552775066657934784f7830496b25324649324e6e466b692532425761664f6f464959466367595a43797864376543556a626334416d46363566742532466b4d686b336f25324235686337734d4a79716a4a45477659466151464972375930775077384246415925324236253242766d6b3377367a7a5275444d6d5a5652736668385274413075455453443775434254364459514e36697665553066706b594c6a453671725672744f78654e4b553954484c5a4a396b4255324a427342685635416976422532466f4b61514e4b675043427744596149665a4334616454684f71463457454e56694c4a77566f586f62664c424b56773637414f6154734c6336355461564b32317651344c613939654b6359673576627873624f627a5451394e37554b4467554f3177446a6944494942736868357a746733396e514d4c535a4248344f7a424f55444551586d323036643366634c67737762585141345068634b336e6873775531427a3877765130395248472532466f597933656a6677424e6d746f59714c4130586741414141424a52553545726b4a676767253344253344266c6162656c3d437265617465644174\" alt=\"create-at\" data-canonical-src=\"https://img.shields.io/github/created-at/rapiz1/rathole?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHUlEQVR4nLVX7U9aVxwm26dlX%2Fdhbx%2B2%2FQnbkvUbrdUAQgJJIfUDNWDTTmOv1FQUFaPJ4kusrV01Jt1sNpctS2u3botZtmxd9tJSFSoqKqIF5bYDFLCovClefstzJ8wXRLDZLznkcO4557n3d3%2FneZ4rEOQZt1WqF%2B8XFr4%2BfOLEe2joY0zwf8ToyZPvjEgkLY%2Bk0mmrXO6dKinxzGk0fjT0x%2BRyr0UqncYczM1rc4tQ%2BIrp2LGXdo4NC4VvWqTS72wqlc%2Br13ORri6KdXdnbOHLlwlzJpRKn6W4%2BK6poOCNnIAfHj%2F%2BwahIZB4vKnqZf0qJpNIql%2Fv8TU0cNl5rbyc3w0QnTp3y2LTaJ7M1NaxDr2fRn1SpPG6Gia21tfE34TcaOay1iMUVOQFbFYqIWSo1W8TiAVanC0evXOEB7Wp14HFb22zE5fqLOC5ERLQWidNaNI4uEcc9i7hcJldHh2NWrQ5gDdbOlpaumIuLb2atAQDPnz0b8NbWcmxVVRJ3HmxpScwwzOJmKDRGe8LlCZDLG9g7TInV1Ql7dbXbV1e3gT0WKirCFomkPyvwXFlZGJOjV6%2BSt64uudDZOU5EUcox%2FMEQDVvt6MbcN27Y3Ayzhv3spaUrB6Z9qrJSO19ezj8p2pLBkJy%2BcCHJxWI5gW5tcfRRz1dU19GfGkou9PZO4smR9jGFwpex4Dy3bvnmKypotbU13VidjqYZhrj49rvMEt%2F%2FYqLz9d00NjW%2Fczgyo9O51zs6aNlo5FDtu0DZgQFhlGXJ0dBADoNhd6uvp6Whoayg7N9LVGH8mD4b%2FHnftUQoNG4vLQ0gixMqlW%2B4qOjtNHDg3r1f6YiRSGxRy7UvqLb9U4qkqnxPONva5lDpHr1%2ByyKRNKWBZy5edMUHB2m5ry%2B%2BEQw%2Bzgf4zo9%2F0ocN3WRzLBw4J%2BJyPWCrqmIgGYtUOsWD4oxZFQoPUjGpVHqI4%2FafkQPC6fZQeeM1%2BvLuIQnjuBWQDDCscrmHP9eoNPAtBqfOnXuaK%2Bh6JEbGrs%2BpvvMmxeIbh863abVPeYySEo9FJHpNMFJY%2BP5cWZkfg7O1tSwYCeSQLTY3E8Q09%2FBVPJUlxQjshT1BscCY02r9UDUBfvCHB66pcfPA3lyAe3ngr3%2F47XDgaJzsly7xwA6NZtlUUPCuAHqaSjUIP%2Bsue8BRWAC%2FNfQ7JZPZ59s0Gj7VtpISz4hQ%2BCpfXGMKhZcvLpUKxfWM8ohvf7p%2FODjHBfcVF8Isk82g1FHykcVFE%2BUZAAX47aE%2FMl4PO50Pnuh0%2Fx4nmcyWPsdwDhBx6CmkLV%2FgFDjYKxOJOFtb0wQyIhL9RyCwK3AOfIGp1YFEBhnMJcLRWEbKdKQoU6ncTZkIEDicAy%2F81dVuEM5RwPfey4xOx0Ik%2FI2NnFki%2BWafOoFIYFcgYZCyxd7eCUjbc4AmF65ft%2FkMhk3o%2B5hc7sMJyqjJEGvYFaQFIr7Y0wPw8BFAY%2B6%2Bvmk3w6zzRuDMmZVRsfh8RtA0uETSD7uCBT6DYQN6iveU0fpkYLjE6qrVrtOxeNKU9THLZJ9kBU2JBsBhV5AivB%2FoKaQNKgPCBwDYaIfZC4adThOqF4WENViLJwVoXobfLBKVw67AOaTsLc65TaVK21vQ4La99eKcYg5vbxsbObzTQ9N7UKDgUO1wDjiDIIBshh5ztg39nQMLSZBH4OzBOUDEQXm206d3fcLgswbXQA4PhcK3nhswU1Bz8wvQ09RHG%2FoYy3ejfwBNmtoYqLA0XgAAAABJRU5ErkJggg%3D%3D&amp;label=CreatedAt\" style=\"max-width: 100%;\"></a></td>\n</tr>\n</tbody>\n</table></markdown-accessiblity-table>\n<a href=\"https://github.com/opsre/awesome-ops\">\n</a><p dir=\"auto\"><a href=\"https://github.com/opsre/awesome-ops\"><img src=\"https://camo.githubusercontent.com/b964a36ea4078c39f603d46a29436371c7541a2f26e0228d7b21b9d9805b43d3/68747470733a2f2f736f6369616c6966792e6769742e63692f6f707372652f617765736f6d652d6f70732f696d6167653f6465736372697074696f6e3d3126666f6e743d42697474657226666f726b733d31266973737565733d31266c616e67756167653d31266c6f676f3d6874747073253341253246253246617661746172732e67697468756275736572636f6e74656e742e636f6d25324675253246313838353638303230266e616d653d31266f776e65723d31267061747465726e3d436972637569742b426f6172642670756c6c733d31267374617267617a6572733d31267468656d653d4c69676874\" alt=\"\" data-canonical-src=\"https://socialify.git.ci/opsre/awesome-ops/image?description=1&amp;font=Bitter&amp;forks=1&amp;issues=1&amp;language=1&amp;logo=https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F188568020&amp;name=1&amp;owner=1&amp;pattern=Circuit+Board&amp;pulls=1&amp;stargazers=1&amp;theme=Light\" style=\"max-width: 100%;\"></a></p>\n<a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/a15b413168923d02e21292705ceaf86b92675f98e250c5c896a02ba7504a6eae/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f657279616a662f7475406d61696e2f696d672f696d6167655f32303234303432305f3231343430382e676966\"><img src=\"https://camo.githubusercontent.com/a15b413168923d02e21292705ceaf86b92675f98e250c5c896a02ba7504a6eae/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f657279616a662f7475406d61696e2f696d672f696d6167655f32303234303432305f3231343430382e676966\" width=\"100%\" height=\"3\" data-animated-image=\"\" data-canonical-src=\"https://cdn.jsdelivr.net/gh/eryajf/tu@main/img/image_20240420_214408.gif\" style=\"max-width: 100%; height: auto; max-height: 3px;\"></a>\n</div>\n<h1 dir=\"auto\">rathole</h1>\n<p dir=\"auto\"><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"./docs/img/rathole-logo.png\"><img src=\"./docs/img/rathole-logo.png\" alt=\"rathole-logo\" style=\"max-width: 100%;\"></a></p>\n<p dir=\"auto\"><a href=\"https://github.com/rapiz1/rathole/stargazers\"><img src=\"https://camo.githubusercontent.com/971aff298ccf02cd873a749934c02642fccc7e35e386baa9b3f848bd9a31cced/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f726170697a312f726174686f6c65\" alt=\"GitHub stars\" data-canonical-src=\"https://img.shields.io/github/stars/rapiz1/rathole\" style=\"max-width: 100%;\"></a><br>\n<a href=\"https://github.com/rapiz1/rathole/releases\"><img src=\"https://camo.githubusercontent.com/ce33560768be151b72767025ae60eb686a19f5cdc4b9a6bcdceeff82e36e718f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f726170697a312f726174686f6c65\" alt=\"GitHub release (latest SemVer)\" data-canonical-src=\"https://img.shields.io/github/v/release/rapiz1/rathole\" style=\"max-width: 100%;\"></a><br>\n<a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/d4b740ae4f2a3ed587acce89844700c93a04ab15b3169b6040560b3b09c5cba8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f726170697a312f726174686f6c652f727573742e796d6c3f6272616e63683d6d61696e\"><img src=\"https://camo.githubusercontent.com/d4b740ae4f2a3ed587acce89844700c93a04ab15b3169b6040560b3b09c5cba8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f726170697a312f726174686f6c652f727573742e796d6c3f6272616e63683d6d61696e\" alt=\"GitHub Workflow Status (branch)\" data-canonical-src=\"https://img.shields.io/github/actions/workflow/status/rapiz1/rathole/rust.yml?branch=main\" style=\"max-width: 100%;\"></a><br>\n<a href=\"https://github.com/rapiz1/rathole/releases\"><img src=\"https://camo.githubusercontent.com/e38c0591a9d123cbcfafd10fdede4390e3e11b0376807a0295937800652bf010/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f646f776e6c6f6164732f726170697a312f726174686f6c652f746f74616c\" alt=\"GitHub all releases\" data-canonical-src=\"https://img.shields.io/github/downloads/rapiz1/rathole/total\" style=\"max-width: 100%;\"></a><br>\n<a href=\"https://hub.docker.com/r/rapiz1/rathole\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/e4cf7989aee91a1cf487301247951900307a8168e6370ceb80c9efd50542bb38/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f726170697a312f726174686f6c65\" alt=\"Docker Pulls\" data-canonical-src=\"https://img.shields.io/docker/pulls/rapiz1/rathole\" style=\"max-width: 100%;\"></a><br>\n<a href=\"https://gitter.im/rapiz1/rathole?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/ff44d2d794841ad24464334fd36558cdbf26d9be5ed0da80998abb46ff4fdb4d/68747470733a2f2f6261646765732e6769747465722e696d2f726170697a312f726174686f6c652e737667\" alt=\"Join the chat at https://gitter.im/rapiz1/rathole\" data-canonical-src=\"https://badges.gitter.im/rapiz1/rathole.svg\" style=\"max-width: 100%;\"></a></p>\n<p dir=\"auto\"><a href=\"README.md\">English</a> | <a href=\"README-zh.md\">简体中文</a></p>\n<p dir=\"auto\">A secure, stable and high-performance reverse proxy for NAT traversal, written in Rust</p>\n<p dir=\"auto\">rathole, like <a href=\"https://github.com/fatedier/frp\">frp</a> and <a href=\"https://github.com/inconshreveable/ngrok\">ngrok</a>, can help to expose the service on the device behind the NAT to the Internet, via a server with a public IP.</p>\n\n<ul dir=\"auto\">\n<li><a href=\"#rathole\">rathole</a>\n<ul dir=\"auto\">\n<li><a href=\"#features\">Features</a></li>\n<li><a href=\"#quickstart\">Quickstart</a></li>\n<li><a href=\"#configuration\">Configuration</a>\n<ul dir=\"auto\">\n<li><a href=\"#logging\">Logging</a></li>\n<li><a href=\"#tuning\">Tuning</a></li>\n</ul>\n</li>\n<li><a href=\"#benchmark\">Benchmark</a></li>\n<li><a href=\"#planning\">Planning</a></li>\n</ul>\n</li>\n</ul>\n\n<h2 dir=\"auto\">Features</h2>\n<ul dir=\"auto\">\n<li><strong>High Performance</strong> Much higher throughput can be achieved than frp, and more stable when handling a large volume of connections. See <a href=\"#benchmark\">Benchmark</a></li>\n<li><strong>Low Resource Consumption</strong> Consumes much fewer memory than similar tools. See <a href=\"#benchmark\">Benchmark</a>. <a href=\"docs/build-guide.md\">The binary can be</a> <strong>as small as ~500KiB</strong> to fit the constraints of devices, like embedded devices as routers.</li>\n<li><strong>Security</strong> 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.</li>\n<li><strong>Hot Reload</strong> Services can be added or removed dynamically by hot-reloading the configuration file. HTTP API is WIP.</li>\n</ul>\n<h2 dir=\"auto\">Quickstart</h2>\n<p dir=\"auto\">A full-powered <code class=\"notranslate\">rathole</code> can be obtained from the <a href=\"https://github.com/rapiz1/rathole/releases\">release</a> page. Or <a href=\"docs/build-guide.md\">build from source</a> <strong>for other platforms and minimizing the binary</strong>. A <a href=\"https://hub.docker.com/r/rapiz1/rathole\" rel=\"nofollow\">Docker image</a> is also available.</p>\n<p dir=\"auto\">The usage of <code class=\"notranslate\">rathole</code> 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.</p>\n<p dir=\"auto\">To use <code class=\"notranslate\">rathole</code>, 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.</p>\n<p dir=\"auto\">Assuming you have a NAS at home behind the NAT, and want to expose its ssh service to the Internet:</p>\n<ol dir=\"auto\">\n<li>On the server which has a public IP</li>\n</ol>\n<p dir=\"auto\">Create <code class=\"notranslate\">server.toml</code> with the following content and accommodate it to your needs.</p>\n<div class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# server.toml\n[server]\nbind_addr = &quot;0.0.0.0:2333&quot; # `2333` specifies the port that rathole listens for clients\n\n[server.services.my_nas_ssh]\ntoken = &quot;use_a_secret_that_only_you_know&quot; # Token that is used to authenticate the client for the service. Change to an arbitrary value.\nbind_addr = &quot;0.0.0.0:5202&quot; # `5202` specifies the port that exposes `my_nas_ssh` to the Internet\"><pre class=\"notranslate\"><span class=\"pl-c\"><span class=\"pl-c\">#</span> server.toml</span>\n[<span class=\"pl-en\">server</span>]\n<span class=\"pl-smi\">bind_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>0.0.0.0:2333<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> `2333` specifies the port that rathole listens for clients</span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">services</span>.<span class=\"pl-en\">my_nas_ssh</span>]\n<span class=\"pl-smi\">token</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>use_a_secret_that_only_you_know<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Token that is used to authenticate the client for the service. Change to an arbitrary value.</span>\n<span class=\"pl-smi\">bind_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>0.0.0.0:5202<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> `5202` specifies the port that exposes `my_nas_ssh` to the Internet</span></pre></div>\n<p dir=\"auto\">Then run:</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"./rathole server.toml\"><pre class=\"notranslate\">./rathole server.toml</pre></div>\n<ol start=\"2\" dir=\"auto\">\n<li>On the host which is behind the NAT (your NAS)</li>\n</ol>\n<p dir=\"auto\">Create <code class=\"notranslate\">client.toml</code> with the following content and accommodate it to your needs.</p>\n<div class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# client.toml\n[client]\nremote_addr = &quot;myserver.com:2333&quot; # 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 = &quot;use_a_secret_that_only_you_know&quot; # Must be the same with the server to pass the validation\nlocal_addr = &quot;127.0.0.1:22&quot; # The address of the service that needs to be forwarded\"><pre class=\"notranslate\"><span class=\"pl-c\"><span class=\"pl-c\">#</span> client.toml</span>\n[<span class=\"pl-en\">client</span>]\n<span class=\"pl-smi\">remote_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>myserver.com:2333<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> The address of the server. The port must be the same with the port in `server.bind_addr`</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">services</span>.<span class=\"pl-en\">my_nas_ssh</span>]\n<span class=\"pl-smi\">token</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>use_a_secret_that_only_you_know<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Must be the same with the server to pass the validation</span>\n<span class=\"pl-smi\">local_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>127.0.0.1:22<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> The address of the service that needs to be forwarded</span></pre></div>\n<p dir=\"auto\">Then run:</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"./rathole client.toml\"><pre class=\"notranslate\">./rathole client.toml</pre></div>\n<ol start=\"3\" dir=\"auto\">\n<li>Now the client will try to connect to the server <code class=\"notranslate\">myserver.com</code> on port <code class=\"notranslate\">2333</code>, and any traffic to <code class=\"notranslate\">myserver.com:5202</code> will be forwarded to the client's port <code class=\"notranslate\">22</code>.</li>\n</ol>\n<p dir=\"auto\">So you can <code class=\"notranslate\">ssh myserver.com:5202</code> to ssh to your NAS.</p>\n<p dir=\"auto\">To run <code class=\"notranslate\">rathole</code> run as a background service on Linux, checkout the <a href=\"./examples/systemd\">systemd examples</a>.</p>\n<h2 dir=\"auto\">Configuration</h2>\n<p dir=\"auto\"><code class=\"notranslate\">rathole</code> 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 <code class=\"notranslate\">[server]</code> and <code class=\"notranslate\">[client]</code> block is present, like the example in <a href=\"#quickstart\">Quickstart</a>.</p>\n<p dir=\"auto\">But the <code class=\"notranslate\">[client]</code> and <code class=\"notranslate\">[server]</code> block can also be put in one file. Then on the server side, run <code class=\"notranslate\">rathole --server config.toml</code> and on the client side, run <code class=\"notranslate\">rathole --client config.toml</code> to explicitly tell <code class=\"notranslate\">rathole</code> the running mode.</p>\n<p dir=\"auto\">Before heading to the full configuration specification, it's recommend to skim <a href=\"./examples\">the configuration examples</a> to get a feeling of the configuration format.</p>\n<p dir=\"auto\">See <a href=\"./docs/transport.md\">Transport</a> for more details about encryption and the <code class=\"notranslate\">transport</code> block.</p>\n<p dir=\"auto\">Here is the full configuration specification:</p>\n<div class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"[client]\nremote_addr = &quot;example.com:2333&quot; # Necessary. The address of the server\ndefault_token = &quot;default_token_if_not_specify&quot; # 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 = &quot;tcp&quot; # Optional. Possible values: [&quot;tcp&quot;, &quot;tls&quot;, &quot;noise&quot;]. Default: &quot;tcp&quot;\n\n[client.transport.tcp] # Optional. Also affects `noise` and `tls`\nproxy = &quot;socks5://user:passwd@127.0.0.1:1080&quot; # 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 &quot;tls&quot;\ntrusted_root = &quot;ca.pem&quot; # Necessary. The certificate of CA that signed the server's certificate\nhostname = &quot;example.com&quot; # 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/transport.md` for further explanation\npattern = &quot;Noise_NK_25519_ChaChaPoly_BLAKE2s&quot; # Optional. Default value as shown\nlocal_private_key = &quot;key_encoded_in_base64&quot; # Optional\nremote_public_key = &quot;key_encoded_in_base64&quot; # Optional\n\n[client.transport.websocket] # Necessary if `type` is &quot;websocket&quot;\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 = &quot;tcp&quot; # Optional. The protocol that needs forwarding. Possible values: [&quot;tcp&quot;, &quot;udp&quot;]. Default: &quot;tcp&quot;\ntoken = &quot;whatever&quot; # Necessary if `client.default_token` not set\nlocal_addr = &quot;127.0.0.1:1081&quot; # 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 = &quot;127.0.0.1:1082&quot;\n\n[server]\nbind_addr = &quot;0.0.0.0:2333&quot; # Necessary. The address that the server listens for clients. Generally only the port needs to be change.\ndefault_token = &quot;default_token_if_not_specify&quot; # 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 = &quot;tcp&quot;\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 &quot;tls&quot;\npkcs12 = &quot;identify.pfx&quot; # Necessary. pkcs12 file of server's certificate and private key\npkcs12_password = &quot;password&quot; # Necessary. Password of the pkcs12 file\n\n[server.transport.noise] # Same as `[client.transport.noise]`\npattern = &quot;Noise_NK_25519_ChaChaPoly_BLAKE2s&quot;\nlocal_private_key = &quot;key_encoded_in_base64&quot;\nremote_public_key = &quot;key_encoded_in_base64&quot;\n\n[server.transport.websocket] # Necessary if `type` is &quot;websocket&quot;\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 = &quot;tcp&quot; # Optional. Same as the client `[client.services.X.type]\ntoken = &quot;whatever&quot; # Necessary if `server.default_token` not set\nbind_addr = &quot;0.0.0.0:8081&quot; # 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 = &quot;0.0.0.1:8082&quot;\"><pre class=\"notranslate\">[<span class=\"pl-en\">client</span>]\n<span class=\"pl-smi\">remote_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>example.com:2333<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. The address of the server</span>\n<span class=\"pl-smi\">default_token</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>default_token_if_not_specify<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The default token of services, if they don't define their own ones</span>\n<span class=\"pl-smi\">heartbeat_timeout</span> = <span class=\"pl-c1\">40</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Set to 0 to disable the application-layer heartbeat test. The value must be greater than `server.heartbeat_interval`. Default: 40 seconds</span>\n<span class=\"pl-smi\">retry_interval</span> = <span class=\"pl-c1\">1</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The interval between retry to connect to the server. Default: 1 second</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">transport</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> The whole block is optional. Specify which transport to use</span>\n<span class=\"pl-smi\">type</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>tcp<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Possible values: [\"tcp\", \"tls\", \"noise\"]. Default: \"tcp\"</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">tcp</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Also affects `noise` and `tls`</span>\n<span class=\"pl-smi\">proxy</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>socks5://user:passwd@127.0.0.1:1080<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The proxy used to connect to the server. `http` and `socks5` is supported.</span>\n<span class=\"pl-smi\">nodelay</span> = <span class=\"pl-c1\">true</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Determine whether to enable TCP_NODELAY, if applicable, to improve the latency but decrease the bandwidth. Default: true</span>\n<span class=\"pl-smi\">keepalive_secs</span> = <span class=\"pl-c1\">20</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Specify `tcp_keepalive_time` in `tcp(7)`, if applicable. Default: 20 seconds</span>\n<span class=\"pl-smi\">keepalive_interval</span> = <span class=\"pl-c1\">8</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Specify `tcp_keepalive_intvl` in `tcp(7)`, if applicable. Default: 8 seconds</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">tls</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary if `type` is \"tls\"</span>\n<span class=\"pl-smi\">trusted_root</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>ca.pem<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. The certificate of CA that signed the server's certificate</span>\n<span class=\"pl-smi\">hostname</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>example.com<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The hostname that the client uses to validate the certificate. If not set, fallback to `client.remote_addr`</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">noise</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Noise protocol. See `docs/transport.md` for further explanation</span>\n<span class=\"pl-smi\">pattern</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>Noise_NK_25519_ChaChaPoly_BLAKE2s<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Default value as shown</span>\n<span class=\"pl-smi\">local_private_key</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>key_encoded_in_base64<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional</span>\n<span class=\"pl-smi\">remote_public_key</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>key_encoded_in_base64<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">websocket</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary if `type` is \"websocket\"</span>\n<span class=\"pl-smi\">tls</span> = <span class=\"pl-c1\">true</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> If `true` then it will use settings in `client.transport.tls`</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">services</span>.<span class=\"pl-en\">service1</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> A service that needs forwarding. The name `service1` can change arbitrarily, as long as identical to the name in the server's configuration</span>\n<span class=\"pl-smi\">type</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>tcp<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The protocol that needs forwarding. Possible values: [\"tcp\", \"udp\"]. Default: \"tcp\"</span>\n<span class=\"pl-smi\">token</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>whatever<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary if `client.default_token` not set</span>\n<span class=\"pl-smi\">local_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>127.0.0.1:1081<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. The address of the service that needs to be forwarded</span>\n<span class=\"pl-smi\">nodelay</span> = <span class=\"pl-c1\">true</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Override the `client.transport.nodelay` per service</span>\n<span class=\"pl-smi\">retry_interval</span> = <span class=\"pl-c1\">1</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The interval between retry to connect to the server. Default: inherits the global config</span>\n\n[<span class=\"pl-en\">client</span>.<span class=\"pl-en\">services</span>.<span class=\"pl-en\">service2</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Multiple services can be defined</span>\n<span class=\"pl-smi\">local_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>127.0.0.1:1082<span class=\"pl-pds\">\"</span></span>\n\n[<span class=\"pl-en\">server</span>]\n<span class=\"pl-smi\">bind_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>0.0.0.0:2333<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. The address that the server listens for clients. Generally only the port needs to be change.</span>\n<span class=\"pl-smi\">default_token</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>default_token_if_not_specify<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional</span>\n<span class=\"pl-smi\">heartbeat_interval</span> = <span class=\"pl-c1\">30</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. The interval between two application-layer heartbeat. Set to 0 to disable sending heartbeat. Default: 30 seconds</span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">transport</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Same as `[client.transport]`</span>\n<span class=\"pl-smi\">type</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>tcp<span class=\"pl-pds\">\"</span></span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">tcp</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Same as the client</span>\n<span class=\"pl-smi\">nodelay</span> = <span class=\"pl-c1\">true</span>\n<span class=\"pl-smi\">keepalive_secs</span> = <span class=\"pl-c1\">20</span>\n<span class=\"pl-smi\">keepalive_interval</span> = <span class=\"pl-c1\">8</span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">tls</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary if `type` is \"tls\"</span>\n<span class=\"pl-smi\">pkcs12</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>identify.pfx<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. pkcs12 file of server's certificate and private key</span>\n<span class=\"pl-smi\">pkcs12_password</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>password<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. Password of the pkcs12 file</span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">noise</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Same as `[client.transport.noise]`</span>\n<span class=\"pl-smi\">pattern</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>Noise_NK_25519_ChaChaPoly_BLAKE2s<span class=\"pl-pds\">\"</span></span>\n<span class=\"pl-smi\">local_private_key</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>key_encoded_in_base64<span class=\"pl-pds\">\"</span></span>\n<span class=\"pl-smi\">remote_public_key</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>key_encoded_in_base64<span class=\"pl-pds\">\"</span></span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">transport</span>.<span class=\"pl-en\">websocket</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary if `type` is \"websocket\"</span>\n<span class=\"pl-smi\">tls</span> = <span class=\"pl-c1\">true</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> If `true` then it will use settings in `server.transport.tls`</span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">services</span>.<span class=\"pl-en\">service1</span>] <span class=\"pl-c\"><span class=\"pl-c\">#</span> The service name must be identical to the client side</span>\n<span class=\"pl-smi\">type</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>tcp<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Same as the client `[client.services.X.type]</span>\n<span class=\"pl-smi\">token</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>whatever<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary if `server.default_token` not set</span>\n<span class=\"pl-smi\">bind_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>0.0.0.0:8081<span class=\"pl-pds\">\"</span></span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Necessary. The address of the service is exposed at. Generally only the port needs to be change.</span>\n<span class=\"pl-smi\">nodelay</span> = <span class=\"pl-c1\">true</span> <span class=\"pl-c\"><span class=\"pl-c\">#</span> Optional. Same as the client</span>\n\n[<span class=\"pl-en\">server</span>.<span class=\"pl-en\">services</span>.<span class=\"pl-en\">service2</span>]\n<span class=\"pl-smi\">bind_addr</span> = <span class=\"pl-s\"><span class=\"pl-pds\">\"</span>0.0.0.1:8082<span class=\"pl-pds\">\"</span></span></pre></div>\n<h3 dir=\"auto\">Logging</h3>\n<p dir=\"auto\"><code class=\"notranslate\">rathole</code>, like many other Rust programs, use environment variables to control the logging level. <code class=\"notranslate\">info</code>, <code class=\"notranslate\">warn</code>, <code class=\"notranslate\">error</code>, <code class=\"notranslate\">debug</code>, <code class=\"notranslate\">trace</code> are available.</p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"RUST_LOG=error ./rathole config.toml\"><pre class=\"notranslate\">RUST_LOG=error ./rathole config.toml</pre></div>\n<p dir=\"auto\">will run <code class=\"notranslate\">rathole</code> with only error level logging.</p>\n<p dir=\"auto\">If <code class=\"notranslate\">RUST_LOG</code> is not present, the default logging level is <code class=\"notranslate\">info</code>.</p>\n<h3 dir=\"auto\">Tuning</h3>\n<p dir=\"auto\">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.</p>\n<p dir=\"auto\">If the bandwidth is more important, TCP_NODELAY can be opted out with <code class=\"notranslate\">nodelay = false</code>.</p>\n<h2 dir=\"auto\">Benchmark</h2>\n<p dir=\"auto\">rathole has similar latency to <a href=\"https://github.com/fatedier/frp\">frp</a>, but can handle a more connections, provide larger bandwidth, with less memory usage.</p>\n<p dir=\"auto\">For more details, see the separate page <a href=\"./docs/benchmark.md\">Benchmark</a>.</p>\n<p dir=\"auto\"><strong>However, don't take it from here that <code class=\"notranslate\">rathole</code> can magically make your forwarded service faster several times than before.</strong> 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.</p>\n<p dir=\"auto\"><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"./docs/img/http_throughput.svg\"><img src=\"./docs/img/http_throughput.svg\" alt=\"http_throughput\" style=\"max-width: 100%;\"></a><br>\n<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"./docs/img/tcp_bitrate.svg\"><img src=\"./docs/img/tcp_bitrate.svg\" alt=\"tcp_bitrate\" style=\"max-width: 100%;\"></a><br>\n<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"./docs/img/udp_bitrate.svg\"><img src=\"./docs/img/udp_bitrate.svg\" alt=\"udp_bitrate\" style=\"max-width: 100%;\"></a><br>\n<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"./docs/img/mem-graph.png\"><img src=\"./docs/img/mem-graph.png\" alt=\"mem\" style=\"max-width: 100%;\"></a></p>\n<h2 dir=\"auto\">Planning</h2>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"\" disabled=\"\" class=\"task-list-item-checkbox\" aria-label=\"Incomplete task\"> HTTP APIs for configuration</li>\n</ul>\n<p dir=\"auto\"><a href=\"./docs/out-of-scope.md\">Out of Scope</a> lists features that are not planned to be implemented and why.</p>","updatedAt":"2025-05-21T16:17:58Z","upvoteCount":null,"author":{"login":"eryajf","avatarUrl":"https://avatars.githubusercontent.com/u/33259379?u=e4a4090a38ac2473aaed4ef9945233636776c6c3&v=4","url":"https://github.com/eryajf"},"category":null,"labels":{"edges":[{"node":{"name":"更多","color":"25B472"}},{"node":{"name":"内网穿透","color":"4b9909"}},{"node":{"name":"rapiz1","color":"5d0e13"}}]},"comments":{"edges":[]}}},"pageContext":{"number":469,"previous":{"title":"rancher/rancher: 一个开源容器管理平台，专为在生产中部署容器的组织而构建。Rancher 让您可以轻松地在任何地方运行 Kubernetes、满足 IT 要求并为 DevOps 团队提供支持","number":468},"next":{"title":"rdiff-backup/rdiff-backup: rdiff-backup 是一个简单的备份工具，可以在本地和远程、Linux 和 Windows 上使用，甚至可以在两者之间跨平台使用。","number":470}}},
    "staticQueryHashes": ["151096407","2861350382"]}