Afstandsmonitoring en beheer van apparaten op basis van Lunix/OpenWrt/Lede via poort 80…

Hallo allemaal, dit is mijn eerste ervaring op Habr. Ik wil schrijven over hoe je op een onconventionele manier netwerkapparatuur in een extern netwerk kunt beheren. Wat betekent onconventioneel: in de meeste gevallen moet je het volgende hebben om apparatuur in een extern netwerk te beheren:

  • Een publiek IP-adres. Of, als de apparatuur achter iemands NAT staat, dan een publiek IP en een "doorgegeven" poort.
  • Een tunnel (PPTP/OpenVPN/L2TP+IPSec, enz.) naar het centrale knooppunt, waardoor het beschikbaar zou zijn.

Daarom heb je "mijn fiets" nodig wanneer de standaardmethoden niet voor je werken, bijvoorbeeld:

  1. De apparatuur bevindt zich achter NAT en behalve gewone http (poort 80) is alles gesloten. Een volledig normale situatie voor grote federale bedrijfsnetwerken. Poorten instellen kunnen ze, maar niet meteen, niet snel en niet voor jou.
  2. Een onbetrouwbare en/of "smalle" verbinding. Lage snelheid, constante verliezen. Pijn en frustratie bij het proberen om een tunnel op te zetten.
  3. Dure verbinding, waar letterlijk elke megabyte telt. Bijvoorbeeld satellietverbinding. Daarnaast grote vertragingen en een "smalle" bandbreedte.
  4. Een situatie waarin je moet "jongleren" met een groot aantal kleine routers, waarvan aan de ene kant OpenWrt/Lede is geïnstalleerd om de mogelijkheden uit te breiden, en aan de andere kant de middelen (geheugen) van de router niet voldoende zijn voor alles.

Opmerking één Wat verhindert je om een "flash" in de USB-poort van de router te plaatsen en het geheugen van de router te vergroten?

Vaak zijn de kosten van de oplossing als geheel een vereiste, maar soms speelt de vormfactor ook een sleutelrol. Bijvoorbeeld, op de locatie staat een TP-Link ML3020, zijn enige USB-poort wordt gebruikt voor een 2G/3G-modem, dit alles is verpakt in een klein plastic huisje en geplaatst op een hoge plek (op een toren), ver weg (in het veld, op 30 km van de dichtstbijzijnde mobiele basisstation). Ja, je kunt een USB-hub aansluiten en het aantal poorten uitbreiden, maar de ervaring leert dat dit omvangrijk en onbetrouwbaar is.

Dus, ik heb geprobeerd je mijn typische situatie te beschrijven: "ergens ver weg staat een zeer belangrijke, eenzame en kleine router met Linux. Het is belangrijk om minstens één keer per dag te weten dat hij "levend" is en indien nodig stuur ik hem commando's, bijvoorbeeld "zonnetje, herstart!"

Laten we overgaan tot de implementatie:

1) Aan de routerzijde elke 5/10/1440 minuten via cron, of wanneer nodig, een http-verzoek naar de server verzenden met wget, het resultaat van het verzoek opslaan in een bestand, dat bestand uitvoerbaar maken en uitvoeren.

Mijn regel in cron ziet er ongeveer zo uit:

Bestand /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

, waar:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai — het domein van mijn server. Ik wil er meteen op wijzen: ja, je kunt ook een specifiek ip-adres van de server opgeven, dat deden we vroeger, totdat onze overheid, in een rechtvaardige poging tot bestrijding van onduidelijke zaken, de toegang tot een groot deel van de "clouds" van DigitalOcean en Amazon heeft geblokkeerd. Bij gebruik van een symbolisch domein, in het geval van een dergelijk voorval, kun je eenvoudig een reserve-cloud opzetten, het domein daarin omleiden en het apparaatmonitoring herstellen.

a.php — de naam van het script aan de serverzijde. Ja, ik weet dat het niet goed is om variabelen en bestandsnamen met één letter te noemen... laten we aannemen dat we zo een paar bytes besparen bij het verzenden van het verzoek 🙂
u — de gebruikersnaam, het inloggegeven van de hardware
p — het wachtwoord
"-O /tmp/wa.sh" — het bestand op de externe router waar het serverantwoord zal worden opgeslagen, bijvoorbeeld het commando reboot.

Opmerking nummer twee: Aaaa, waarom gebruiken we wget en niet curl, aangezien je met curl https-verzoeken kunt verzenden en niet alleen met GET maar ook met POST? Aaaa omdat, zoals in de oude grap, "Er gaat niets de kruik in!". Curl omvat encryptiebibliotheken van ongeveer 2 MB en het is dus onwaarschijnlijk dat je een image kunt samenstellen voor een kleine TP-LINK ML3020 bijvoorbeeld. Maar met wget — dat kan.

2) Aan de serverzijde (ik gebruik Ubuntu) gaan we Zabbix gebruiken. Waarom: ik wil dat het er mooi uitziet (met grafieken) en handig is (commando's verzenden via het contextmenu). Zabbix heeft zo'n heerlijke functie genaamd de zabbix-agent. Via de agent zullen we een php-script aanroepen op de server, dat informatie zal teruggeven over of onze router zich in de vereiste periode heeft geregistreerd. Voor het opslaan van informatie over de registratietijden, commando's voor apparaten, gebruik ik MySQL, een aparte tabel users met ongeveer deze velden:

		CREATIE TABEL `users` (
		  `id` varchar(25) NIET NULL,
		  `passwd` varchar(25) NIET NULL,
		  `description` varchar(150) NIET NULL,
		  `category` varchar(30) NIET NULL,
		  `status` varchar(10) NIET NULL,
		  `last_time` varchar(20) NIET NULL, // tijd van de laatste verbinding
		  `last_ip` varchar(20) NIET NULL, // IP van de laatste verbinding 
		  `last_port` int(11) NIET NULL, // poort van de laatste verbinding
		  `task` text NIET NULL, // taak die de router ontvangt
		  `reg_task` varchar(150) NIET NULL, // "reguliere" taak, als we willen dat de taak altijd wordt uitgevoerd bij registratie
		  `last_task` text NIET NULL, // log van taken
		  `response` text NIET NULL, // hier wordt het antwoord van het apparaat geschreven
		  `seq` int(11) NIET NULL
		) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Alle bronnen kunnen worden opgehaald uit de Git-repository op het volgende adres: https://github.com/BazDen/iotnet.online.git
Nu kunnen PHP-scripts, geplaatst aan de serverzijde (voor gemak kunnen ze in de map /usr/share/zabbix/ worden geplaatst):

Bestand a.php:

set_charset("utf8");
	// hier zoeken we onze router in de databasetabel
	$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();
		// hier sturen we de taken naar de router
		echo $task;
		echo "n";
		echo $reg_task;
		// hier schrijven we de responstijd en het antwoord van de router
		$response_history="[".date("Y-m-d H:i")."] ".$message;
		// taak verzonden, nu moeten we het verwijderen, en na verwijdering in de logs markeren dat deze taak is uitgevoerd
		$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();
		}
		// nu moeten we de registratietijd van de gebruiker, zijn ip en zijn bericht opslaan. Tot nu toe alleen het bericht
		$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();
	}
	// als we de router niet in onze database hebben gevonden, of zijn status is "inactief", dan zal er een reboot-commando worden gestuurd....
	// Waarom zo wreed? Omdat routers soms verdwijnen, en dit is een kleine manier om "nieuwe eigenaren" te straffen.
	else
	{
	echo "reboot";
	}
	$sql_users->close();
?>

Het bestand agent.php (dit is het script van de aangeroepen 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. During registration, the device sets this field to "1"
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		echo $seq;
	}
		
	// Reset $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();
?>		

En de laatste stap: het registreren van de agent en het toevoegen van grafieken.

Als u de zabbix-agent nog niet heeft geïnstalleerd, dan:

apt-get install zabbix-agent

Bewerk het bestand /etc/zabbix/zabbix_agentd.conf.

Voeg de volgende regel toe:

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

, waar:
test – de naam van onze agent
„php /usr/share/zabbix/agent.php user password“ – het script dat wordt aangeroepen met de logingegevens van het apparaat.

Grafieken toevoegen: open de webinterface van Zabbix, kies in het menu:
Configuratie -> Netwerknodes -> Maak netwerknode. Hier hoeft u alleen de naam van de netwerknode, zijn groep en de standaard agentinterface op te geven:

Afstandsmonitoring en beheer van apparaten op basis van Lunix/OpenWrt/Lede via poort 80…

Nu moeten we voor deze netwerknode een dataveld toevoegen. Let op de twee velden: „sleutel“ – dat is de parameter die we in het bestand /etc/zabbix/zabbix_agentd.conf hebben opgegeven (in ons geval is dat test), en „update-interval“ – ik zet dit op 5 minuten, omdat het apparaat ook eens in de vijf minuten wordt geregistreerd op de server.

Afstandsmonitoring en beheer van apparaten op basis van Lunix/OpenWrt/Lede via poort 80…

En voeg de grafiek toe. Ik raad aan om „Vulling“ als stijl voor de rendering te kiezen.

Afstandsmonitoring en beheer van apparaten op basis van Lunix/OpenWrt/Lede via poort 80…

Het resultaat is iets heel overzichtelijks, bijvoorbeeld zo:

Afstandsmonitoring en beheer van apparaten op basis van Lunix/OpenWrt/Lede via poort 80…

Op de redelijke vraag: „was het dat waard?“, antwoord ik: natuurlijk, kijk naar „de redenen voor het creëren van de fiets“ aan het begin van het artikel.

Als mijn eerste grafomanie de interesse van de lezers wekt, wil ik in de volgende artikelen beschrijven hoe je opdrachten naar apparatuur op afstand kunt verzenden. Ik heb ook het hele schema weten te realiseren voor apparaten die draaien op RouterOS (Mikrotik).

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster