通过端口 80 远程监控和控制基于 Lunix/OpenWrt/Lede 的设备...

大家好,这是我第一次体验哈布雷。 我想写一篇如何以非标准的方式管理外部网络上的网络设备。 非标准是什么意思:在大多数情况下,要管理外部网络上的设备,您需要:

  • 公共 IP 地址。 好吧,或者如果设备位于某人的 NAT 之后,则需要一个公共 IP 和一个“转发”端口。
  • 到中心节点的隧道(PPTP/OpenVPN/L2TP+IPSec 等),通过该隧道可对其进行访问。

因此,当标准方法不适合您时,您将需要“我的自行车”,例如:

  1. 该设备位于NAT后面,除了通常的http(端口80)之外,一切都是关闭的。 对于大型联邦企业网络来说,这是完全正常的情况。 他们可以注册端口,但不会立即、不会很快,而且不会为您注册。
  2. 不稳定和/或“狭窄”的沟通渠道。 速度低,损耗恒定。 尝试组织隧道时的痛苦和挫败感。
  3. 这是一种昂贵的通信渠道,几乎每一兆字节都很重要。 例如,卫星通信。 加上长延迟和“窄”频带。
  4. 需要“杂耍”大量小型路由器的情况,一方面安装了OpenWrt/Lede来扩展能力,另一方面路由器的资源(内存)又不够用对于一切。

注意次数 是什么阻止您将闪存驱动器安装到路由器的 USB 端口并扩展路由器的内存?

大多数情况下,要求是针对整个解决方案的成本,但有时外形因素也起着关键作用。 例如,现场有一个TP-Link ML3020,它唯一的USB端口用于2G/3G调制解调器,所有这些都被包裹在某种小塑料盒中,并放置在高高的地方(在桅杆上),很远很远(在现场,距离最近的移动运营商基站 30 公里)。 是的,您可以插入USB集线器并扩展端口数量,但经验表明这很麻烦且不可靠。

所以,我试图向你们描述我的典型情况:“在很远很远的地方,有一个非常重要、孤独的小型路由器,运行着 Linux。 重要的是每天至少一次知道他“还活着”,并且如有必要,会向他发送命令,例如“亲爱的,重新启动!”

让我们继续实施:

1)在路由器端,通过cron,每隔5/10/1440分钟,或者任何时候,需要使用wget向服务器发送http请求,将请求结果保存到文件中,使文件可执行,并执行它。

我的 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 和亚马逊“云”的份额。 如果您使用符号域,如果发生此类事件,您可以轻松地建立备份云,将域重定向到它并恢复设备监控。

a.php 是服务器端脚本的名称。 是的,我知道用相同的字母命名变量和文件名是错误的......我建议这样我们在发送请求时节省一些字节:)
u - 用户名,硬件登录
p - 密码
“-O /tmp/wa.sh”是远程路由器上的一个文件,其中将保存服务器响应,例如重新启动命令。

注意事项二: 啊啊,为什么我们使用 wget 而不是curl,因为通过curl 你可以不使用GET 而是使用POST 发送https 请求? 啊,因为,正如老笑话中所说的“NE 爬进罐子里!” 例如,curl 包含大小约为 2MB 的加密库,因此您不太可能为小型 TP-LINK ML3020 组装映像。 还有 wget - 请。

2)在服务器端(我有Ubuntu)我们将使用Zabbix。 为什么:我希望它美观(带有图表)且方便(通过上下文菜单发送命令)。 Zabbix有zabbix代理这么奇妙的东西。 通过代理,我们将调用服务器上的 PHP 脚本,该脚本将返回有关我们的路由器是否在要求的时间内注册的信息。 为了存储有关注册时间、设备命令的信息,我使用 MySQL,一个单独的表 users ,大约包含以下字段:

		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 存储库下载: https://github.com/BazDen/iotnet.online.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 web界面,从菜单中选择:
设置 -> 网络节点 -> 创建网络节点。 这里指定网络主机的名称、其组和默认代理接口就足够了:

通过端口 80 远程监控和控制基于 Lunix/OpenWrt/Lede 的设备...

现在我们需要为此网络节点添加一个数据元素。 注意两个字段:“key” - 这正是我们在 /etc/zabbix/zabbix_agentd.conf 文件中写入的参数(在我们的例子中是 test),以及“update Interval” - 我将其设置为 5 分钟,因为设备也每五分钟在服务器上注册一次。

通过端口 80 远程监控和控制基于 Lunix/OpenWrt/Lede 的设备...

好吧,让我们添加一个图表。 我建议选择“填充”作为渲染风格。

通过端口 80 远程监控和控制基于 Lunix/OpenWrt/Lede 的设备...

输出非常简洁,例如:

通过端口 80 远程监控和控制基于 Lunix/OpenWrt/Lede 的设备...

对于合理的问题:“值得吗?”,我会回答:嗯,当然,请参阅文章开头的“创造自行车的原因”。

如果我的第一次写字经历引起了读者的兴趣,那么在接下来的文章中我想描述如何向远程设备发送命令。 我们还成功地为基于 RouterOS (Mikrotik) 的设备实现了整个方案。

来源: habr.com

添加评论