Giám sát và điều khiển từ xa các thiết bị dựa trên Lunix/OpenWrt/Lede qua cổng 80…

Xin chào mọi người, đây là lần đầu tiên tôi trải nghiệm Habré. Tôi muốn viết về cách quản lý thiết bị mạng trên mạng bên ngoài theo cách không chuẩn. Phi tiêu chuẩn nghĩa là gì: trong hầu hết các trường hợp, để quản lý thiết bị trên mạng bên ngoài, bạn cần:

  • Địa chỉ IP công cộng. Chà, hoặc nếu thiết bị nằm sau NAT của ai đó, thì đó là IP công cộng và cổng “chuyển tiếp”.
  • Đường hầm (PPTP/OpenVPN/L2TP+IPSec, v.v.) tới nút trung tâm mà qua đó có thể truy cập được.

Do đó, bạn sẽ cần “xe đạp của tôi” khi các phương pháp tiêu chuẩn không phù hợp với bạn, ví dụ:

  1. Thiết bị được đặt phía sau NAT và ngoại trừ http (cổng 80) thông thường, mọi thứ đều bị đóng. Đây là tình huống hoàn toàn bình thường đối với các mạng doanh nghiệp liên bang lớn. Họ có thể đăng ký cổng, nhưng không phải ngay lập tức, không nhanh chóng và không dành cho bạn.
  2. Kênh liên lạc không ổn định và/hoặc “hẹp”. Tốc độ thấp, tổn thất liên tục. Đau đớn và thất vọng khi cố gắng tổ chức một đường hầm.
  3. Một kênh liên lạc đắt tiền, trong đó mỗi megabyte đều có giá trị. Ví dụ, thông tin vệ tinh. Cộng với độ trễ dài và dải tần “hẹp”.
  4. Một tình huống khi bạn cần “tung hứng” một số lượng lớn các bộ định tuyến nhỏ, một mặt OpenWrt/Lede được cài đặt để mở rộng khả năng, mặt khác tài nguyên (bộ nhớ) của bộ định tuyến là không đủ cho tất cả.

Ghi chú số lần Điều gì ngăn cản bạn cài đặt ổ đĩa flash vào cổng USB của bộ định tuyến và mở rộng bộ nhớ của bộ định tuyến?

Thông thường, các yêu cầu là về chi phí của toàn bộ giải pháp, nhưng đôi khi yếu tố hình thức cũng đóng một vai trò quan trọng. Ví dụ: có TP-Link ML3020 tại địa điểm này, cổng USB duy nhất của nó được sử dụng cho modem 2G/3G, tất cả những thứ này được bọc trong một loại hộp nhựa nhỏ nào đó và đặt ở một nơi nào đó cao, cao (trên cột), rất xa (tại hiện trường, cách trạm gốc của nhà điều hành di động gần nhất 30 km). Có, bạn có thể cắm hub USB và mở rộng số lượng cổng, nhưng kinh nghiệm cho thấy điều này cồng kềnh và không đáng tin cậy.

Vì vậy, tôi đã cố gắng mô tả cho các bạn tình huống điển hình của tôi: “ở một nơi rất xa, rất xa, có một bộ định tuyến nhỏ, cô đơn và rất quan trọng chạy Linux. Điều quan trọng là phải biết ít nhất một lần mỗi ngày rằng anh ấy “còn sống” và nếu cần, các lệnh sẽ được gửi đến anh ấy, chẳng hạn như “em yêu, khởi động lại!”

Hãy chuyển sang thực hiện:

1) Về phía bộ định tuyến, qua cron, cứ sau 5/10/1440 phút hoặc bất cứ khi nào bạn muốn, bạn cần gửi yêu cầu http đến máy chủ bằng wget, lưu kết quả của yêu cầu vào một tệp, làm cho tệp có thể thực thi được , và thực hiện nó.

Dòng cron của tôi trông giống như thế này:

Tệp /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

Ở đâu:
xn--80abgfbdwanb2akugdrd3a2e5gsbj.xn--p1ai là miền máy chủ của tôi. Hãy để tôi lưu ý ngay: có, bạn có thể chỉ định một địa chỉ IP cụ thể của máy chủ, chúng tôi đã từng làm điều này cho đến khi đạt được trạng thái của chúng tôi, trong một nỗ lực đấu tranh chính đáng, tôi sẽ nói, tôi không biết, đã chặn quyền truy cập vào sư tử thị phần của “đám mây” DigitalOcean và Amazon. Nếu bạn sử dụng miền tượng trưng, ​​​​nếu sự cố như vậy xảy ra, bạn có thể dễ dàng tạo đám mây dự phòng, chuyển hướng miền đến đó và khôi phục giám sát thiết bị.

a.php là tên của tập lệnh phía máy chủ. Có, tôi biết rằng việc đặt tên biến và tên tệp bằng cùng một chữ cái là sai... Tôi đề xuất rằng cách này chúng ta sẽ tiết kiệm được một vài byte khi gửi yêu cầu :)
u - tên người dùng, đăng nhập phần cứng
p - mật khẩu
“-O /tmp/wa.sh” là một tệp trên bộ định tuyến từ xa nơi phản hồi của máy chủ, chẳng hạn như lệnh khởi động lại, sẽ được lưu.

Lưu ý số XNUMX: Ahhh, tại sao chúng ta sử dụng wget mà không sử dụng Curl, bởi vì thông qua Curl, bạn có thể gửi yêu cầu https không phải bằng GET mà bằng POST? Ahhh bởi vì, như trong câu chuyện cười xưa “NE trèo vào trong lọ!” Curl bao gồm các thư viện mã hóa có kích thước khoảng 2MB và do đó, không chắc là bạn sẽ có thể tập hợp một hình ảnh cho một TP-LINK ML3020 nhỏ chẳng hạn. Và với wget - làm ơn.

2) Về phía máy chủ (tôi có Ubuntu), chúng tôi sẽ sử dụng Zabbix. Tại sao: Tôi muốn nó đẹp (có đồ thị) và thuận tiện (gửi lệnh qua menu ngữ cảnh). Zabbix có một điều tuyệt vời là đặc vụ zabbix. Thông qua tác nhân, chúng tôi sẽ gọi một tập lệnh PHP trên máy chủ, tập lệnh này sẽ trả về thông tin về việc bộ định tuyến của chúng tôi có đăng ký trong khoảng thời gian cần thiết hay không. Để lưu trữ thông tin về thời gian đăng ký, lệnh cho thiết bị, tôi sử dụng MySQL, một bảng riêng cho người dùng với các trường khoảng sau:

		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;

Tất cả các nguồn có thể được tải xuống từ kho Git tại: https://github.com/BazDen/iotnet.online.git
Bây giờ các tập lệnh PHP được đặt ở phía máy chủ (để thuận tiện, chúng có thể được đặt trong thư mục /usr/share/zabbix/):

tập tin 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();
	?>

Tệp Agent.php (đây là tập lệnh của tác nhân zabbix được gọi):

<?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();
?>		

Vâng, giai đoạn cuối cùng: đăng ký đại lý và thêm lịch trình.

Nếu bạn chưa cài đặt tác nhân zabbix thì:

apt-get install zabbix-agent

Chỉnh sửa tệp /etc/zabbix/zabbix_agentd.conf.

Thêm dòng:

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

Ở đâu:
test là tên của đại lý của chúng tôi
“Mật khẩu người dùng php /usr/share/zabbix/agent.php” - một tập lệnh được gọi cho biết dữ liệu đăng ký thiết bị.

Thêm biểu đồ: mở giao diện web zabbix, chọn từ menu:
Cài đặt -> Nút mạng -> Tạo nút mạng. Ở đây chỉ cần chỉ định tên của máy chủ mạng, nhóm của nó và giao diện tác nhân mặc định là đủ:

Giám sát và điều khiển từ xa các thiết bị dựa trên Lunix/OpenWrt/Lede qua cổng 80…

Bây giờ chúng ta cần thêm phần tử dữ liệu cho nút mạng này. Hãy chú ý đến hai trường: “key” - đây chính xác là tham số mà chúng tôi đã viết trong tệp /etc/zabbix/zabbix_agentd.conf (trong trường hợp của chúng tôi là kiểm tra) và “khoảng thời gian cập nhật” - Tôi đặt thành 5 phút , bởi vì và thiết bị cũng được đăng ký trên máy chủ cứ năm phút một lần.

Giám sát và điều khiển từ xa các thiết bị dựa trên Lunix/OpenWrt/Lede qua cổng 80…

Vâng, hãy thêm một biểu đồ. Tôi khuyên bạn nên chọn “Fill” làm kiểu kết xuất.

Giám sát và điều khiển từ xa các thiết bị dựa trên Lunix/OpenWrt/Lede qua cổng 80…

Đầu ra là một cái gì đó rất ngắn gọn, ví dụ như thế này:

Giám sát và điều khiển từ xa các thiết bị dựa trên Lunix/OpenWrt/Lede qua cổng 80…

Đối với câu hỏi hợp lý: “nó có đáng không?”, tôi sẽ trả lời: tất nhiên, hãy xem “lý do tạo ra một chiếc xe đạp” ở đầu bài viết.

Nếu trải nghiệm đồ họa đầu tiên của tôi khơi dậy sự quan tâm của độc giả, thì trong những bài viết sau tôi muốn mô tả cách gửi lệnh đến thiết bị từ xa. Chúng tôi cũng đã quản lý để triển khai toàn bộ sơ đồ cho các thiết bị dựa trên RouterOS (Mikrotik).

Nguồn: www.habr.com

Thêm một lời nhận xét