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:
- 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.
- Nestabilní a/nebo „úzké“ spojení. Malá rychlost, neustálé ztráty. Bolest a zklamání při pokusu o organizaci tunelu.
- Drahé spojení, kde je doslova každý megabajt cenný. Například satelitní spojení. Plus vysoké latence a „úzká“ šířka pásma.
- 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:
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-agentUpravujeme 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:

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.

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

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

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
