docs: README - SSH terminal, sending to other machines, PIN, passkeys, WebSocket transport, Cloudflare and nginx notes
This commit is contained in:
1 parent
18d6684c55
commit
467bd3cb4f
1 file changed
+96
-40
@@ -1,74 +1,130 @@
|
||||
# LPRA - LongPolling Remote Access
|
||||
|
||||
Лёгкий self-hosted сервис для доступа к Linux-машинам **без белого IP** (за NAT).
|
||||
Агент на клиенте сам исходяще подключается к серверу по HTTP long-polling; админ
|
||||
в веб-панели видит список машин и открывает по каждой **терминал в браузере** (по умолчанию от root, пользователя можно сменить).
|
||||
Агент на клиенте сам исходяще подключается к серверу - по WebSocket, а где он не проходит,
|
||||
по HTTP long-polling. В веб-панели видно список машин, и по каждой есть терминал в браузере,
|
||||
файловый менеджер, проброс портов и статус.
|
||||
|
||||
```
|
||||
браузер ──WS──> [nginx :8445 TLS] ──> [Go server 127.0.0.1:8091] <──long-poll── агент (root, за NAT)
|
||||
│
|
||||
SQLite
|
||||
браузер ──HTTPS/WS──> [Cloudflare] ──> [nginx TLS] ──> [Go server 127.0.0.1:8091] <──WS / long-poll── агент (за NAT)
|
||||
│ ▲
|
||||
SQLite └──── прямой TCP/UDP-туннель :8446 (проброс tcp/udp)
|
||||
```
|
||||
|
||||
## Возможности
|
||||
- **Терминал** - вкладки на нескольких машинах сразу, до четырёх терминалов в одной вкладке
|
||||
(перетаскиванием, с изменяемыми размерами), переименование вкладок. На телефоне - панель
|
||||
клавиш (Esc, Ctrl, Alt, стрелки и т.д.).
|
||||
- **SSH-терминал** - в меню «+»: агент открывает SSH-соединение к другому хосту (по паролю,
|
||||
ключу - можно загрузить файл - или своими ключами из `~/.ssh`), шелл открывается во вкладке,
|
||||
а шаги подключения видны в статусе. Ключ хоста запоминается при первом входе
|
||||
(`ssh_known_hosts` рядом с `state.json` агента); если он сменится, вход откажет.
|
||||
- **Файлы** - просмотр, редактор с подсветкой, hex-редактор, предпросмотр картинок, видео, PDF,
|
||||
таблиц SQLite; загрузка и скачивание до 512 МБ кусками по 4 МБ (проходит через Cloudflare);
|
||||
свойства (chmod/chown), zip/unzip.
|
||||
- **Перемещение и копирование** - внутри машины или, кнопкой «сеть» в том же окне, **на другую
|
||||
машину или на SSH-хост**: папка уходит потоком tar без промежуточных файлов, с прогрессом,
|
||||
скоростью и отменой. «Переместить» удаляет исходник после успешной отправки. Правила для
|
||||
существующего: сообщить / заменить / оставить как есть.
|
||||
- **Проброс портов** - `http` через панель, `tcp`/`udp` через прямой туннель.
|
||||
- **Статус** - нагрузка, память, диски, сеть, тест скорости канала до сервера.
|
||||
- **Вход** - пароль и/или ключи доступа (passkeys); пароль можно выключить, когда есть ключ.
|
||||
- **PIN-код** (необязательный, 4 цифры) - спрашивается в каждой новой вкладке браузера, но не при
|
||||
перезагрузке. На устройстве можно не спрашивать его 5/15/30/60 минут после ввода.
|
||||
Пять неверных попыток - выход из сессии.
|
||||
|
||||
## Компоненты
|
||||
- **Сервер** (`cmd/server`) - админ-панель + точка встречи для агентов. За nginx (TLS).
|
||||
- **Агент** (`cmd/agent`) - Linux-бинарь, systemd-сервис от root, PTY по запросу.
|
||||
- **install.sh** - интерактивный установщик, отдаётся сервером как статика.
|
||||
- **Сервер** (`cmd/server`) - панель и точка встречи для агентов. Ставится за nginx (TLS).
|
||||
- **Агент** (`cmd/agent`) - бинарь для Linux (amd64/arm64), systemd-сервис от root.
|
||||
- **install.sh** - установщик агента, отдаётся сервером.
|
||||
|
||||
## Сборка
|
||||
```sh
|
||||
./build.sh
|
||||
```
|
||||
Получаются `bin/lpra-server` и `dist/agent-linux-{amd64,arm64}`.
|
||||
Получаются `bin/lpra-server*` и `dist/agent-linux-{amd64,arm64}`.
|
||||
Версия задаётся в одном месте - `VERSION.txt`, она вшивается в сервер и агент.
|
||||
|
||||
## Запуск сервера
|
||||
```sh
|
||||
./bin/lpra-server -addr 127.0.0.1:8091 -dist ./dist -db ./lpra.db
|
||||
```
|
||||
Поставьте перед ним nginx по `deploy/nginx.conf.example` (TLS, long-poll/WS).
|
||||
Локально без TLS можно добавить `-insecure-cookies`.
|
||||
| Флаг | Переменная | По умолчанию | |
|
||||
|---|---|---|---|
|
||||
| `-addr` | `LPRA_ADDR` | `127.0.0.1:8091` | адрес HTTP (за nginx) |
|
||||
| `-db` | `LPRA_DB` | `lpra.db` | база SQLite |
|
||||
| `-dist` | `LPRA_DIST` | `dist` | бинарники агента для `/download/` |
|
||||
| `-tunnel` | `LPRA_TUNNEL_ADDR` | `:8446` | прямой туннель TCP+UDP (пусто - выключен) |
|
||||
| `-insecure-cookies` | `LPRA_INSECURE_COOKIES=1` | | куки без Secure - только для локального запуска без TLS |
|
||||
|
||||
Первый запуск: откройте `/setup` - мастер создаст администратора. Дальше `/settings`:
|
||||
адрес хоста (по умолчанию `https://localhost:8445`), enroll-секрет и готовая
|
||||
команда установки.
|
||||
Пример юнита - `deploy/lpra-server.service`.
|
||||
|
||||
## Установка агента на клиент
|
||||
Одной командой (под root):
|
||||
```sh
|
||||
curl -fsSL https://localhost:8445/install.sh | sudo HOST=https://localhost:8445 ENROLL_SECRET=<секрет> sh
|
||||
Первый запуск: откройте `/setup` - мастер создаст администратора. Дальше в `/settings`:
|
||||
адрес хоста, enroll-секрет, короткий код установки и готовая команда.
|
||||
|
||||
### nginx
|
||||
Конфиг - `deploy/nginx.conf.example`. Обязательно:
|
||||
- заголовки `Upgrade` / `Connection` (через `map $http_upgrade $connection_upgrade`) - без них
|
||||
WebSocket не пройдёт, и агенты и терминалы останутся на long-polling (работает, но медленнее
|
||||
на больших выводах);
|
||||
- `proxy_read_timeout` больше 25 с (удержание long-poll), `proxy_buffering off`.
|
||||
|
||||
### Cloudflare
|
||||
Работает за проксирующим Cloudflare: WebSocket он пропускает, файлы идут кусками меньше лимита
|
||||
на запрос, статика с хешем в имени кэшируется. Чтобы панель видела настоящие IP (ограничение
|
||||
попыток входа и кода установки считается по адресу), включите в nginx real IP:
|
||||
```nginx
|
||||
real_ip_header CF-Connecting-IP;
|
||||
set_real_ip_from 173.245.48.0/20; # и остальные диапазоны с https://www.cloudflare.com/ips/
|
||||
```
|
||||
Или интерактивно (спросит секрет, а если агент уже стоит - предложит удалить):
|
||||
Прямой туннель (`:8446`) - это не HTTP, через проксирующий Cloudflare он не идёт: в
|
||||
«Настройки → Прямой туннель» укажите для агентов IP хоста или DNS-имя без проксирования.
|
||||
|
||||
## Установка агента
|
||||
Короткой командой из `/settings` (код из 3-24 букв и цифр, кнопка «Новый код» меняет его):
|
||||
```sh
|
||||
curl -fsSL https://localhost:8445/install.sh | sudo sh
|
||||
curl -fsSL https://panel.example/i/<код> | sudo sh
|
||||
```
|
||||
Или полной:
|
||||
```sh
|
||||
curl -fsSL https://panel.example/install.sh | sudo HOST=https://panel.example ENROLL_SECRET=<секрет> sh
|
||||
```
|
||||
Без параметров установщик спросит секрет, а если агент уже стоит - предложит удалить.
|
||||
Обновить агента можно кнопкой в панели («Изменить» → обновить).
|
||||
|
||||
## Связь агента с сервером
|
||||
В «Изменить» → «Связь с сервером» для каждой машины:
|
||||
- **auto** (по умолчанию) - WebSocket; если он не подключается, long-polling ровно минуту, потом
|
||||
снова попытка WebSocket;
|
||||
- **ws** - только WebSocket;
|
||||
- **lp** - только long-polling.
|
||||
|
||||
## Проброс портов и прямой туннель
|
||||
Правила проброса создаются на странице машины. Режим `http` идёт через адрес панели (long-poll),
|
||||
режимы `tcp`/`udp` - через прямой туннель: агент держит исходящее соединение к порту туннеля хоста
|
||||
(флаг `-tunnel` / `LPRA_TUNNEL_ADDR`).
|
||||
Правила создаются на странице машины «Порты». Режим `http` идёт через адрес панели,
|
||||
`tcp`/`udp` - через прямой туннель: агент держит исходящее соединение к порту туннеля хоста,
|
||||
по нему мультиплексируются все соединения.
|
||||
|
||||
Порт туннеля и хост, к которому для него подключаются агенты (например, IP вместо домена панели),
|
||||
меняются в `/settings` → «Прямой туннель». Агенты забирают адрес с панели сами - при подключении и
|
||||
при каждом опросе, переустановка не нужна. Локальные `TUNNEL_ADDR` / `TUNNEL_PORT` в окружении агента
|
||||
имеют приоритет над настройкой панели (`TUNNEL_ADDR=off` отключает туннель).
|
||||
Порт туннеля и хост для агентов меняются в `/settings` → «Прямой туннель»; агенты забирают их
|
||||
сами, переустановка не нужна. Локальные `TUNNEL_ADDR` / `TUNNEL_PORT` в окружении агента имеют
|
||||
приоритет (`TUNNEL_ADDR=off` отключает туннель).
|
||||
|
||||
Если на хосте активен ufw и сервер запущен от root, панель сама открывает порт хоста правила
|
||||
(tcp для `http`/`tcp`, udp для `udp`) и порт туннеля для прямых режимов, а при удалении правила - закрывает.
|
||||
При `ProtectSystem=strict` в systemd-юните ufw нужны права на запись: `ReadWritePaths=/etc/ufw /run`.
|
||||
|
||||
## Версия
|
||||
Версия задаётся в одном месте - `VERSION.txt`; файл вшивается в сервер и агент при сборке.
|
||||
Если на хосте активен ufw и сервер запущен от root, панель сама открывает порты правил и порт
|
||||
туннеля, а при удалении правила закрывает. При `ProtectSystem=strict` в юните нужно
|
||||
`ReadWritePaths=/etc/ufw /run`.
|
||||
|
||||
## Пользователь терминала
|
||||
По умолчанию терминал открывается от пользователя, под которым запущен агент (на Linux - root).
|
||||
В окне «Изменить машину» можно выбрать другого пользователя машины или создать нового
|
||||
(имя, пароль, опционально - добавить в sudo). Смена и создание работают, только если агент запущен от root.
|
||||
Файловый менеджер по-прежнему работает от пользователя агента.
|
||||
По умолчанию терминал открывается от пользователя агента (root). В «Изменить машину» можно выбрать
|
||||
другого пользователя или создать нового (с паролем, по желанию с sudo) - если агент запущен от root.
|
||||
Файловый менеджер работает от пользователя агента.
|
||||
|
||||
## Безопасность
|
||||
- Пароли админов - bcrypt; сессии в HttpOnly/Secure/SameSite куках; CSRF на формах; rate-limit логина.
|
||||
- Агенты: общий enroll-секрет → индивидуальный токен (хранится хешем, сверка constant-time).
|
||||
- Открытие терминала пишется в таблицу `audit` (терминал даёт root-доступ), как и смена/создание пользователя.
|
||||
- Пароли админов - bcrypt; сессии в HttpOnly/Secure/SameSite куках; CSRF на формах;
|
||||
ограничение попыток входа, PIN и кода установки.
|
||||
- Ключи доступа (WebAuthn) - вход без пароля; пароль можно выключить совсем.
|
||||
- Агенты: общий enroll-секрет → индивидуальный токен (хранится хешем, сверка constant-time);
|
||||
туннель авторизуется HMAC от токена.
|
||||
- SSH-пароли и ключи передаются агенту один раз для подключения и нигде не сохраняются.
|
||||
- Открытие терминала и SSH, перенос файлов на другие машины, смена пользователя пишутся в `audit`.
|
||||
|
||||
## Скриншоты
|
||||
<img width="1256" height="709" alt="image" src="https://github.com/user-attachments/assets/5f0b30f1-d5e3-4b62-817e-4041641df6e3" />
|
||||
|
||||
Reference in new issue
Block a user