สวัสดีทุกคน นี่เป็นประสบการณ์ครั้งแรกของฉันกับHabré ฉันต้องการเขียนเกี่ยวกับวิธีจัดการอุปกรณ์เครือข่ายบนเครือข่ายภายนอกด้วยวิธีที่ไม่ได้มาตรฐาน ที่ไม่ได้มาตรฐานหมายถึงอะไร: ในกรณีส่วนใหญ่ คุณต้องมีการจัดการอุปกรณ์บนเครือข่ายภายนอก:
- ที่อยู่ IP สาธารณะ หรือหากอุปกรณ์อยู่หลัง NAT ของใครบางคน แสดงว่าเป็น IP สาธารณะและพอร์ต "ส่งต่อ"
- Tunnel (PPTP/OpenVPN/L2TP+IPSec ฯลฯ) ไปยังโหนดกลางที่สามารถเข้าถึงได้
ดังนั้น คุณจะต้องมี “จักรยานของฉัน” เมื่อวิธีการมาตรฐานไม่เหมาะกับคุณ เช่น:
- อุปกรณ์ตั้งอยู่ด้านหลัง NAT และยกเว้น http ปกติ (พอร์ต 80) ทุกอย่างปิดอยู่ นี่เป็นสถานการณ์ปกติโดยสิ้นเชิงสำหรับเครือข่ายองค์กรขนาดใหญ่ของรัฐบาลกลาง พวกเขาสามารถลงทะเบียนพอร์ตได้ แต่ไม่ใช่ในทันที ไม่รวดเร็ว และไม่ใช่สำหรับคุณ
- ช่องทางการสื่อสารไม่เสถียร และ/หรือ “แคบ” ความเร็วต่ำ การสูญเสียอย่างต่อเนื่อง ความเจ็บปวดและความหงุดหงิดเมื่อพยายามจัดอุโมงค์
- ช่องทางการสื่อสารที่มีราคาแพงซึ่งทุกเมกะไบต์มีความสำคัญอย่างแท้จริง เช่น การสื่อสารผ่านดาวเทียม บวกกับความล่าช้าที่ยาวนานและวงดนตรีที่ "แคบ"
- สถานการณ์เมื่อคุณต้องการ "เล่นปาหี่" เราเตอร์ขนาดเล็กจำนวนมาก ซึ่งในอีกด้านหนึ่ง OpenWrt/Lede ได้รับการติดตั้งเพื่อขยายขีดความสามารถ และในทางกลับกัน ทรัพยากร (หน่วยความจำ) ของเราเตอร์ยังไม่เพียงพอ สำหรับทุกอย่าง.
หมายเหตุจำนวนครั้ง อะไรขัดขวางไม่ให้คุณติดตั้งแฟลชไดรฟ์เข้ากับพอร์ต USB ของเราเตอร์และขยายหน่วยความจำของเราเตอร์
บ่อยครั้งที่ข้อกำหนดมีไว้สำหรับต้นทุนของโซลูชันโดยรวม แต่บางครั้งฟอร์มแฟคเตอร์ก็มีบทบาทสำคัญเช่นกัน ตัวอย่างเช่น มี TP-Link ML3020 ที่ไซต์ พอร์ต USB เพียงพอร์ตเดียวที่ใช้สำหรับโมเด็ม 2G/3G ทั้งหมดนี้ห่อด้วยกล่องพลาสติกขนาดเล็กบางชนิดและวางไว้ในตำแหน่งที่สูง สูง (บนเสากระโดง) ไกล, ไกล (ในสนาม 30 กม. จากสถานีฐานผู้ให้บริการโทรศัพท์เคลื่อนที่ที่ใกล้ที่สุด) ใช่ คุณสามารถเสียบฮับ USB และขยายจำนวนพอร์ตได้ แต่ประสบการณ์แสดงให้เห็นว่าสิ่งนี้ยุ่งยากและไม่น่าเชื่อถือ
ดังนั้นฉันจึงพยายามอธิบายสถานการณ์ทั่วไปของฉันให้คุณฟัง: “ที่ไหนสักแห่งที่ไกลออกไป มีเราเตอร์ขนาดเล็กที่โดดเดี่ยวและสำคัญมากที่ใช้ Linux สิ่งสำคัญคือต้องรู้อย่างน้อยวันละครั้งว่าเขา "มีชีวิตอยู่" และหากจำเป็นจะมีการส่งคำสั่งไปให้เขาเช่น "ที่รัก รีบูต!"
มาดูการดำเนินการกันดีกว่า:
1) ที่ฝั่งเราเตอร์ ผ่าน cron ทุกๆ 5/10/1440 นาที หรือเมื่อใดก็ตามที่คุณต้องการ คุณต้องส่งคำขอ http ไปยังเซิร์ฟเวอร์โดยใช้ wget บันทึกผลลัพธ์ของคำขอลงในไฟล์ ทำให้ไฟล์ปฏิบัติการได้ และดำเนินการมัน
เส้น cron ของฉันมีลักษณะดังนี้:
ไฟล์ /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
, ที่ไหน:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai คือโดเมนของเซิร์ฟเวอร์ของฉัน ฉันจะทราบทันที: ใช่ คุณสามารถระบุที่อยู่ IP เฉพาะของเซิร์ฟเวอร์ได้ เราเคยทำเช่นนี้จนกระทั่งรัฐของเรา ด้วยแรงกระตุ้นอันชอบธรรมของการต่อสู้ ฉันจะบอกว่า ฉันไม่รู้ ถูกบล็อกการเข้าถึง ส่วนแบ่งใหญ่ของ DigitalOcean และ Amazon "เมฆ" หากคุณใช้โดเมนสัญลักษณ์ หากเกิดเหตุการณ์ดังกล่าว คุณสามารถเพิ่มคลาวด์สำรอง เปลี่ยนเส้นทางโดเมนไปยังโดเมนนั้น และกู้คืนการตรวจสอบอุปกรณ์ได้อย่างง่ายดาย
a.php คือชื่อของสคริปต์ฝั่งเซิร์ฟเวอร์ ใช่ ฉันรู้ว่าการตั้งชื่อตัวแปรและชื่อไฟล์ด้วยตัวอักษรเดียวกันนั้นผิด... ฉันแนะนำว่าวิธีนี้จะช่วยประหยัดไบต์ได้สองสามไบต์เมื่อส่งคำขอ :)
คุณ - ชื่อผู้ใช้, เข้าสู่ระบบฮาร์ดแวร์
พี - รหัสผ่าน
“-O /tmp/wa.sh” เป็นไฟล์บนเราเตอร์ระยะไกลที่การตอบสนองของเซิร์ฟเวอร์ เช่น คำสั่งรีบูต จะถูกบันทึก
หมายเหตุหมายเลขสอง: อ้าว ทำไมเราถึงใช้ wget ไม่ใช่ curl เพราะผ่าน curl คุณสามารถส่งคำขอ https ที่ไม่ใช่ GET แต่ส่งด้วย POST ได้ อ่า เพราะอย่างกับมุกเก่าๆ ที่ว่า "NE ปีนเข้าไปในโถ!" curl มีไลบรารีการเข้ารหัสขนาดประมาณ 2MB และด้วยเหตุนี้ คุณจึงไม่น่าจะสามารถประกอบรูปภาพสำหรับ TP-LINK ML3020 ขนาดเล็กได้ เป็นต้น และด้วย wget - ได้โปรด
2) ทางฝั่งเซิร์ฟเวอร์ (ฉันมี Ubuntu) เราจะใช้ Zabbix เหตุผล: อยากให้สวยงาม (มีกราฟ) และสะดวก (ส่งคำสั่งผ่านเมนูบริบท) แซบบิกซ์มีสิ่งมหัศจรรย์เหมือนกับตัวแทนแซบบิกซ์ เราจะเรียกสคริปต์ PHP บนเซิร์ฟเวอร์ผ่านตัวแทนซึ่งจะส่งคืนข้อมูลเกี่ยวกับว่าเราเตอร์ของเราลงทะเบียนในช่วงเวลาที่กำหนดหรือไม่ ในการจัดเก็บข้อมูลเกี่ยวกับเวลาลงทะเบียนคำสั่งสำหรับอุปกรณ์ฉันใช้ MySQL ซึ่งเป็นผู้ใช้ตารางแยกต่างหากโดยมีฟิลด์ต่อไปนี้โดยประมาณ:
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;
สามารถดาวน์โหลดแหล่งที่มาทั้งหมดได้จากพื้นที่เก็บข้อมูล Git ที่:
ตอนนี้สคริปต์ PHP ถูกวางไว้ที่ฝั่งเซิร์ฟเวอร์ (เพื่อความสะดวก สามารถวางไว้ในโฟลเดอร์ /usr/share/zabbix/):
ไฟล์ a.php:
<?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 (นี่คือสคริปต์ของตัวแทน zabbix ที่เรียกว่า):
<?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();
?>
ขั้นตอนสุดท้าย: การลงทะเบียนตัวแทนและเพิ่มตารางเวลา
หากคุณยังไม่ได้ติดตั้งตัวแทน zabbix ให้:
apt-get install zabbix-agent
แก้ไขไฟล์ /etc/zabbix/zabbix_agentd.conf
เพิ่มบรรทัด:
UserParameter=test,php /usr/share/zabbix/agent.php user password
, ที่ไหน:
test คือชื่อตัวแทนของเรา
“รหัสผ่านผู้ใช้ php /usr/share/zabbix/agent.php” - สคริปต์ที่เรียกว่าระบุข้อมูลการลงทะเบียนอุปกรณ์
การเพิ่มแผนภูมิ: เปิดเว็บอินเตอร์เฟส zabbix เลือกจากเมนู:
การตั้งค่า -> โหนดเครือข่าย -> สร้างโหนดเครือข่าย การระบุชื่อโฮสต์เครือข่าย กลุ่ม และอินเทอร์เฟซเอเจนต์เริ่มต้นก็เพียงพอแล้ว:
ตอนนี้เราจำเป็นต้องเพิ่มองค์ประกอบข้อมูลสำหรับโหนดเครือข่ายนี้ ให้ความสนใจกับสองฟิลด์: "คีย์" - นี่คือพารามิเตอร์ที่เราเขียนในไฟล์ /etc/zabbix/zabbix_agentd.conf ทุกประการ (ในกรณีของเราคือการทดสอบ) และ "ช่วงเวลาอัปเดต" - ฉันตั้งไว้ที่ 5 นาที เพราะและอุปกรณ์จะถูกลงทะเบียนบนเซิร์ฟเวอร์ทุกๆ ห้านาทีด้วย
ทีนี้มาเพิ่มกราฟกัน ฉันแนะนำให้เลือก "เติม" เป็นรูปแบบการเรนเดอร์
ผลลัพธ์เป็นสิ่งที่กระชับมาก เช่น:
สำหรับคำถามที่สมเหตุสมผล: "คุ้มไหม" ฉันจะตอบ: แน่นอนดู "เหตุผลในการสร้างจักรยาน" ในตอนต้นของบทความ
หากประสบการณ์ Graphomaniac ครั้งแรกของฉันกระตุ้นความสนใจของผู้อ่านในบทความต่อไปนี้ฉันต้องการอธิบายวิธีส่งคำสั่งไปยังอุปกรณ์ระยะไกล นอกจากนี้เรายังจัดการเพื่อใช้โครงร่างทั้งหมดสำหรับอุปกรณ์ที่ใช้ RouterOS (Mikrotik)
ที่มา: will.com