feat: SOCKS/proxy detection + tunnel auto-reconnect, uptime, copy command#12
feat: SOCKS/proxy detection + tunnel auto-reconnect, uptime, copy command#12rekurt wants to merge 4 commits into
Conversation
Add a ProxyListening heuristic that flags processes listening on well-known SOCKS/proxy ports (1080, 1081, 3128, 9050, 9150). 8080/8443 are deliberately excluded to avoid false positives on http-alt servers. The new reason plugs into the existing enrichment pipeline, so proxy listeners get the magenta + [!] treatment and match the 'suspicious' filter automatically. Also adds tor-socks/socks names to known_ports.
- Add an Uptime column (compact 45s/12m/3h04m/2d05h formatting), reset on restart. - Layer a listener health check over the Alive status: an alive ssh child with no local listener on its port (broken -D/-L bind) now shows a yellow 'no listener' warning instead of a misleading green 'alive'. Reuses already-scanned LISTEN entries — opens no new connections. - Add 'c' key to copy the tunnel's full ssh command to the clipboard, reusing the existing copy_to_clipboard helper. - New i18n strings (uptime column, no-listener, copy hint) in en/ru/zh.
Tunnels that die on their own are now automatically restarted with exponential backoff (2s doubling up to 60s) so an unreachable host isn't hammered. reconnect_failed() runs each loop iteration right after cleanup(); gating is by next_retry_at rather than the tick, and a successful restart resets the backoff. Manual kill removes a tunnel entirely, so only self-inflicted failures reconnect.
…t, model health Auto-reconnect (#1,#2,#3,#8): - Backoff now actually grows for unreachable hosts. The reset was tied to a 'successful' 150ms spawn, which an unreachable host passes (it blocks on TCP timeout), so the delay never increased. Growth now happens on every attempt and is reset only after a tunnel stays Alive for STABLE_THRESHOLD (30s), via refresh_health. - reconnect uses a new non-blocking restart_async() (no 150ms sleep in the render thread); failures are caught on the next tick. Manual restart() stays blocking for immediate feedback. - After MAX_RETRIES attempts without recovery a tunnel is marked permanently failed (auto_reconnect=false); drop_failed() now prunes only those, so 'save' no longer discards a tunnel that's mid-reconnect. auto_reconnect is now a meaningful flag. Listener health in the model (#4,#5): - New TunnelStatus::Unhealthy (process alive, local port not listening). Decision extracted to a pure, unit-tested decide_status(); a HEALTH_GRACE window and a scan_usable flag suppress false 'no listener' right after start and while auto-refresh is paused. cleanup() now takes the listening port set; the view no longer reaches into the scan. Cleanups: - command_string() shell-quotes args via shlex (#6). - uptime column reuses prt-core format_duration (#7). - private from_parts() constructor removes spawn duplication (#9). - cross-reference comments between PROXY_PORTS and known_ports (#10). New unit tests: decide_status, next_backoff, command_string quoting.
|
Closing as superseded by #13 ( That overlap is what made this branch conflict in every shared file. Generated by Claude Code |
Что и зачем
Три фичи вокруг SSH-туннелей / SOCKS5. Туннельная инфраструктура (
forward.rs,ssh_tunnel.rs,views/tunnels.rs, авто-старт из конфига) уже существовала — здесь закрыты конкретные пробелы.1. Детект локальных SOCKS/proxy-листенеров (
prt-core)Новая эвристика
ProxyListeningвsuspicious.rs: процесс, слушающий на well-known SOCKS/proxy-порту (1080, 1081, 3128, 9050, 9150).8080/8443намеренно исключены, чтобы не плодить ложные срабатывания на http-alt. Новая причина встраивается в существующий конвейер — листенер автоматически получает magenta-подсветку + бейдж[!]в Connections и попадает под фильтрsuspicious. Плюс именаsocks/tor-socksвknown_ports.2. Доработка UI туннелей (дёшевый набор, без новых соединений)
45s/12m/3h04m/2d05h), сбрасывается при рестарте.Alive: живой ssh-процесс без реального LISTEN на своём порту (типичный признак сломанного-D/-L) показывается жёлтымno listenerвместо обманчивого зелёногоalive. Переиспользует уже отсканированные данные — никаких новых соединений.c) — копирует полнуюssh-команду туннеля в буфер через существующийcopy_to_clipboard.3. Авто-reconnect упавших туннелей (
prt)Туннели, упавшие сами по себе, автоматически перезапускаются с экспоненциальным backoff (2s → ×2 → потолок 60s), чтобы не долбить недоступный хост.
reconnect_failed()вызывается каждый цикл послеcleanup(); гейтинг поnext_retry_at, успешный рестарт сбрасывает backoff. Ручной kill удаляет туннель целиком — реконнектятся только самопроизвольные падения.i18n
Новые строки (
tunnel_col_uptime,tunnel_health_no_listener,hint_copy_tunnel) добавлены во все три языка (en/ru/zh) — compile-time completeness-check проходит.Тесты
suspicious.rs: 1080/9050 LISTEN → flagged, 8080 → нет, ESTABLISHED → нет.fmt_uptime.cargo test --workspace— зелёный (197+ тестов),clippyиfmt --checkчисты.Ручная проверка
ssh -D 1080 localhost(илиnc -l 1080) → строка порта 1080 в Connections magenta +[!], ловится фильтромsuspicious.n) → растёт Uptime;c→ ssh-команда в буфере; health =aliveпри живом листенере.failed, затем повторы с растущим backoff; при восстановлении хоста сам переходит вalive.https://claude.ai/code/session_013YMo3DYYxbDAr6coo72M9W
Generated by Claude Code