Vzdálené sledování a správa zařízení na bázi Lunix/OpenWrt/Lede přes port 80…

Ahoj všichni, toto je moje první zkušenost na Habru. Chci napsat o tom, jak netradičně spravovat síťová zařízení ve veřejné síti. Co znamená netradičně: ve většině případů pro správu zařízení ve veřejné síti potřebujete:

  • Veřejná IP adresa. Nebo pokud je zařízení za něčím NAT, pak veřejná IP a „přesměrovaný“ port.
  • Tunel (PPTP/OpenVPN/L2TP+IPSec atd.) k centrální uzlu, přes který by bylo přístupné.

Proto bude „můj bicykl“ potřebný, když vám standardní metody nevyhovují, například:

  1. Zařízení je za NAT a kromě běžného http (port 80) je všechno zavřené. Naprosto normální situace pro velké federální korporátní sítě. Zapsat porty — mohou, ale ne okamžitě, rychle a ne pro vás.
  2. Nestabilní a/nebo „úzké“ spojení. Malá rychlost, neustálé ztráty. Bolest a zklamání při pokusu o organizaci tunelu.
  3. Drahé spojení, kde je doslova každý megabajt cenný. Například satelitní spojení. Plus vysoké latence a „úzká“ šířka pásma.
  4. Situace, kdy musíte „žonglovat“ s velkým množstvím malých routerů, na kterých je z jedné strany nainstalováno OpenWrt/Lede pro rozšíření možností, a z druhé strany prostředků (paměti) routeru je daleko nedostatek.

Poznámka číslo jedna A co brání v tom, abyste do USB portu routeru vložili „flashku“ a rozšířili paměť routeru?

Nejčastěji hrají roli požadavky na náklady řešení jako celku, ale někdy hraje klíčovou roli také formát. Například na místě je TP-Link ML3020, jeho jediný USB port je použit pro 2G/3G modem, to vše je zabalené v nějakém malém plastovém krytu a umístěné kdesi vysoko (na stožáru), daleko (v poli, 30 km od nejbližší základnové stanice mobilního operátora). Ano, můžete připojit USB hub a rozšířit počet portů, ale zkušenost ukazuje, že je to objemné a nespolehlivé.

Takže jsem se snažil vám popsat moji typickou situaci: „kdesi daleko, stojí velmi důležitý, osamělý a malý router běžící na Linuxu. Je důležité vědět alespoň jednou denně, že je "naživu" a v případě potřeby mu posílat příkazy, například "sluníčko, restartuj se!"

Přejděme k realizaci:

1) Na straně routeru pomocí cron každých 5/10/1440 minut, nebo kdykoli je třeba odesílat http požadavek na server pomocí wget, výsledek požadavku uložit do souboru, soubor udělat spustitelným a provést ho.

Můj řádek v cronu vypadá přibližně takto:

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

, kde:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai — doména mého serveru. Hned poznamenávám: ano, můžete uvést i konkrétní IP adresu serveru, dříve jsme to tak dělali, dokud naše vláda, v boji proti něčemu, co nevím, nezakázala přístup k většině „cloudů“ jako DigitalOcean a Amazon. V případě použití symbolické domény, pokud dojde k takovému problému, můžete jednoduše nastavit záložní cloud, přesměrovat na něj doménu a obnovit monitorování zařízení.

a.php — název skriptu na straně serveru. Ano, vím, že je špatné nazývat proměnné a názvy souborů jedním písmenem… navrhuji považovat to za úsporu několika bajtů při odesílání požadavku 🙂
u — uživatelské jméno, přihlašovací údaje zařízení
p — heslo
„-O /tmp/wa.sh“ — soubor na vzdáleném routeru, kam se bude ukládat odpověď serveru, například příkaz reboot.

Poznámka číslo dva: Aaaa, proč používáme wget, a ne curl, vždyť pomocí curl lze odesílat https požadavky a ne GETem, ale POSTem? Aaaa, protože jako v starém anekdotě „Do džbánu se nedá!“. Curl zahrnuje knihovny pro šifrování o velikosti zhruba 2 MB a jejich velikost znamená, že asi těžko sestavíte obraz pro malý TP-LINK ML3020 například. A s wget — prosím.

2) Na straně serveru (mám to na Ubuntu) budeme používat Zabbix. Proč: chci, aby to vypadalo hezky (s grafy) a bylo pohodlné (odesílat příkazy přes kontextové menu). Zabbix má jednu skvělou věc, jako je zabbix-agent. Přes agenta budeme volat php skript na serveru, který bude vracet informace o tom, jestli se náš router registroval v požadovaném časovém období. Pro uchovávání informací o čase registrace, příkazech pro zařízení používám MySQL, samostatnou tabulku uživatelů přibližně s těmito poli:

		VYTVOŘIT TABULKU `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, 
		  `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;

Všechny zdrojové kódy lze stáhnout z Git-repozitáře na adrese: https://github.com/BazDen/iotnet.online.git
Nyní PHP skripty umístěné na straně serveru (pro pohodlí je můžete umístit do složky /usr/share/zabbix/):

Soubor a.php:

set_charset("utf8");
	// zde hledáme náš router v tabulce databáze
	$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();
		// zde posíláme routeru jeho úkoly
		echo $task;
		echo "n";
		echo $reg_task;
		// zde zapisujeme čas odpovědi a samotnou odpověď routeru
		$response_history="[".date("Y-m-d H:i")."] ".$message;
		// úkol byl odeslán, nyní ho musíme odstranit, a po odstranění označit v logech, že takový úkol byl splněn
		$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();
		}
		// nyní musíme uložit čas registrace uživatele, jeho ip a zprávu od něj. Zatím pouze zprávu
		$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();
	}
	// pokud jsme nenalezli router v naší databázi, nebo jeho stav je "neaktivní", odešle se mu příkaz reboot....
	// Proč tak krutě? Protože routery občas zmizí, a to je malý způsob, jak potrestat "nové vlastníky". 
	else
	{
	echo "reboot";
	}
	$sql_users->close();
?>

Soubor agent.php (toto je skript volaného zabbix-agenta):

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();
	// Výměna dat probíhá přes pole seq. Při registraci zařízení se toto pole nastaví na "1"
	if (($sql_users->num_rows)==1){
		$sql_users->fetch();
		echo $seq;
	}
		
	// Nuluje $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();
?>		

A nyní poslední krok: nastavení agenta a přidání grafů.

Pokud nemáte nainstalovaný zabbix-agent, pak:

apt-get install zabbix-agent

Upravujeme soubor /etc/zabbix/zabbix_agentd.conf.

Přidáváme řádek:

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

, kde:
test — jméno našeho agenta
„php /usr/share/zabbix/agent.php user password“ — skript, který bude zavolán s přihlašovacími údaji zařízení.

Přidání grafů: otevřeme webové rozhraní zabbix, v menu vybereme:
Nastavení -> Uzly sítě -> Vytvořit uzel sítě. Zde stačí zadat název uzlu sítě, jeho skupinu, rozhraní agenta podle defaultu:

Vzdálené sledování a správa zařízení na bázi Lunix/OpenWrt/Lede přes port 80…

Nyní musíme pro tento uzel sítě přidat datový prvek. Věnujte pozornost dvěma polím: „klíč“ — to je parametr, který jsme uvedli v souboru /etc/zabbix/zabbix_agentd.conf (v našem případě to je test), a „interval aktualizace“ — já nastavím 5 minut, protože se zařízení také registruje na serveru jednou za pět minut.

Vzdálené sledování a správa zařízení na bázi Lunix/OpenWrt/Lede přes port 80…

A nyní přidáme graf. Doporučuji zvolit jako styl vykreslování „Výplň“.

Vzdálené sledování a správa zařízení na bázi Lunix/OpenWrt/Lede přes port 80…

Na výstupu získáme něco velmi lakonického, například takto:

Vzdálené sledování a správa zařízení na bázi Lunix/OpenWrt/Lede přes port 80…

Na legitimní otázku: „stálo to za to?“, odpovím: samozřejmě, podívejte se na „důvody pro vytvoření kola“ na začátku článku.

Pokud můj první grafomanský pokus vzbudí zájem čtenářů, pak v následujících článcích chci popsat, jak posílat příkazy na vzdálené zařízení. Také se mi podařilo realizovat celou schéma i pro zařízení na bázi RouterOS (Mikrotik).

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster