Monitoraggio remoto e gestione di dispositivi basati su Lunix/OpenWrt/Lede attraverso la porta 80...

Ciao a tutti, questo è il mio primo post su Habr. Vorrei scrivere su come gestire in modo non convenzionale le apparecchiature di rete in una rete esterna. Cosa significa non convenzionale: nella maggior parte dei casi, per gestire le apparecchiature in una rete esterna è necessario:

  • Un indirizzo IP pubblico. Oppure, se l'apparecchiatura si trova dietro un NAT, un IP pubblico e una porta "inoltrata".
  • Un tunnel (PPTP/OpenVPN/L2TP+IPSec, ecc.) verso un nodo centrale, attraverso il quale sarebbe accessibile.

Quindi, la "mia bicicletta" ti servirà quando i metodi standard non sono adatti, ad esempio:

  1. L'apparecchiatura si trova dietro un NAT e oltre al normale http (porta 80) — tutto è chiuso. Situazione piuttosto comune per grandi reti aziendali federali. Possono aprire le porte — ma non subito, non rapidamente e non per te.
  2. Un canale di comunicazione instabile e/o "ristretto". Bassa velocità, perdite costanti. Dolore e delusione nel tentativo di organizzare un tunnel.
  3. Un canale di comunicazione costoso, dove ogni megabyte conta. Ad esempio, una connessione satellitare. Inoltre, grandi ritardi e banda "ristretta".
  4. Una situazione in cui è necessario "giocare" con un gran numero di piccoli router, sui quali da un lato è installato OpenWrt/Lede per ampliare le funzionalità, e dall'altro le risorse (memoria) del router non sono sufficienti per tutti.

Nota numero uno E cosa impedisce di collegare una "chiavetta USB" alla porta USB del router per espandere la memoria?

Spesso, i requisiti di costo complessivo della soluzione sono determinanti, ma a volte anche il fattore di forma gioca un ruolo chiave. Ad esempio, presso un sito è presente un TP-Link ML3020, il cui unico porto USB è utilizzato per un modem 2G/3G, il tutto racchiuso in un piccolo involucro di plastica e collocato in alto (su un palo), lontano (in un campo, a 30 km dalla stazione base più vicina dell'operatore mobile). Sì, si può collegare un hub USB e aumentare il numero di porte, ma l'esperienza dimostra che è ingombrante e poco affidabile.

Dunque, ho cercato di descriverti la mia situazione tipica: "da qualche parte lontano, c'è un router molto importante, solitario e piccolo sotto il controllo di Linux. È fondamentale sapere almeno una volta al giorno che è "vivo" e inviare comandi ad esso, come ad esempio "piccolo sole, riavviati!"

Passiamo all'implementazione:

1) Sul lato del router, mediante cron ogni 5/10/1440 minuti, o quando necessario, è necessario inviare una richiesta http al server utilizzando wget, salvare il risultato della richiesta in un file, rendere eseguibile il file e quindi eseguirlo.

La mia riga in cron appare più o meno così:

File /etc/crontabs/root:

  */5 * * * * wget "http://xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai/a.php?u=user&p=password" -O /tmp/wa.sh && chmod 777 /tmp/wa.sh && /tmp/wa.sh

, dove:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai — è il dominio del mio server. Nota bene: sì, puoi specificare anche l'indirizzo ip specifico del server, lo facevamo prima, finché il nostro stato, nel suo giusto impulso di lotta non si sa contro cosa — non ha chiuso l'accesso a gran parte dei "cloud" di DigitalOcean e Amazon. In caso di utilizzo di un dominio simbolico, in una simile situazione, sarai in grado di sollevare in modo tranquillo un cloud di riserva, reindirizzarlo al dominio e ripristinare il monitoraggio dei dispositivi.

a.php — è il nome dello script sul server. Sì, so che è sbagliato usare nomi di variabili e file con una sola lettera... propongo di considerare che in questo modo risparmiamo alcuni byte quando inviamo la richiesta 🙂
u — nome utente, login dell'apparecchiatura
p — password
„-O /tmp/wa.sh“ — file on the remote router where the server's response will be saved, for example the reboot command.

Nota numero due: Aaaa, perché usiamo wget invece di curl, dato che con curl si possono inviare richieste https e non solo GET, ma anche POST? Aaaa, perché come in una vecchia barzelletta „Non si infila nella damigiana!“. Curl include librerie di crittografia grandi circa 2 MB e a causa di ciò sarà difficile riuscire a creare un'immagine per un piccolo TP-LINK ML3020, ad esempio. Ma con wget — va bene.

2) Sul lato server (per me è Ubuntu) useremo Zabbix. Perché: voglio che sia bello (con grafici) e comodo (per inviare comandi tramite menu contestuale). Zabbix ha una cosa deliziosa chiamata zabbix-agent. Tramite l'agente invocheremo uno script php su server, che restituirà informazioni su se il nostro router si è registrato nel periodo richiesto. Per memorizzare informazioni sul tempo di registrazione, comandi per i dispositivi, utilizzo MySQL, una tabella separata utenti con circa questi campi:

		CREA LA TABELLA `users` (
		  `id` varchar(25) NON NULL,
		  `passwd` varchar(25) NON NULL,
		  `description` varchar(150) NON NULL,
		  `category` varchar(30) NON NULL,
		  `status` varchar(10) NON NULL,
		  `last_time` varchar(20) NON NULL, // orario dell'ultima connessione
		  `last_ip` varchar(20) NON NULL, // IP dell'ultima connessione 
		  `last_port` int(11) NON NULL, // porta dell'ultima connessione
		  `task` text NON NULL, // compito che riceve il router
		  `reg_task` varchar(150) NON NULL, // "compito" regolare, se vogliamo che il compito venga eseguito sempre al momento della registrazione
		  `last_task` text NON NULL, // log dei compiti
		  `response` text NON NULL, // qui viene scritto il responso del dispositivo
		  `seq` int(11) NON NULL
		) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Tutti i sorgenti possono essere prelevati dal repository Git, all'indirizzo: https://github.com/BazDen/iotnet.online.git
Ora gli script PHP, collocati sul lato server (per comodità possono essere messi nella cartella /usr/share/zabbix/):

File a.php:

set_charset("utf8");
	// qui cerchiamo il nostro router nella tabella del database
	$sql_users=$conn->prepare("SELECT task, reg_task, response, last_time FROM users WHERE id=? AND passwd=? AND status='active';");
	$sql_users->bind_param('ss', $user, $password);
	$sql_users->bind_result($task, $reg_task, $response, $last_time);
	$sql_users->execute();
	$sql_users->store_result();
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		// qui inviamo i compiti al router
		echo $task;
		echo "n";
		echo $reg_task;
		// qui scriviamo il tempo di risposta e la risposta del router
		$response_history="[".date("Y-m-d H:i")."] ".$message;
		// il compito è stato inviato, ora dobbiamo eliminarlo e, dopo l'eliminazione, segnare nei log che il compito è stato completato
		$last_ip=$_SERVER["REMOTE_ADDR"];
		$last_port=$_SERVER["REMOTE_PORT"];
		$ts_last_conn_time=$last_time;
		$sql_users=$conn->prepare("UPDATE users SET task='', seq=1 WHERE (id=?);");
		$sql_users->bind_param('s', $user);
		$sql_users->execute();
		if (strlen($message)>1){
			$sql_users=$conn->prepare("UPDATE users SET response=?, seq=1 WHERE (id=?);");
			$sql_users->bind_param('ss', $response_history, $user);
			$sql_users->execute();
		}
		// ora dobbiamo salvare il tempo di registrazione dell'utente, il suo IP e il messaggio da lui inviato. Per ora solo il messaggio
		$ts_now=time();
		$sql_users=$conn->prepare("UPDATE users SET last_time=?, last_ip=?, last_port=? WHERE (id=?);");
		$sql_users->bind_param('ssss', $ts_now, $last_ip, $last_port, $user);
		$sql_users->execute();
	}
	// se non abbiamo trovato il router nel nostro database, o il suo stato è "non attivo", verrà inviata al router il comando reboot....
	// Perché così severo? Perché i router a volte scompaiono, e questo è un modo per "punire" i "nuovi proprietari". 
	else
	{
	echo "reboot";
	}
	$sql_users->close();
?>

File agent.php (this is the script for the invoked Zabbix agent):

set_charset("utf8");
	$sql_users=$conn->prepare("SELECT seq FROM users WHERE id=? AND passwd=? AND status='active';");
	$sql_users->bind_param('ss', $user, $password);
	$sql_users->bind_result($seq);
	$sql_users->execute();
	$sql_users->store_result();
	// data exchange occurs through the seq field. When registering, the device sets this field to "1"
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		echo $seq;
	}
		
	// resetting $seq.
	$sql_users=$conn->prepare("UPDATE users SET seq=0 WHERE id=? AND passwd=? AND status='active';");
	$sql_users->bind_param('ss', $user, $password);
	$sql_users->execute();
	$sql_users->close();
?>		

And now the final step: setting up the agent and adding graphs.

If you haven't installed the Zabbix agent yet, then:

apt-get install zabbix-agent

Edit the file /etc/zabbix/zabbix_agentd.conf.

Add the line:

UserParameter=test,php /usr/share/zabbix/agent.php user password

, dove:
test — the name of our agent
„php /usr/share/zabbix/agent.php utente password“ — script chiamato con le credenziali del dispositivo.

Aggiunta di grafici: apriamo l'interfaccia web di zabbix e nel menu selezioniamo:
Configurazione -> Nodi di rete -> Crea nodo di rete. Qui è sufficiente indicare il nome del nodo di rete, il suo gruppo e l'interfaccia dell'agente di default:

Monitoraggio remoto e gestione di dispositivi basati su Lunix/OpenWrt/Lede attraverso la porta 80...

Adesso dobbiamo aggiungere un elemento dati per questo nodo di rete. Fate attenzione a due campi: „chiave“ — questo è il parametro che abbiamo specificato nel file /etc/zabbix/zabbix_agentd.conf (in questo caso è test) e „intervallo di aggiornamento“ — metto 5 minuti, poiché anche l'attrezzatura si registrerà sul server ogni cinque minuti.

Monitoraggio remoto e gestione di dispositivi basati su Lunix/OpenWrt/Lede attraverso la porta 80...

E aggiungiamo il grafico. Raccomando di scegliere come stile di disegno „Riempimento“.

Monitoraggio remoto e gestione di dispositivi basati su Lunix/OpenWrt/Lede attraverso la porta 80...

Il risultato è qualcosa di molto conciso, ad esempio così:

Monitoraggio remoto e gestione di dispositivi basati su Lunix/OpenWrt/Lede attraverso la porta 80...

Alla giusta domanda: „e ne è valsa la pena?“, rispondo: certo, guarda „le ragioni per creare una bicicletta“ all'inizio dell'articolo.

Se il mio primo esperimento da grafomane susciterà l'interesse dei lettori, nei prossimi articoli voglio descrivere come inviare comandi a dispositivi remoti. Sono riuscito a realizzare l'intero schema anche per i dispositivi basati su RouterOS (Mikrotik).

Fonte: habr.com

Acquista un hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista un hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster