Pozdrav svima, ovo je moje prvo iskustvo na Habréu. Želim pisati o tome kako upravljati mrežnom opremom na vanjskoj mreži na nestandardan način. Šta znači nestandardno: u većini slučajeva za upravljanje opremom na vanjskoj mreži potrebno vam je:
- Javna IP adresa. Pa, ili ako oprema stoji iza nečijeg NAT-a, onda javni IP i "proslijeđeni" port.
- Tunel (PPTP/OpenVPN/L2TP+IPSec, itd.) do centralnog čvora preko kojeg bi bio dostupan.
Stoga će vam trebati "moj bicikl" kada vam standardne metode ne odgovaraju, na primjer:
- Oprema se nalazi iza NAT-a i osim uobičajenog http (port 80) sve je zatvoreno. Ovo je sasvim normalna situacija za velike federalne korporativne mreže. Oni mogu registrovati portove, ali ne odmah, ne brzo i ne za vas.
- Nestabilan i/ili “uzak” kanal komunikacije. Mala brzina, konstantni gubici. Bol i frustracija pri pokušaju organiziranja tunela.
- Skup komunikacijski kanal, gdje je bukvalno svaki megabajt bitan. Na primjer, satelitske komunikacije. Plus duga kašnjenja i "uski" opseg.
- Situacija kada je potrebno "žonglirati" velikim brojem malih rutera, na kojima je, s jedne strane, instaliran OpenWrt/Lede radi proširenja mogućnosti, a s druge strane resursi (memorija) rutera nisu dovoljni za sve.
Zabilježite broj puta Šta vas sprečava da instalirate fleš disk u USB port rutera i proširite memoriju rutera?
Najčešće su zahtjevi za cijenu rješenja u cjelini, ali ponekad i faktor oblika igra ključnu ulogu. Na primjer, na lokaciji se nalazi TP-Link ML3020, njegov jedini USB port se koristi za 2G/3G modem, sve je to umotano u nekakvu malu plastičnu kutiju i postavljeno negdje visoko, visoko (na jarbol), daleko, daleko (na terenu, 30 km od bazne stanice najbližeg mobilnog operatera). Da, možete priključiti USB čvorište i proširiti broj portova, ali iskustvo pokazuje da je to glomazno i nepouzdano.
Dakle, pokušao sam vam opisati svoju tipičnu situaciju: „negdje daleko, daleko, nalazi se vrlo važan, usamljen i mali ruter pod kontrolom...“ LinuxVažno je barem jednom dnevno znati da je "živ" i da mu se po potrebi mogu slati naredbe, na primjer, "Draga, ponovo pokreni!".
Pređimo na implementaciju:
1) Na strani rutera, preko cron-a, svakih 5/10/1440 minuta, ili kad god želite, trebate poslati http zahtjev serveru koristeći wget, sačuvati rezultat zahtjeva u datoteku, učiniti datoteku izvršnom , i izvršite ga.
Moja cron linija izgleda otprilike ovako:
Fajl /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 gdje:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai je domen mog servera. Odmah da napomenem: da, možete odrediti određenu IP adresu servera, to smo radili sve dok naša država, u pravednom nagonu borbe, reći ću, ne znam, nije blokirala pristup lavovskom udio DigitalOcean i Amazon “oblaka”. Ako koristite simboličku domenu, ako dođe do takvog incidenta, lako možete podići backup oblak, preusmjeriti domenu na njega i vratiti praćenje uređaja.
a.php je ime skripte na strani servera. Da, znam da je pogrešno imenovati varijable i nazive fajlova istim slovom... Predlažem da na ovaj način uštedimo nekoliko bajtova prilikom slanja zahteva :)
u - korisničko ime, hardverska prijava
p - lozinka
“-O /tmp/wa.sh” je datoteka na udaljenom ruteru gdje će se pohraniti odgovor servera, na primjer naredba za ponovno pokretanje.
Napomena broj dva: Ahhh, zašto koristimo wget, a ne curl, jer preko curl-a možete slati https zahtjeve ne sa GET-om, već sa POST-om? Ahhh jer, kao u starom vicu "NE se penje u teglu!" curl uključuje biblioteke za enkripciju veličine oko 2MB i zbog toga je malo vjerovatno da ćete moći sastaviti sliku za mali TP-LINK ML3020, na primjer. A sa wgetom - molim.
2) Na strani servera (imam ovo Ubuntu) koristit ćemo Zabbix. Zašto: Želim da bude lijep (s grafovima) i praktičan (slanje naredbi putem kontekstnog menija). Zabbix ima sjajnu funkciju koja se zove zabbix agent. Koristit ćemo agenta za pozivanje PHP skripte na server, koji će vratiti informacije o tome da li je naš ruter bio registrovan tokom potrebnog vremenskog perioda. Za pohranjivanje informacija o vremenima registracije i naredbama uređaja, koristim zasebnu MySQL tabelu pod nazivom "korisnici" sa poljima sličnim sljedećim:
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; Svi izvori se mogu preuzeti iz Git repozitorija na:
Sada su PHP skripte postavljene na strani servera (radi pogodnosti, mogu se postaviti u /usr/share/zabbix/ folder):
a.php fajl:
<?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("Y-m-d 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 fajl (ovo je skripta zabbix agenta):
<?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();
?> Pa, zadnja faza: registracija agenta i dodavanje rasporeda.
Ako još niste instalirali zabbix agenta, tada:
apt-get install zabbix-agentUredite datoteku /etc/zabbix/zabbix_agentd.conf.
Dodajte liniju:
UserParameter=test,php /usr/share/zabbix/agent.php user password gdje:
test je ime našeg agenta
“php /usr/share/zabbix/agent.php korisnička lozinka” - pozvana skripta koja označava podatke o registraciji uređaja.
Dodavanje grafikona: otvorite zabbix web sučelje, odaberite iz menija:
Postavke -> Mrežni čvorovi -> Kreiraj mrežni čvor. Ovdje je dovoljno navesti ime mrežnog hosta, njegovu grupu i zadani interfejs agenta:

Sada moramo dodati element podataka za ovaj mrežni čvor. Obratite pažnju na dva polja: "ključ" - to je upravo parametar koji smo napisali u /etc/zabbix/zabbix_agentd.conf fajl (u našem slučaju to je test), i "interval ažuriranja" - postavio sam ga na 5 minuta , jer se i oprema registruje na serveru svakih pet minuta.

Pa, dodajmo graf. Preporučujem da odaberete "Fill" kao stil prikazivanja.

Izlaz je nešto vrlo lakonski, na primjer ovako:

Na razumno pitanje: "je li se isplatilo?", odgovorit ću: pa, naravno, pogledajte "razloge za stvaranje bicikla" na početku članka.
Ako moje prvo grafomansko iskustvo izazove zanimanje čitatelja, onda u sljedećim člancima želim opisati kako slati komande udaljenoj opremi. Također smo uspjeli implementirati cijelu shemu za uređaje bazirane na RouterOS-u (Mikrotik).
izvor: www.habr.com
