+проверка микротика
This commit is contained in:
parent
5f1bc35579
commit
a6f8722ad3
2 changed files with 66 additions and 1 deletions
|
|
@ -32,6 +32,7 @@ from .ssh_client import (
|
||||||
fetch_slave_config,
|
fetch_slave_config,
|
||||||
get_ip_neighbors_multi,
|
get_ip_neighbors_multi,
|
||||||
ssh_run_multi,
|
ssh_run_multi,
|
||||||
|
verify_is_mikrotik,
|
||||||
)
|
)
|
||||||
from .types import DeviceAction, DiscoveredDevice, DiscoveryResult, ProgressCallback
|
from .types import DeviceAction, DiscoveredDevice, DiscoveryResult, ProgressCallback
|
||||||
|
|
||||||
|
|
@ -811,7 +812,15 @@ async def _discover_mikrotik(
|
||||||
logger.info("[discovery] MikroTik: no IP found via SSH_CLIENT")
|
logger.info("[discovery] MikroTik: no IP found via SSH_CLIENT")
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.info("[discovery] MikroTik found at %s", mikrotik_ip)
|
logger.info("[discovery] MikroTik candidate: %s — verifying...", mikrotik_ip)
|
||||||
|
await _emit("disc_action", {"message": f"Проверка MikroTik {mikrotik_ip} (WinBox/SSH)..."})
|
||||||
|
is_mikrotik = await verify_is_mikrotik(mikrotik_ip, ssh_port, ssh_options)
|
||||||
|
if not is_mikrotik:
|
||||||
|
logger.info("[discovery] %s — NOT a MikroTik (WinBox and SSH banner check failed), skipping", mikrotik_ip)
|
||||||
|
await _emit("disc_action", {"message": f"{mikrotik_ip} — не MikroTik, пропускаем"})
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info("[discovery] MikroTik confirmed at %s", mikrotik_ip)
|
||||||
await _emit("disc_infra_found", {"type": "mikrotik", "ip": mikrotik_ip})
|
await _emit("disc_infra_found", {"type": "mikrotik", "ip": mikrotik_ip})
|
||||||
try:
|
try:
|
||||||
existing = (await db.execute(
|
existing = (await db.execute(
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,62 @@ async def open_ssh_tunnel(
|
||||||
raise last_exc
|
raise last_exc
|
||||||
|
|
||||||
|
|
||||||
|
# ── MikroTik verification ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
async def verify_is_mikrotik(
|
||||||
|
host: str,
|
||||||
|
ssh_port: int = 22,
|
||||||
|
ssh_options: list | None = None,
|
||||||
|
timeout: float = 3.0,
|
||||||
|
) -> bool:
|
||||||
|
"""Check whether host is actually a MikroTik RouterOS device.
|
||||||
|
|
||||||
|
Two independent probes are tried (first positive result wins):
|
||||||
|
1. TCP connect to port 8291 (WinBox) — exclusively used by MikroTik.
|
||||||
|
2. SSH banner check — RouterOS advertises "ROSSSH" as its SSH version.
|
||||||
|
|
||||||
|
Returns True if either probe confirms MikroTik, False otherwise.
|
||||||
|
"""
|
||||||
|
# Probe 1: WinBox port 8291 (MikroTik-exclusive)
|
||||||
|
try:
|
||||||
|
reader, writer = await asyncio.wait_for(
|
||||||
|
asyncio.open_connection(host, 8291), timeout=timeout
|
||||||
|
)
|
||||||
|
writer.close()
|
||||||
|
try:
|
||||||
|
await writer.wait_closed()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
logger.info("[discovery] %s — MikroTik confirmed via WinBox port 8291", host)
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Probe 2: SSH banner
|
||||||
|
if ssh_options:
|
||||||
|
for opt in ssh_options:
|
||||||
|
try:
|
||||||
|
kwargs = _build_connect_kwargs(host, ssh_port, opt)
|
||||||
|
kwargs["connect_timeout"] = int(timeout)
|
||||||
|
async with asyncssh.connect(**kwargs) as conn:
|
||||||
|
banner = (conn.get_extra_info("server_version") or "").lower()
|
||||||
|
if "rosssh" in banner or "mikrotik" in banner:
|
||||||
|
logger.info(
|
||||||
|
"[discovery] %s — MikroTik confirmed via SSH banner: %s", host, banner
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
logger.info(
|
||||||
|
"[discovery] %s — SSH connected but banner does not match MikroTik: %s",
|
||||||
|
host, banner,
|
||||||
|
)
|
||||||
|
return False # Connected successfully — definitely not MikroTik
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.info("[discovery] %s — could not verify MikroTik (no probe succeeded)", host)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
# ── Internal helpers ──────────────────────────────────────────────────────────
|
# ── Internal helpers ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def _parse_neigh_output(stdout: str) -> list[str]:
|
def _parse_neigh_output(stdout: str) -> list[str]:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue