10 Commits

Author SHA1 Message Date
Андрей Бобырев
3f2d621d02 fix(tunnel): close stdin so autossh survives backgrounding; add quick "+ Тоннель" button
Background autossh died immediately because nohup left stdin attached to the
closed curl pipe — autossh saw EOF and bailed. Add </dev/null and wrap in
subshell so the process is fully detached from the install script's session.

Also add an "+ Тоннель" button next to "+ Добавить": creates a router with a
placeholder base URL and opens the tunnel modal in one click — for routers
without a public IP that have nothing to put in the base URL field yet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 22:30:43 +03:00
Андрей Бобырев
61d80ebc22 fix(tunnel): one-liner curl|sh; keypair generated on VPS; on-page copy fallback
aarch64-k3.10 Entware lacks sshpass, cronie, and openssh-keygen. Generate the
ed25519 keypair on the VPS (where ssh-keygen is always present) and ship the
private key to the router inside the install script.

The router only sees a short curl|sh one-liner — easy to copy, immune to
markdown auto-linkification of .sh paths that mangled previous attempts.

- _gen_ed25519_keypair / _add_pubkey_to_authorized_keys helpers
- /tunnel-cmd: generate keypair on first call, store priv+pub on router record,
  add pub to ~/.ssh/authorized_keys, return one-liner
- /tunnel-script: returns full install script with private key embedded
  (text/plain), token-authenticated, single-use
- removed /tunnel-register-key endpoint (router no longer generates the key)
- copy button: select on-page text + execCommand fallback for non-HTTPS;
  if both fail, leave selected so user can Cmd+C manually

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 22:12:15 +03:00
Андрей Бобырев
b140cdac43 fix(tunnel): SSH key auth instead of sshpass; init.d boot persistence; copy fallback
aarch64-k3.10 Entware does not have sshpass or cronie packages. Switch to ed25519
SSH key auth and persist via /opt/etc/init.d/S99kdns_tunnel instead of cron.

- /api/routers/{rid}/tunnel-cmd: drop VPS_SSH_PASS dependency, generate one-time
  registration token, build install script that:
    1. opkg install autossh + openssh-keygen
    2. ssh-keygen ed25519 if not exists
    3. curl POST pubkey to new register-key endpoint with token
    4. autossh -i <key>  (no sshpass)
    5. /opt/etc/init.d/S99kdns_tunnel for boot autostart
- /api/routers/{rid}/tunnel-register-key: new endpoint, token-auth, appends pubkey
  to ~/.ssh/authorized_keys with kdns-tunnel-{rid} comment for de-dup
- copy button: fallback to document.execCommand('copy') for non-HTTPS contexts
  (navigator.clipboard requires secure context — UI runs on plain http)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 22:03:40 +03:00
Андрей Бобырев
cc31234e91 fix(tunnel): install cronie, start crond, killall watchdog; add tunnel-status endpoint
- opkg install now includes cronie so crond is actually present
- /opt/etc/init.d/S10crond start runs after install so cron watchdog fires
- cron watchdog switches from pgrep (not always in PATH) to killall -0 autossh
- killall autossh instead of pkill before re-launching (works in BusyBox)
- GET /api/routers/{rid}/tunnel-status: checks if tunnel port is listening on VPS localhost
- "⟳ Проверить связь" button in tunnel modal calls the new endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 21:54:34 +03:00
Андрей Бобырев
d48b7b2023 feat: reverse SSH tunnel for routers without public IP
UI: «⇄ Тоннель» button next to «Тест» — opens modal with autossh
install command for the router and an auto-applied localhost RCI URL.
Backend: GET /api/routers/{id}/tunnel-cmd allocates a free port
(starts at TUNNEL_PORT_START) and returns the shell command;
DELETE /api/routers/{id}/tunnel clears the assignment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 20:57:05 +03:00
Андрей Бобырев
adcf95ff4a fix(ui): author links only in bottom bar (match strip style)
Made-with: Cursor
2026-04-25 13:05:32 +03:00
Андрей Бобырев
6f7345de4d fix(ui): router row onclick quotes broke delete/test/edit/toggle
Use single-quoted onclick/onchange so JSON.stringify(id) does not break HTML.
Encode router id in API paths; handle test errors and delete failures.

Made-with: Cursor
2026-04-25 12:47:45 +03:00
Андрей Бобырев
4f42da9a0e Per-router RCI creds + .env fallback; parse user:pass@ URL; fix apply/checkbox (kdns-sel), save groups on toggle; update.sh
Made-with: Cursor
2026-04-25 01:42:16 +03:00
Андрей Бобырев
ef946e37f2 feat: scan interfaces via RCI; show Keenetic login + password status (no secret in UI)
Made-with: Cursor
2026-04-25 00:45:55 +03:00
Андрей Бобырев
3e97743e07 Initial: FastAPI DNS routes manager for legacy Keenetic (RCI, port 8001)
Made-with: Cursor
2026-04-24 22:45:28 +03:00