Skip to content
LEGIT AIDOCS
Open the console

Monitor Linux servers over SSH

Add a server with its address and an account; the platform watches logins, ports, administrators, critical files and its own canaries every 30 seconds, with nothing installed.

Servers are watched without an agent. Each tenant has its own Ed25519 key pair; the platform logs in with it and reads what an administrator could read with uname, last, w, ss and sha256sum. It is built for Linux: the signals are read with standard Linux commands, so other systems with an SSH server connect but report less.

  1. Open Servers. The platform’s key is at the top of the page, in the key vault: everyone sees its fingerprint, an administrator sees the key itself — Show key, then a current authenticator code — for 60 seconds. Copy the line it gives.

  2. Put that line into ~/.ssh/authorized_keys of the account the platform will use on the server. The line is restricted: no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty — the key can run the platform’s commands and nothing else, so a stolen copy cannot open a shell or a tunnel. You can also pin it to Legit AI’s address with from= (the vault offers the address your servers see); then a copy is useless anywhere else, but every server stops answering if that address changes.

    Alternatively, type that account’s password in the add form: the platform logs in once with it and installs the key itself. The password is used for that one login and never stored.

  3. Enter username@host or username@host:port, an optional label, and choose Add & Test.

Before accepting a server, the platform checks that something answers on that address and port, so a mistyped host is refused at once instead of failing in the background forever.

The account used to add the server is put on the server’s list of authorised users automatically.

Adding a server only passes a port where an SSH server greets; any other port gets the same answer as a closed one. On the cloud, an account can try 10 addresses that fail in 15 minutes, 60 addresses an hour, and 5 passwords on one server in 15 minutes. Going back to the same address costs nothing.

Under the add form, Add several servers takes a list, one user@host or user@host:port per line — the way an inventory or an Ansible hosts file already holds them — and adds and checks each in turn, with one line of outcome per server.

Beside it is a command that puts the platform’s key on all of them first. Run it on a machine that already reaches them over SSH, with their addresses in hosts.txt:

Terminal window
while read -r host; do
ssh -n "$host" "mkdir -p ~/.ssh && chmod 700 ~/.ssh && grep -qF '<the key>' ~/.ssh/authorized_keys 2>/dev/null || echo '<the restricted line>' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
done < hosts.txt

The console fills in the line after the key is shown (administrator, fresh code); a server that already holds the key is left as it is.

Under Network Map → Discovery, Scan this network checks the whole network from the connected server itself: which devices answer, which ports are open and what they announce. Nothing is installed and root is not needed: the server only needs python3.

Method What it gives What it needs
TCP connection, ARP Live devices, MAC, open ports Nothing
Banners, HTTP SSH version, web page title, Server header Nothing
NetBIOS, DNS, NTP, mDNS Device name, UDP services Nothing
UPnP/SSDP Maker, model, device type UPnP on the device
SNMP v2c/v3 Firmware, name, uptime, interfaces, connected devices, LLDP neighbours Read-only access you provide; net-snmp on the server for v3
nmap Service versions, OS nmap on the server. For OS: root, or setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip /usr/bin/nmap

Every fact is marked confirmed (the device said so) or inferred (MAC prefix, ports, TTL), with its method and evidence. What could not be read is shown as unknown, with what would answer it.

Limits. Private ranges only, up to 4096 addresses a scan, at a limited rate. Starting one takes an ADMIN, a fresh authenticator code and a statement that the network is yours, written to the audit log. A scan only reads: it guesses no passwords, exploits nothing and changes nothing. Stop ends it at once. The first scan is the baseline; after that a new device or a critically exposed service opens an alert.

A scan sees a router from outside. With a login, Router access reads the router’s own lists: connected devices with their leases, firmware, model, serial number, uptime, interfaces, routes and neighbouring devices. These facts are marked confirmed, and a device only the router knows joins the device list and the map. Readings repeat with every scan, and a device that appears later raises an alert.

Kind How it is read Tried on
MikroTik REST (RouterOS 7), binary API (RouterOS 6 and 7), or SSH RouterOS 7.16.2. The challenge login of versions before 6.43 follows the protocol, not tried on a device
OpenWrt ubus API or SSH OpenWrt 24.10.4
OPNsense API key OPNsense 25.7
UniFi Controller or UniFi OS login, or an API key Sign-in and sites on UniFi Network 9.0.114 with no devices adopted. Device and client rows, UniFi OS and the API key follow Ubiquiti’s formats, not tried on a device
FortiGate REST API token Follows Fortinet’s documentation, not tried on a device
Cisco IOS, Huawei VRP, Juniper, VyOS, EdgeOS, FortiOS SSH: a fixed list of show-type commands Follow each maker’s output format, not tried on a device. If a model answers differently, the affected table stays empty

A home or ISP router (ZTE, Huawei HG and the like) usually has no public API and SSH turned off. Turn on SNMP, or SSH if the provider allows it; otherwise the scan’s outside view is what there is.

Very old routers that only offer SHA-1 SSH algorithms are not connected to: the session would not protect the password. Update the firmware, or use SNMP.

Use a read-only account. On MikroTik: /user add name=legit group=read password=.... Legit AI warns when a login can change the router.

How it is protected.

  • It only reads. Commands and API calls are a fixed list, and nothing takes a command from a person. The running configuration is never read: it holds password hashes and keys.
  • The password stays off your server. The SSH or TLS session runs from Legit AI to the router; your server runs a small relay that only passes bytes, and needs python3.
  • The router’s key or certificate is pinned on first contact and judged before the password is sent. If it changes, the password is not sent, an alert is raised, and reading waits until an ADMIN confirms the change with a fresh code.
  • A login the router refuses is tried once. It is not tried again until you change it, so nothing here can lock an account or guess a password.
  • Unencrypted logins are refused unless you turn them on for that router; Legit AI then warns on each reading.
  • Only private addresses. Giving a login takes an ADMIN, a fresh authenticator code and your statement that the router is yours. It is sealed, never shown again, removed with the server, and every change and reading is in the audit log.

Every 30 seconds, over one connection, the platform reads:

Signal Raises
Recent logins (last, w) A critical alert for any login by an account not on the server’s authorised list, with forensic evidence gathered at once and the source address looked up
Members of the sudo (or wheel) group A critical alert when someone is added (T1098)
Listening ports A high alert when a new port opens (T1571)
SHA-256 of /etc/passwd, /etc/ssh/sshd_config, /etc/crontab, /etc/hosts and the account’s authorized_keys An alert when one of them changes
The auth log’s inode, modification time and line count An alert when the log has fewer lines than before, or an earlier modification time, without having been rotated (T1070.002)
Canary files you placed on the server An alert when one is read, changed or removed
Default route, neighbour table, open TCP connections, DNS servers Network Map: the router with its address, MAC and maker, the devices this server has been in contact with, and its connections checked against threat intel. This is what the server knows, not a scan of the LAN
OS, kernel, CPU, memory, disk, top processes, installed packages, OpenSSH version The server’s card and its change timeline

A server that stops answering, or runs short of memory or disk, is recorded on its health timeline. That is an operational condition, not an attack, so it does not go to the alert queue.

Edit server → Authorized Users (ADMIN) lists the accounts whose logins are expected, optionally from a given network range. Their logins stay silent; any other login is an alert.

Check How
Known vulnerabilities in the server’s OpenSSH, from NVD with EPSS exploit likelihood Scan on the server’s card. It needs outbound intelligence lookups to be allowed, so it does not run on an air-gapped deployment.
Persistence: cron jobs, running systemd services, SUID binaries, /etc/ld.so.preload POST /api/ssh/servers/{id}/scan-persistence

The first connection to a server pins its host key. Any later connection that is shown a different key is refused and written to the audit log, so a machine in the network path cannot pose as the server. When a server has really been rebuilt, an ADMIN clears its pin (DELETE /api/ssh/servers/{id}/host-key) and the next connection pins the new key.

Replace (administrator, a fresh code, and the last six characters of the current fingerprint typed) pushes the new key to every server that is online and logs in with it before switching. The new key takes over the old key’s line with its options — a from= pin stays. If any server cannot be reached with the new key, the rotation stops and the old key stays in use. The vault suggests a replacement after 90 days.