
Легковесный и высокопроизводительный обратный прокси для обхода NAT, написанный на Rust. Альтернатива frp и ngrok.

Безопасный, стабильный и высокопроизводительный обратный прокси для обхода NAT, написанный на Rust
rathole, как и frp и ngrok, помогает предоставить доступ к сервису на устройстве за NAT через сервер с публичным IP.
Полнофункциональный rathole можно получить на странице релизов. Или собрать из исходников для других платформ и минимизации бинарного файла. Также доступен Docker-образ.
Использование rathole очень похоже на frp. Если у вас есть опыт работы с последним, то конфигурация будет очень простой. Единственное отличие в том, что конфигурация сервиса разделена на клиентскую и серверную части, и токен обязателен.
Для использования rathole вам нужен сервер с публичным IP и устройство за NAT, на котором работают сервисы, которые нужно предоставить в Интернет.
Предположим, у вас есть NAS дома за NAT, и вы хотите предоставить его SSH-сервис в Интернет:
Создайте server.toml со следующим содержимым и адаптируйте его под свои нужды.
# server.toml
[server]
bind_addr = "0.0.0.0:2333" # `2333` указывает порт, на котором rathole слушает клиентов
[server.services.my_nas_ssh]
token = "use_a_secret_that_only_you_know" # Токен для аутентификации клиента для этого сервиса. Измените на произвольное значение.
bind_addr = "0.0.0.0:5202" # `5202` указывает порт, который открывает `my_nas_ssh` в Интернет
Затем выполните:
./rathole server.toml
Создайте client.toml со следующим содержимым и адаптируйте его под свои нужды.
# client.toml
[client]
remote_addr = "myserver.com:2333" # Адрес сервера. Порт должен совпадать с портом в `server.bind_addr`
[client.services.my_nas_ssh]
token = "use_a_secret_that_only_you_know" # Должен совпадать с серверным для прохождения проверки
local_addr = "127.0.0.1:22" # Адрес сервиса, который нужно перенаправлять
Затем выполните:
./rathole client.toml
myserver.com на порту 2333, и любой трафик на myserver.com:5202 будет перенаправлен на порт клиента 22.Таким образом, вы можете выполнить ssh myserver.com:5202, чтобы подключиться по SSH к вашему NAS.
Чтобы запустить rathole как фоновый сервис в Linux, обратитесь к примерам systemd.
rathole может автоматически определить режим работы (серверный или клиентский) в зависимости от содержимого конфигурационного файла, если присутствует только один из блоков [server] или [client], как в примере из Быстрого старта.
Но блоки [client] и [server] также можно поместить в один файл. Тогда на стороне сервера выполните rathole --server config.toml, а на стороне клиента — rathole --client config.toml, чтобы явно указать rathole режим работы.
Прежде чем перейти к полной спецификации конфигурации, рекомендуется просмотреть примеры конфигурации, чтобы ознакомиться с форматом.
См. Transport для получения дополнительных сведений о шифровании и блоке transport.
Вот полная спецификация конфигурации:
[client]
remote_addr = "example.com:2333" # Обязательно. Адрес сервера
default_token = "default_token_if_not_specify" # Опционально. Токен по умолчанию для сервисов, если они не определяют свои собственные
heartbeat_timeout = 40 # Опционально. Установите 0, чтобы отключить проверку heartbeat на уровне приложения. Значение должно быть больше, чем `server.heartbeat_interval`. По умолчанию: 40 секунд
retry_interval = 1 # Опционально. Интервал между повторными попытками подключения к серверу. По умолчанию: 1 секунда
[client.transport] # Весь блок опционален. Указывает, какой транспорт использовать
type = "tcp" # Опционально. Возможные значения: ["tcp", "tls", "noise"]. По умолчанию: "tcp"
[client.transport.tcp] # Опционально. Также влияет на `noise` и `tls`
proxy = "socks5://user:[email protected]:1080" # Опционально. Прокси для подключения к серверу. Поддерживается `http` и `socks5`.
nodelay = true # Опционально. Определяет, включать ли TCP_NODELAY (если применимо) для уменьшения задержки, но снижения пропускной способности. По умолчанию: true
keepalive_secs = 20 # Опционально. Указывает `tcp_keepalive_time` из `tcp(7)`, если применимо. По умолчанию: 20 секунд
keepalive_interval = 8 # Опционально. Указывает `tcp_keepalive_intvl` из `tcp(7)`, если применимо. По умолчанию: 8 секунд
[client.transport.tls] # Необходимо, если `type` равен "tls"
trusted_root = "ca.pem" # Обязательно. Сертификат CA, подписавшего сертификат сервера
hostname = "example.com" # Опционально. Имя хоста, которое клиент использует для проверки сертификата. Если не задано, используется `client.remote_addr`
[client.transport.noise] # Протокол Noise. См. `docs/transport.md` для объяснения
pattern = "Noise_NK_25519_ChaChaPoly_BLAKE2s" # Опционально. Значение по умолчанию, как показано
local_private_key = "key_encoded_in_base64" # Опционально
remote_public_key = "key_encoded_in_base64" # Опционально
[client.transport.websocket] # Необходимо, если `type` равен "websocket"
tls = true # Если `true`, то используются настройки из `client.transport.tls`
[client.services.service1] # Сервис, который нужно перенаправлять. Имя `service1` можно менять произвольно, главное, чтобы оно совпадало с именем в конфигурации сервера
type = "tcp" # Опционально. Протокол, который нужно перенаправлять. Возможные значения: ["tcp", "udp"]. По умолчанию: "tcp"
token = "whatever" # Необходимо, если не задан `client.default_token`
local_addr = "127.0.0.1:1081" # Обязательно. Адрес сервиса, который нужно перенаправлять
nodelay = true # Опционально. Переопределяет `client.transport.nodelay` для данного сервиса
retry_interval = 1 # Опционально. Интервал между повторными попытками подключения к серверу. По умолчанию: наследует глобальную конфигурацию
[client.services.service2] # Можно определить несколько сервисов
local_addr = "127.0.0.1:1082"
[server]
bind_addr = "0.0.0.0:2333" # Обязательно. Адрес, на котором сервер слушает клиентов. Обычно нужно менять только порт.
default_token = "default_token_if_not_specify" # Опционально
heartbeat_interval = 30 # Опционально. Интервал между двумя heartbeat на уровне приложения. Установите 0, чтобы отключить отправку heartbeat. По умолчанию: 30 секунд
[server.transport] # То же, что и `[client.transport]`
type = "tcp"
[server.transport.tcp] # То же, что и у клиента
nodelay = true
keepalive_secs = 20
keepalive_interval = 8
[server.transport.tls] # Необходимо, если `type` равен "tls"
pkcs12 = "identify.pfx" # Обязательно. Файл pkcs12 с сертификатом сервера и закрытым ключом
pkcs12_password = "password" # Обязательно. Пароль от файла pkcs12
[server.transport.noise] # То же, что и `[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] # Необходимо, если `type` равен "websocket"
tls = true # Если `true`, то используются настройки из `server.transport.tls`
[server.services.service1] # Имя сервиса должно совпадать с клиентским
type = "tcp" # Опционально. То же, что и `[client.services.X.type]`
token = "whatever" # Необходимо, если не задан `server.default_token`
bind_addr = "0.0.0.0:8081" # Обязательно. Адрес, на котором предоставляется сервис. Обычно нужно менять только порт.
nodelay = true # Опционально. То же, что и у клиента
[server.services.service2]
bind_addr = "0.0.0.1:8082"
rathole, как и многие другие программы на Rust, использует переменные окружения для управления уровнем логирования. Доступны уровни info, warn, error, debug, trace.
RUST_LOG=error ./rathole config.toml
запустит rathole только с логированием ошибок.
Если RUST_LOG не задан, уровень логирования по умолчанию — info.
Начиная с версии v0.4.7, rathole включает TCP_NODELAY по умолчанию, что должно улучшить задержки и интерактивные приложения, такие как RDP, серверы Minecraft. Однако это немного снижает пропускную способность.
Если пропускная способность важнее, TCP_NODELAY можно отключить с помощью nodelay = false.
rathole имеет схожую задержку с frp, но может обрабатывать больше соединений, обеспечивать большую пропускную способность при меньшем потреблении памяти.
Для получения более подробной информации см. отдельную страницу Бенчмарк.
Однако не думайте, что rathole волшебным образом сделает ваш перенаправленный сервис в несколько раз быстрее. Бенчмарк выполняется на локальной петле (loopback), что отражает производительность, когда задача ограничена процессором. Можно получить значительное улучшение, если сеть не является узким местом. К сожалению, это не относится ко многим пользователям. В этом случае основным преимуществом является более низкое потребление ресурсов, в то время как пропускная способность и задержка могут не улучшиться существенно.

Out of Scope перечислены функции, которые не планируется реализовывать, и объясняется почему.