透過連接埠 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) 的裝置實現了整個方案。

來源: www.habr.com

添加評論