Ciao a tutti, questa è la mia prima esperienza su Habr. Vorrei scrivere di come gestire in modo non convenzionale l'hardware di rete in una rete esterna. Cosa significa in modo non convenzionale: nella maggior parte dei casi, per gestire l'hardware in una rete esterna hai bisogno di:
- Un indirizzo IP pubblico. Oppure, se l'hardware si trova dietro a 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 sarà utile quando i metodi standard non ti sono adatti, ad esempio:
- L'hardware si trova dietro un NAT e, al di fuori dell'http normale (porta 80), tutto è chiuso. Una situazione del tutto normale per grandi reti aziendali federali. Possono aprire le porte, ma non subito, non rapidamente e non per te.
- Un canale di comunicazione instabile e/o "ristretto". Velocità bassa, perdite costanti. Dolore e delusione nel tentativo di organizzare un tunnel.
- Un canale di comunicazione costoso, dove ogni megabyte è prezioso. Ad esempio, la comunicazione satellitare. Inoltre, grandi ritardi e una banda "ristretta".
- Situazione in cui devi "giocolare" con un gran numero di piccoli router, sui quali da un lato è installato OpenWrt/Lede per ampliarne le funzionalità, mentre dall'altro le risorse (memoria) del router non sono sufficienti per tutto.
Nota numero uno E cosa impedisce di inserire una "flash" nella porta USB del router e aumentare la memoria del router?
Spesso i requisiti riguardano il costo della soluzione nel suo complesso, ma talvolta il fattore di forma gioca un ruolo chiave. Ad esempio, presso l'oggetto è presente un TP-Link ML3020, la sua unica porta USB è utilizzata per un modem 2G/3G, il tutto è racchiuso in un piccolo involucro di plastica e collocato in alto (su un'antenna), lontano (in un campo, a 30 km dalla stazione base più vicina dell'operatore mobile). Sì, puoi collegare un hub USB e aumentare il numero di porte, ma l'esperienza dimostra che è ingombrante e inaffidabile.
Quindi, ho cercato di descriverti la mia situazione tipica: "là fuori, lontano, c'è un router molto importante, solitario e piccolo sotto il controllo di Linux. È importante sapere almeno una volta al giorno che è "vivo" e, se necessario, inviargli comandi, ad esempio "sole, riavviati!"
Passiamo all'implementazione:
1) Sul lato del router, tramite 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 il file eseguibile ed 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. Vorrei sottolineare: sì, è possibile specificare anche un indirizzo ip specifico del server, così abbiamo fatto in passato, fino a quando il nostro stato, in un fervente sforzo per combattere non so cosa — non ha bloccato l'accesso a gran parte dei 'cloud' DigitalOcean e Amazon. Nel caso di utilizzo di un dominio simbolico, in caso di problemi simili, potrete tranquillamente creare un cloud di riserva, reindirizzare il dominio su di esso e ripristinare il monitoraggio dei dispositivi.
a.php — è il nome dello script sul server. Sì, so che è sbagliato chiamare variabili e nomi di file con una sola lettera… propongo di considerare che in tal modo risparmiamo qualche byte nell'invio della richiesta 🙂
u — nome utente, login del dispositivo
p — password
‘-O /tmp/wa.sh’ — è il file sul router remoto dove verrà salvata la risposta del server, ad esempio il comando reboot.
Nota numero due: Aaaaah, perché usiamo wget e non curl, visto che con curl si possono inviare richieste https anche in POST e non solo in GET? Aaaaah perché, come nel'antico scherzo ‘Non entra nel crivello!’. Curl include librerie di crittografia di circa 2MB e per questo sarà difficile raccogliere un'immagine per un piccolo TP-LINK ML3020, per esempio. Con wget, invece, è tutto a posto.
2) Sul lato del server (io uso Ubuntu) utilizzeremo Zabbix. Perché: voglio che sia bello (con grafici) e conveniente (inviare comandi tramite menu contestuale). Zabbix ha una cosa molto interessante, chiamata zabbix-agent. Tramite l'agente chiameremo uno script php su server, che restituirà informazioni su se il nostro router è stato registrato nel periodo di tempo richiesto. Per memorizzare informazioni sul tempo di registrazione, sui comandi per i dispositivi, utilizzo MySQL, una tabella separata users con questi campi:
CREA 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, `last_ip` varchar(20) NON NULL, `last_port` int(11) NON NULL, `task` text NON NULL, `reg_task` varchar(150) NON NULL, `last_task` text NON NULL, `response` text NON NULL, `seq` int(11) NON NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; Tutti i sorgenti possono essere prelevati dal repository Git, all'indirizzo:
Ora gli script PHP, posizionati sul lato server (per comodità possono essere posizionati 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 al router i suoi compiti
echo $task;
echo "n";
echo $reg_task;
// qui scriviamo il tempo di risposta e la risposta stessa del router
$response_history="[".date("Y-m-d H:i")."] ".$message;
// compito 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 troviamo il router nel nostro database, o il suo stato è "non attivo", allora ... verrà inviata al router il comando di reboot....
// Perché così severamente? Perché i router a volte scompaiono, e questo è un modo per punire i "nuovi proprietari".
else
{
echo "reboot";
}
$sql_users->close();
?>File agent.php (questo è lo script delzabbix-agent che viene chiamato):
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();
// lo scambio di dati avviene tramite il campo seq. Quando si registra, il dispositivo imposta questo campo a "1"
if (($sql_users->num_rows)==1){
$sql_users->fetch();
echo $seq;
}
// azzeriamo $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();
?> E l'ultima fase: configurazione dell'agente e aggiunta dei grafici.
Se non hai ancora installato l'agente zabbix, allora:
apt-get install zabbix-agentModifichiamo il file /etc/zabbix/zabbix_agentd.conf.
Aggiungiamo la riga:
UserParameter=test,php /usr/share/zabbix/agent.php user password , dove:
test — il nome del nostro agente
„php /usr/share/zabbix/agent.php user password“ — lo script chiamato con le credenziali del dispositivo.
Aggiunta dei grafici: apriamo l'interfaccia web di zabbix, nel menu selezioniamo:
Impostazioni -> Nodii di rete -> Crea nodo di rete. Qui è sufficiente specificare il nome del nodo di rete, il suo gruppo, l'interfaccia dell'agente predefinita:

Ora dobbiamo aggiungere un elemento dati per questo nodo di rete. Fai attenzione ai due campi: „chiave“ — è proprio quel parametro che abbiamo specificato nel file /etc/zabbix/zabbix_agentd.conf (nel nostro caso è test), e „intervallo di aggiornamento“ — impostiamo 5 minuti, poiché anche il dispositivo è registrato sul server una volta ogni cinque minuti.

E poi aggiungiamo un grafico. Ti consiglio di scegliere come stile di visualizzazione „Riempimento“.

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

In risposta alla ragionevole domanda: „ne valeva la pena?”, rispondo: certo, guarda “le ragioni per cui è stato creato il sistema” all'inizio dell'articolo.
Se il mio primo esperimento da grafomane susciterà l'interesse dei lettori, nei prossimi articoli voglio descrivere come inviare comandi ai dispositivi remoti. Sono riuscito a realizzare l'intero schema anche per i dispositivi basati su RouterOS (Mikrotik).
Fonte: habr.com
