Fernüberwachung und -verwaltung von Linux / OpenWrt / Lede-basierten Geräten über Port 80 ...

Hallo allerseits, dies ist meine erste Erfahrung auf Habré. Ich möchte darüber schreiben, wie nicht standardmäßige Netzwerkgeräte in einem externen Netzwerk verwaltet werden. Was bedeutet es nicht standardisiert: In den meisten Fällen müssen Sie zur Steuerung von Geräten in einem externen Netzwerk:

  • Die öffentliche IP-Adresse. Nun, oder wenn sich das Gerät hinter dem NAT einer anderen Person befindet, dann die öffentliche IP und der "weitergeleitete" Port.
  • Der Tunnel (PPTP / OpenVPN / L2TP + IPSec usw.) zum zentralen Knoten, über den er zugänglich wäre.

Daher benötigen Sie mein Fahrrad, wenn Standardmethoden für Sie nicht geeignet sind, zum Beispiel:
  1. Das Gerät befindet sich hinter dem NAT und bis auf den üblichen http (Port 80) ist alles geschlossen. Für große Unternehmensnetzwerke des Bundes ist die Situation ganz normal. Registrieren Sie Ports - sie können, aber nicht sofort, nicht schnell und nicht für Sie.
  2. Instabiler und / oder "enger" Kommunikationskanal. Niedrige Geschwindigkeit, konstanter Verlust. Schmerz und Frustration beim Versuch, einen Tunnel zu organisieren.
  3. Ein teurer Kommunikationskanal, bei dem buchstäblich jedes Megabyte zählt. Zum Beispiel Satellitenkommunikation. Plus große Verzögerungen und ein "schmaler" Streifen.
  4. Die Situation, in der Sie eine große Anzahl kleiner Router "jonglieren" müssen, auf denen einerseits OpenWrt / Lede installiert ist, um die Funktionen zu erweitern, und andererseits die Ressourcen (Speicher) des Routers bei weitem nicht ausreichen.

Anzahl mal notieren
Und was verhindert, dass ein USB-Stick vom Router installiert wird und der Speicher des Routers erweitert wird?

Meistens spielen die Anforderungen an die Kosten der gesamten Lösung, manchmal spielt auch der Formfaktor eine wichtige Rolle. Zum Beispiel ist das Objekt mit einem TP-Link ML3020 ausgestattet, dessen einziger USB-Anschluss unter einem 2G / 3G-Modem verwendet wird. All dies wird in einen Faden mit einem kleinen Kunststoffgehäuse gewickelt und irgendwo hoch hoch (am Mast), weit, weit (in) platziert Feld, 30 km von der nächsten Basisstation eines Mobilfunkbetreibers entfernt). Ja, Sie können einen USB-Hub anschließen und die Anzahl der Ports erhöhen. Die Erfahrung hat jedoch gezeigt, dass dies umständlich und unzuverlässig ist.

Deshalb habe ich versucht, Ihnen meine typische Situation zu beschreiben: „Irgendwo weit, weit weg gibt es einen sehr wichtigen, einsamen und kleinen Router, auf dem Linux ausgeführt wird. Es ist wichtig, mindestens einmal am Tag zu wissen, dass er "lebt", und wenn nötig, wurden ihm Befehle gesendet, zum Beispiel "Sonne, Neustart!"

Fahren wir mit der Implementierung fort:

1) Cron auf der Routerseite alle 5/10/1440 Minuten oder wann immer Sie eine http-Anfrage mit wget an den Server senden müssen, speichern Sie das Ergebnis der Anfrage in einer Datei, machen Sie die Datei ausführbar und führen Sie sie aus.

Meine Linie in Cron sieht ungefähr so ​​aus:

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

wo:
xn - 80abgfbdwanb2akugdrd3a2e5gsbj.xn - p1ai - die Domäne meines Servers. Ich werde sofort bemerken: Ja, Sie können auch eine bestimmte Server-IP-Adresse angeben. Wir haben dies bereits zuvor getan, während unser Staat in einem gerechten Ausbruch des Kampfes mir nicht mehr schien - den Zugang zum Löwenanteil der „Wolken“ von DigitalOcean und Amazon nicht blockiert hat. Wenn Sie bei Verwendung eines solchen Vorfalls eine symbolische Domäne verwenden, können Sie die Sicherungswolke ruhig anheben, die Domäne darauf umleiten und die Geräteüberwachung wiederherstellen.

a.php - der Name des Skripts auf der Serverseite. Ja, ich weiß, dass es falsch ist, Variablen und Dateinamen mit einem Buchstaben zu benennen ... Ich schlage vor, dass wir beim Senden einer Anfrage ein paar Bytes sparen :)
u - Benutzername, Hardware-Login
p - Passwort
"-O /tmp/wa.sh" ist die Datei auf dem Remote-Router, in der die Serverantwort gespeichert wird, z. B. der Neustartbefehl.

Anmerkung Nummer zwei:
Ahhh, warum verwenden wir wget, nicht curl, weil Sie durch curl https-Anfragen senden können und nicht GET, sondern POST? Ahhh, denn wie im alten Witz "schleicht sich NE in die Hütte!". Curl enthält Verschlüsselungsbibliotheken mit einer Größe von etwa 2 MB. Auf diese Weise können Sie beispielsweise ein Bild für einen kleinen TP-LINK ML3020 zusammenstellen. Und mit wget bitte.

2) Auf der Serverseite (ich habe Ubuntu) werden wir Zabbix verwenden. Warum: Ich möchte, dass es schön (mit Grafiken) und bequem ist (Befehle über das Kontextmenü senden). Zabbix hat so eine schöne Sache als Zabbix-Agent. Über den Agenten rufen wir das PHP-Skript auf dem Server auf, das Informationen darüber zurückgibt, ob unser Router im erforderlichen Zeitraum registriert wurde. Um Informationen über die Registrierungszeit und Befehle für Geräte zu speichern, verwende ich MySQL, eine separate Benutzertabelle mit ungefähr den folgenden Feldern:

  CREATE TABLE `users` ( `id` varchar(25) NOT NULL, `passwd` varchar(25) NOT NULL, `description` varchar(150) NOT NULL, `category` varchar(30) NOT NULL, `status` varchar(10) NOT NULL, `last_time` varchar(20) NOT NULL, //    `last_ip` varchar(20) NOT NULL, // IP   `last_port` int(11) NOT NULL, //    `task` text NOT NULL, //     `reg_task` varchar(150) NOT NULL, // "" ,          `last_task` text NOT NULL, //   `response` text NOT NULL, //     `seq` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Alle Quellen können aus dem Git-Repository unter folgender Adresse entnommen werden: https://github.com/BazDen/iotnet.online.git
Jetzt die auf der Serverseite gehosteten PHP-Skripte (der Einfachheit halber können Sie sie im Ordner / usr / share / zabbix / ablegen):

A.php-Datei:

 <?php //   :  ,       //   message ?    ,         $user=$_REQUEST['u']; $password=$_REQUEST['p']; $message=$_REQUEST['m']; //      (MySQL) $conn=new mysqli("localhost","db_login","db_password","DB_name"); if (mysqli_connect_errno()) { exit(); } $conn->set_charset("utf8"); //         $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(); //       echo $task; echo "\n"; echo $reg_task; //           $response_history="[".date("Ymd H:i")."] ".$message; //  ,    ,     ,  -   $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(); } //      ,      .    $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(); } //         ,    "",   ...    reboot.... //    ?     ,      " ". else { echo "reboot"; } $sql_users->close(); ?> 

Agent.php-Datei (dies ist das Skript des aufgerufenen zabbix-Agenten):

 <?php //   Zabbix.      users   "1"        // user  password -    $user = $argv[1]; $password = $argv[2]; //      $conn=new mysqli("localhost","db_user","db_password","db_name"); if (mysqli_connect_errno()) { exit(); } $conn->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(); //      seq.        "1" if (($sql_users->num_rows)==1){ $sql_users->fetch(); echo $seq; } //  $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(); ?> 

Nun, die letzte Phase: Verschreiben eines Agenten und Hinzufügen von Zeitplänen.

Wenn Sie den zabbix-Agenten noch nicht installiert haben, gehen Sie wie folgt vor:

 apt-get install zabbix-agent 

Bearbeiten der Datei /etc/zabbix/zabbix_agentd.conf.

Fügen Sie die Zeile hinzu:

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

wo:
Test ist der Name unseres Agenten
"Php /usr/share/zabbix/agent.php Benutzerpasswort" - das aufgerufene Skript mit den Registrierungsdaten des Geräts.

Hinzufügen von Grafiken: Öffnen Sie die zabbix-Weboberfläche und wählen Sie aus dem Menü:
Einstellungen -> Hosts -> Host erstellen. Es reicht aus, den Hostnamen, seine Gruppe und die Standardagentenschnittstelle anzugeben:



Jetzt müssen wir ein Datenelement für diesen Host hinzufügen. Achten Sie auf zwei Felder: Der "Schlüssel" ist genau der Parameter, den wir in der Datei /etc/zabbix/zabbix_agentd.conf angegeben haben (in unserem Fall ist es ein Test), und das "Aktualisierungsintervall" - ich habe 5 Minuten festgelegt, weil und das Gerät wird alle fünf Minuten auf dem Server registriert.



Nun, fügen Sie den Zeitplan hinzu. Ich empfehle, als Zeichenstil „Füllen“ zu wählen.



Die Ausgabe ist sehr prägnant, zum Beispiel wie folgt:



Auf die vernünftige Frage: "War es das wert?" Werde ich antworten: Nun, natürlich sehen Sie die "Gründe für die Herstellung eines Fahrrads" am Anfang des Artikels.

Wenn meine erste graphomanische Erfahrung das Interesse der Leser wecken wird, möchte ich in den folgenden Artikeln beschreiben, wie Befehle an entfernte Geräte gesendet werden. Es war auch möglich, das gesamte Schema für Geräte zu implementieren, die auf RouterOS (Mikrotiks) basieren.

Source: https://habr.com/ru/post/de445568/


All Articles