|
|
@@ -1,4 +1,11 @@
|
|
|
-# Reverse SSH Tunnel для удалённого доступа
|
|
|
+# Reverse SSH Tunnels для удалённого доступа
|
|
|
+
|
|
|
+Система поддерживает **два независимых reverse туннеля** для доступа к устройствам за NAT:
|
|
|
+
|
|
|
+1. **SSH Tunnel (порты 50000-59999)** - доступ к терминалу устройства (localhost:22)
|
|
|
+2. **Dashboard Tunnel (порты 60000-65535)** - доступ к веб-дашборду (localhost:80)
|
|
|
+
|
|
|
+Оба туннеля управляются серверной конфигурацией и используют один ED25519 SSH ключ.
|
|
|
|
|
|
## Архитектура
|
|
|
|
|
|
@@ -8,34 +15,32 @@
|
|
|
│ │
|
|
|
│ sshd (port 22) ───────────> main SSH (admin access) │
|
|
|
│ │
|
|
|
-│ sshd_tunnel (port 2222) ──> tunnel-only SSH │
|
|
|
-│ │ │
|
|
|
-│ └──> /home/tunnel/.ssh/authorized_keys │
|
|
|
-│ (device pubkeys with restrictions) │
|
|
|
+│ Tunnel Access: │
|
|
|
+│ ┌──────────────────────────────────────────────────────────┐ │
|
|
|
+│ │ SSH Tunnel Ports (50000-59999) │ │
|
|
|
+│ │ ssh -p {allocated_port} root@server │ │
|
|
|
+│ │ → устройство localhost:22 (терминал) │ │
|
|
|
+│ │ │ │
|
|
|
+│ │ Dashboard Tunnel Ports (60000-65535) │ │
|
|
|
+│ │ http://server:{allocated_port}/ │ │
|
|
|
+│ │ → устройство localhost:80 (веб-интерфейс) │ │
|
|
|
+│ └──────────────────────────────────────────────────────────┘ │
|
|
|
│ │
|
|
|
-│ Admin Dashboard: │
|
|
|
-│ ┌────────────────────────────────────┐ │
|
|
|
-│ │ Device: 38:54:39:4b:1b:ac │ │
|
|
|
-│ │ [Open SSH] ──> Generate UUID │ │
|
|
|
-│ └────────────────────────────────────┘ │
|
|
|
-│ │ │
|
|
|
-│ └──> /admin/ssh/{uuid} │
|
|
|
-│ │ │
|
|
|
-│ └──> ttyd on localhost:random_port │
|
|
|
-│ ssh -p {allocated_port} root@localhost │
|
|
|
+│ /home/tunnel/.ssh/authorized_keys │
|
|
|
+│ (device ED25519 pubkeys) │
|
|
|
│ │
|
|
|
-│ Tunnel Status API: │
|
|
|
+│ Port Allocation: │
|
|
|
│ ┌────────────────────────────────────┐ │
|
|
|
-│ │ POST /api/v1/tunnel-port │ │
|
|
|
-│ │ { device_id, port: 12345 } │ │
|
|
|
+│ │ Device: 38:54:39:4b:1b:ac │ │
|
|
|
+│ │ - SSH Tunnel Port: 50000 │ │
|
|
|
+│ │ - Dashboard Tunnel Port: 60000 │ │
|
|
|
+│ │ Status: Connected │ │
|
|
|
│ └────────────────────────────────────┘ │
|
|
|
│ │
|
|
|
-│ Audit Log: │
|
|
|
-│ - device_id │
|
|
|
-│ - admin_user │
|
|
|
-│ - session_uuid │
|
|
|
-│ - timestamp │
|
|
|
-│ - commands (optional) │
|
|
|
+│ SSH Config (/etc/ssh/sshd_config): │
|
|
|
+│ - AllowTcpForwarding yes │
|
|
|
+│ - GatewayPorts yes │
|
|
|
+│ - PermitTunnel yes │
|
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
|
@@ -52,19 +57,31 @@
|
|
|
│ (permissions: 0600, owner: root) │
|
|
|
│ │
|
|
|
│ SSH Tunnel (when enabled via server config): │
|
|
|
-│ ssh -N -R 0:localhost:22 \ │
|
|
|
-│ -p 2222 \ │
|
|
|
+│ # Туннель 1: SSH доступ (терминал) │
|
|
|
+│ ssh -N -R {ssh_remote_port}:localhost:22 \ │
|
|
|
+│ -p 22 \ │
|
|
|
│ -o ServerAliveInterval=30 \ │
|
|
|
│ -o ServerAliveCountMax=3 \ │
|
|
|
│ -o ExitOnForwardFailure=yes \ │
|
|
|
-│ -i /opt/mybeacon/etc/tunnel_key \ │
|
|
|
+│ -i /etc/beacon/ssh_tunnel_ed25519 \ │
|
|
|
│ tunnel@server.com │
|
|
|
│ │
|
|
|
-│ Parse allocated port from stderr → │
|
|
|
-│ POST /api/v1/tunnel-port │
|
|
|
-│ { "device_id": "...", "port": 12345 } │
|
|
|
+│ Dashboard Tunnel (when enabled via server config): │
|
|
|
+│ # Туннель 2: Dashboard доступ (веб-интерфейс) │
|
|
|
+│ ssh -N -R {dashboard_remote_port}:localhost:80 \ │
|
|
|
+│ -p 22 \ │
|
|
|
+│ -o ServerAliveInterval=30 \ │
|
|
|
+│ -o ServerAliveCountMax=3 \ │
|
|
|
+│ -o ExitOnForwardFailure=yes \ │
|
|
|
+│ -i /etc/beacon/ssh_tunnel_ed25519 \ │
|
|
|
+│ tunnel@server.com │
|
|
|
+│ │
|
|
|
+│ Порты выделяются сервером (фиксированные): │
|
|
|
+│ - ssh_remote_port: 50000-59999 │
|
|
|
+│ - dashboard_remote_port: 60000-65535 │
|
|
|
│ │
|
|
|
│ Auto-reconnect on disconnect (ReconnectDelay: 5s) │
|
|
|
+│ Max session lifetime: 24 hours │
|
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
@@ -483,7 +500,7 @@ if tunnelChanged {
|
|
|
|
|
|
```bash
|
|
|
# На сервере
|
|
|
-sudo useradd -m -d /home/tunnel -s /bin/false tunnel
|
|
|
+sudo useradd -m -d /home/tunnel -s /bin/sh tunnel
|
|
|
sudo mkdir -p /home/tunnel/.ssh
|
|
|
sudo chmod 700 /home/tunnel/.ssh
|
|
|
sudo touch /home/tunnel/.ssh/authorized_keys
|
|
|
@@ -491,102 +508,46 @@ sudo chmod 600 /home/tunnel/.ssh/authorized_keys
|
|
|
sudo chown -R tunnel:tunnel /home/tunnel/.ssh
|
|
|
```
|
|
|
|
|
|
-### 2. Конфиг отдельного sshd
|
|
|
-
|
|
|
-**Файл:** `/etc/ssh/sshd_tunnel_config`
|
|
|
-
|
|
|
-```sshd_config
|
|
|
-# Tunnel-only SSH daemon for MyBeacon devices
|
|
|
-Port 2222
|
|
|
-Protocol 2
|
|
|
-
|
|
|
-# Listening
|
|
|
-ListenAddress 0.0.0.0
|
|
|
-
|
|
|
-# Host keys (use existing)
|
|
|
-HostKey /etc/ssh/ssh_host_ed25519_key
|
|
|
-HostKey /etc/ssh/ssh_host_rsa_key
|
|
|
-
|
|
|
-# Logging
|
|
|
-SyslogFacility AUTH
|
|
|
-LogLevel INFO
|
|
|
-
|
|
|
-# Authentication
|
|
|
-PubkeyAuthentication yes
|
|
|
-AuthorizedKeysFile /home/tunnel/.ssh/authorized_keys
|
|
|
-PasswordAuthentication no
|
|
|
-ChallengeResponseAuthentication no
|
|
|
-KerberosAuthentication no
|
|
|
-GSSAPIAuthentication no
|
|
|
-PermitRootLogin no
|
|
|
-
|
|
|
-# Restrictions for tunnel user
|
|
|
-Match User tunnel
|
|
|
- # ONLY port forwarding, nothing else
|
|
|
- AllowTcpForwarding remote
|
|
|
- GatewayPorts no
|
|
|
- PermitOpen localhost:*
|
|
|
-
|
|
|
- # Disable everything else
|
|
|
- X11Forwarding no
|
|
|
- AllowAgentForwarding no
|
|
|
- PermitTTY no
|
|
|
- PermitUserRC no
|
|
|
-
|
|
|
- # Force command (ignored with -N, but extra safety)
|
|
|
- ForceCommand /bin/echo "Port forwarding only"
|
|
|
-
|
|
|
- # Limits
|
|
|
- MaxSessions 10
|
|
|
- ClientAliveInterval 30
|
|
|
- ClientAliveCountMax 3
|
|
|
-
|
|
|
- # Security
|
|
|
- PermitEmptyPasswords no
|
|
|
- MaxAuthTries 3
|
|
|
-```
|
|
|
+**ВАЖНО:** Используйте `/bin/sh` вместо `/bin/false` или `/usr/sbin/nologin` - иначе SSH сессия будет немедленно закрываться!
|
|
|
|
|
|
-### 3. Systemd unit для tunnel sshd
|
|
|
+### 2. Настройка SSH сервера
|
|
|
|
|
|
-**Файл:** `/etc/systemd/system/sshd-tunnel.service`
|
|
|
+Добавьте следующие настройки в `/etc/ssh/sshd_config`:
|
|
|
|
|
|
-```ini
|
|
|
-[Unit]
|
|
|
-Description=OpenSSH Tunnel Server for MyBeacon Devices
|
|
|
-After=network.target auditd.service
|
|
|
-ConditionPathExists=!/etc/ssh/sshd_tunnel_not_to_be_run
|
|
|
+```bash
|
|
|
+# Разрешить TCP forwarding для туннелей
|
|
|
+AllowTcpForwarding yes
|
|
|
|
|
|
-[Service]
|
|
|
-Type=notify
|
|
|
-EnvironmentFile=-/etc/default/ssh
|
|
|
-ExecStartPre=/usr/sbin/sshd -t -f /etc/ssh/sshd_tunnel_config
|
|
|
-ExecStart=/usr/sbin/sshd -D -f /etc/ssh/sshd_tunnel_config
|
|
|
-ExecReload=/bin/kill -HUP $MAINPID
|
|
|
-KillMode=process
|
|
|
-Restart=on-failure
|
|
|
-RestartSec=42s
|
|
|
+# Разрешить GatewayPorts для доступа извне (не только localhost)
|
|
|
+GatewayPorts yes
|
|
|
|
|
|
-[Install]
|
|
|
-WantedBy=multi-user.target
|
|
|
+# Разрешить туннели
|
|
|
+PermitTunnel yes
|
|
|
```
|
|
|
|
|
|
-Запуск:
|
|
|
+Перезапустите SSH сервер:
|
|
|
|
|
|
```bash
|
|
|
-sudo systemctl daemon-reload
|
|
|
-sudo systemctl enable sshd-tunnel
|
|
|
-sudo systemctl start sshd-tunnel
|
|
|
-sudo systemctl status sshd-tunnel
|
|
|
+sudo systemctl restart sshd
|
|
|
```
|
|
|
|
|
|
-### 4. Firewall правила
|
|
|
+**Объяснение:**
|
|
|
+- `AllowTcpForwarding yes` - разрешает reverse SSH tunnels
|
|
|
+- `GatewayPorts yes` - разрешает bind на 0.0.0.0 (доступ извне), а не только на 127.0.0.1
|
|
|
+- `PermitTunnel yes` - разрешает туннелирование
|
|
|
+
|
|
|
+### 3. Firewall правила
|
|
|
|
|
|
```bash
|
|
|
-# Разрешить порт 2222 для tunnel SSH
|
|
|
-sudo ufw allow 2222/tcp comment "MyBeacon SSH Tunnel"
|
|
|
+# Разрешить порты 50000-59999 для SSH Tunnel
|
|
|
+sudo ufw allow 50000:59999/tcp comment "MyBeacon SSH Tunnel"
|
|
|
+
|
|
|
+# Разрешить порты 60000-65535 для Dashboard Tunnel
|
|
|
+sudo ufw allow 60000:65535/tcp comment "MyBeacon Dashboard Tunnel"
|
|
|
|
|
|
# Или для iptables
|
|
|
-sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
|
|
|
+sudo iptables -A INPUT -p tcp --dport 50000:59999 -j ACCEPT
|
|
|
+sudo iptables -A INPUT -p tcp --dport 60000:65535 -j ACCEPT
|
|
|
```
|
|
|
|
|
|
## Серверное API
|
|
|
@@ -935,6 +896,115 @@ async def ssh_session_stats():
|
|
|
- [ ] Audit log записи
|
|
|
- [ ] Переподключение туннеля при обрыве
|
|
|
|
|
|
+## Тестирование и использование
|
|
|
+
|
|
|
+### Проверка статуса туннелей на сервере
|
|
|
+
|
|
|
+```bash
|
|
|
+# Проверить что порты слушают
|
|
|
+ss -tlnp | grep -E ':(50000|60000)'
|
|
|
+
|
|
|
+# Пример вывода:
|
|
|
+# LISTEN 0 128 0.0.0.0:50000 0.0.0.0:*
|
|
|
+# LISTEN 0 128 0.0.0.0:60000 0.0.0.0:*
|
|
|
+```
|
|
|
+
|
|
|
+### SSH Tunnel - доступ к терминалу
|
|
|
+
|
|
|
+```bash
|
|
|
+# Подключение к устройству через SSH tunnel
|
|
|
+ssh -p 50000 root@server-ip
|
|
|
+
|
|
|
+# Или через ProxyJump (если доступ через промежуточный сервер)
|
|
|
+ssh -J user@server -p 50000 root@localhost
|
|
|
+```
|
|
|
+
|
|
|
+### Dashboard Tunnel - доступ к веб-интерфейсу
|
|
|
+
|
|
|
+```bash
|
|
|
+# Через браузер
|
|
|
+http://server-ip:60000/
|
|
|
+
|
|
|
+# Или через curl
|
|
|
+curl http://server-ip:60000/api/status
|
|
|
+```
|
|
|
+
|
|
|
+**Пример ответа:**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "device_id": "38:54:39:4b:1b:ac",
|
|
|
+ "registered": true,
|
|
|
+ "mode": "cloud",
|
|
|
+ "uptime_sec": 400,
|
|
|
+ "network": {
|
|
|
+ "eth0_ip": "192.168.5.244/24",
|
|
|
+ "gateway": "192.168.5.1"
|
|
|
+ },
|
|
|
+ "scanners": {
|
|
|
+ "ble_running": true,
|
|
|
+ "wifi_running": true
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### Логи туннелей на устройстве
|
|
|
+
|
|
|
+```bash
|
|
|
+# На устройстве просмотреть логи
|
|
|
+ssh root@device-ip "tail -f /var/log/mybeacon.log | grep tunnel"
|
|
|
+
|
|
|
+# Пример вывода:
|
|
|
+# [ssh-tunnel] Started: 192.168.5.2:22 -> localhost:22 (remote_port=50000)
|
|
|
+# [dashboard-tunnel] Started: 192.168.5.2:22 -> localhost:80 (remote_port=60000)
|
|
|
+```
|
|
|
+
|
|
|
+### Управление туннелями через server API
|
|
|
+
|
|
|
+```python
|
|
|
+# Включить SSH туннель
|
|
|
+POST /api/v1/admin/update_device
|
|
|
+{
|
|
|
+ "device_id": "38:54:39:4b:1b:ac",
|
|
|
+ "password": "12345678",
|
|
|
+ "patch": {
|
|
|
+ "ssh_tunnel.enabled": true
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Включить Dashboard туннель
|
|
|
+POST /api/v1/admin/update_device
|
|
|
+{
|
|
|
+ "device_id": "38:54:39:4b:1b:ac",
|
|
|
+ "password": "12345678",
|
|
|
+ "patch": {
|
|
|
+ "dashboard_tunnel.enabled": true
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+После получения новой конфигурации (≤30 секунд) устройство:
|
|
|
+1. Запустит соответствующий туннель
|
|
|
+2. Подключится к серверу
|
|
|
+3. Сервер выделит фиксированный порт из диапазона
|
|
|
+4. Туннель будет доступен по этому порту
|
|
|
+
|
|
|
+### Отладка проблем
|
|
|
+
|
|
|
+```bash
|
|
|
+# На сервере: проверить активные SSH сессии от tunnel user
|
|
|
+sudo ps aux | grep 'sshd.*tunnel'
|
|
|
+
|
|
|
+# На сервере: логи SSH
|
|
|
+sudo journalctl -u sshd -f | grep tunnel
|
|
|
+
|
|
|
+# На устройстве: проверить процессы туннелей
|
|
|
+ps aux | grep 'ssh.*192.168'
|
|
|
+
|
|
|
+# На устройстве: убить зависший туннель
|
|
|
+killall ssh
|
|
|
+# Демон автоматически перезапустит туннели через 5 секунд
|
|
|
+```
|
|
|
+
|
|
|
## Ссылки
|
|
|
|
|
|
- **ttyd**: https://github.com/tsl0922/ttyd
|