Cześć wszystkim, to moje pierwsze doświadczenie na Habra. Chcę napisać o tym, jak nietypowo zarządzać urządzeniami sieciowymi w zewnętrznej sieci. Co oznacza nietypowo: w większości przypadków, do zarządzania urządzeniami w zewnętrznej sieci potrzebujesz:
- Publicznego adresu IP. Lub jeśli urządzenie znajduje się za czyimś NAT-em, to publicznego IP i „przekierowanego” portu.
- Tunelu (PPTP/OpenVPN/L2TP+IPSec itd.) do centralnego węzła, przez który byłaby dostępna.
Dlatego „mój rower” będzie potrzebny, gdy standardowe metody Ci nie odpowiadają, na przykład:
- Urządzenie znajduje się za NAT-em, a oprócz zwykłego http (port 80) – wszystko jest zamknięte. Całkiem normalna sytuacja w dużych ogólnokrajowych sieciach korporacyjnych. Mogą przepisać porty – ale nie od razu, nie szybko i nie dla Ciebie.
- Niestabilny i/lub „wąski” kanał komunikacyjny. Niska prędkość, ciągłe straty. Ból i rozczarowanie przy próbie zorganizowania tunelu.
- Drogi kanał komunikacyjny, gdzie dosłownie każdy megabajt jest na wagę złota. Na przykład komunikacja satelitarna. Dodatkowo duże opóźnienia i „wąska” przepustowość.
- Sytuacja, w której musisz „żonglować” dużą ilością małych routerów, na których z jednej strony zainstalowano OpenWrt/Lede w celu rozszerzenia możliwości, a z drugiej strony pamięci routera nie starcza na wszystko.
Notatka numer jeden A co przeszkadza w podłączeniu „pendrive'a” do portu USB routera i zwiększeniu pamięci routera?
Najczęściej wymagania dotyczące kosztów rozwiązania jako całości, ale czasami kluczową rolę odgrywa także forma. Na przykład w obiekcie znajduje się TP-Link ML3020, jego jedyny port USB jest używany do modemu 2G/3G, wszystko to jest owinięte w jakiś mały plastikowy korpus i umieszczone wysoko (na maszcie), daleko (na przykład w polu, 30 km od najbliższej stacji bazowej operatora komórkowego). Tak, można podłączyć hub USB i zwiększyć liczbę portów, ale doświadczenie pokazuje, że jest to nieporęczne i niewiarygodne.
Tak więc, starałem się opisać moją typową sytuację: „gdzieś daleko, stoi bardzo ważny, samotny i mały router zarządzany przez Linux. Ważne jest, aby przynajmniej raz dziennie wiedzieć, że jest „żywy” i w razie potrzeby wysłać mu polecenia, na przykład „słoneczko, zrestartuj się!”
Przejdźmy do realizacji:
1) Po stronie routera co 5/10/1440 minut, lub w dowolnym innym momencie, należy wysłać żądanie http do serwera przy użyciu wget, zapisać wynik żądania w pliku, nadać plikowi prawa do wykonania i wykonać go.
Moja linia w cron wygląda mniej więcej tak:
Plik /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 , gdzie:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai — domena mojego serwera. Od razu zaznaczam: tak, można podać również konkretny adres IP serwera, wcześniejsze tak robiliśmy, póki nasze państwo, w słusznym zapale walki z czymś, czego nie wiem — nie zablokowało dostępu do większości „chmur” DigitalOcean i Amazon. W przypadku użycia symbolicznej domeny, w przypadku zaistnienia takiego przypadku, spokojnie będzie można uruchomić zapasową chmurę, przekierować na nią domenę i przywrócić monitorowanie urządzeń.
a.php — nazwa skryptu po stronie serwera. Tak, wiem, że to błąd, nazywać zmienne i nazwy plików jedną literą… proponuję uznać, że w ten sposób oszczędzamy kilka bajtów przy wysyłaniu żądania 🙂
u — nazwa użytkownika, login urządzenia
p — hasło
„-O /tmp/wa.sh“ — plik na zdalnym routerze, gdzie będzie przechowywana odpowiedź serwera, na przykład polecenie reboot.
Uwagi numer dwa: Aaaa, dlaczego używamy wget, a nie curl, przecież przez curl można wysyłać żądania https i nie tylko GET, ale także POST? Aaaa dlatego, że jak w starym dowcipie „Nie wejdzie do wiadra!”. W skład curl wchodzą biblioteki szyfrujące o wielkości około 2 MB i z tego powodu prawdopodobnie nie uda się szybko zbudować obrazu dla małego TP-LINK ML3020, na przykład. A z wget — proszę bardzo.
2) Po stronie serwera (u mnie to Ubuntu) użyjemy Zabbixa. Dlaczego: chcę, aby to wyglądało ładnie (z wykresami) i wygodnie (wysyłać polecenia przez menu kontekstowe). Zabbix ma taką uroczą rzecz jak zabbix-agent. Poprzez agenta będziemy wywoływać skrypt php na serwerze, który będzie zwracał informacje o tym, czy nasz router zarejestrował się w wymaganym okresie czasu. Do przechowywania informacji o czasie rejestracji, poleceniach dla urządzeń, używam MySQL, oddzielnej tabeli users około takich pól:
STWÓRZ TABELĘ `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; Wszystkie źródła można pobrać z repozytorium Git pod adresem:
Teraz skrypty PHP umieszczane po stronie serwera (dla wygody można je umieścić w folderze /usr/share/zabbix/):
Plik a.php:
set_charset("utf8");
// tutaj szukamy naszego routera w tabeli bazy danych
$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();
// tutaj wysyłamy routerowi jego zadania
echo $task;
echo "n";
echo $reg_task;
// tutaj zapisujemy czas odpowiedzi i samą odpowiedź routera
$response_history="[".date("Y-m-d H:i")."] ".$message;
// zadanie zostało wysłane, teraz musimy je usunąć, a po usunięciu zaznaczyć w logach, że takie zadanie zostało wykonane
$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();
}
// teraz musimy zapisać czas rejestracji użytkownika, jego IP i wiadomość od niego. Na razie tylko wiadomość
$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();
}
// jeśli nie znaleźliśmy routera w naszej bazie danych lub jego status to "nieaktywny", to zostanie mu wysłana komenda reboot....
// Dlaczego tak surowo? Ponieważ routery czasami znikają, a to mały sposób na ukaranie "nowych właścicieli".
else
{
echo "reboot";
}
$sql_users->close();
?>Plik agent.php (to skrypt wywoływanego agenta zabbix):
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();
// Wymiana danych odbywa się przez pole seq. Podczas rejestracji urządzenie ustawia to pole na "1"
if (($sql_users->num_rows)==1){
$sql_users->fetch();
echo $seq;
}
// Zresetuj $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();
?> No i ostatni etap: zarejestrowanie agenta i dodanie wykresów.
Jeśli jeszcze nie masz zainstalowanego agenta zabbix, to:
apt-get install zabbix-agentEdytujemy plik /etc/zabbix/zabbix_agentd.conf.
Dodajemy linijkę:
UserParameter=test,php /usr/share/zabbix/agent.php user password , gdzie:
test — nazwa naszego agenta
„php /usr/share/zabbix/agent.php user password“ — wywoływany skrypt z danymi logowania urządzenia.
Dodawanie wykresów: otwieramy interfejs webowy zabbix, w menu wybieramy:
Konfiguracja -> Węzły sieci -> Utwórz węzeł sieci. Tutaj wystarczy podać nazwę węzła sieci, jego grupę, interfejs agenta domyślnie:

Teraz dla tego węzła sieci musimy dodać element danych. Zwróć uwagę na dwa pola: „klucz“ — to właśnie ten parametr, który wpisaliśmy w pliku /etc/zabbix/zabbix_agentd.conf (w naszym przypadku to test), oraz „interwał aktualizacji“ — ustalam go na 5 minut, ponieważ sprzęt rejestruje się na serwerze również raz na pięć minut.

A teraz dodajemy wykres. Polecam wybrać styl rysowania „Wypełnienie“.

Na wyjściu otrzymujemy coś bardzo zwięzłego, na przykład tak:

Na zasadne pytanie: „czy to się opłacało?“, odpowiem: oczywiście, zobacz „powody stworzenia roweru“ na początku artykułu.
Jeśli moje pierwsze grafomańskie doświadczenie wzbudzi zainteresowanie czytelników, to w kolejnych artykułach chcę opisać, jak wysyłać polecenia na zdalne urządzenia. Udało mi się zrealizować całą schemę również dla urządzeń opartych na RouterOS (Mikrotik).
Źródło: habr.com
