पोर्ट 80 के माध्यम से Lunix/OpenWrt/Lede आधारित उपकरणों की दूरस्थ निगरानी और नियंत्रण…

सभी को नमस्कार, हेब्रे पर यह मेरा पहला अनुभव है। मैं इस बारे में लिखना चाहता हूं कि किसी बाहरी नेटवर्क पर गैर-मानक तरीके से नेटवर्क उपकरण कैसे प्रबंधित किया जाए। गैर-मानक का क्या मतलब है: ज्यादातर मामलों में, बाहरी नेटवर्क पर उपकरण प्रबंधित करने के लिए आपको निम्न की आवश्यकता होती है:

  • सार्वजनिक आईपी पता. ठीक है, या यदि उपकरण किसी के NAT के पीछे है, तो एक सार्वजनिक आईपी और एक "अग्रेषित" पोर्ट।
  • केंद्रीय नोड तक सुरंग (PPTP/OpenVPN/L2TP+IPSec, आदि) जिसके माध्यम से यह पहुंच योग्य होगा।

इसलिए, आपको "मेरी बाइक" की आवश्यकता होगी जब मानक तरीके आपके अनुरूप नहीं होंगे, उदाहरण के लिए:

  1. उपकरण NAT के पीछे स्थित है और सामान्य http (पोर्ट 80) को छोड़कर, सब कुछ बंद है। बड़े संघीय कॉर्पोरेट नेटवर्क के लिए यह पूरी तरह से सामान्य स्थिति है। वे बंदरगाहों को पंजीकृत कर सकते हैं, लेकिन तुरंत नहीं, जल्दी से नहीं, और आपके लिए नहीं।
  2. अस्थिर और/या "संकीर्ण" संचार चैनल। कम गति, लगातार नुकसान। सुरंग को व्यवस्थित करने का प्रयास करते समय दर्द और निराशा।
  3. एक महँगा संचार चैनल, जहाँ वस्तुतः हर मेगाबाइट मायने रखता है। उदाहरण के लिए, उपग्रह संचार. साथ ही लंबी देरी और एक "संकीर्ण" बैंड।
  4. ऐसी स्थिति जब आपको बड़ी संख्या में छोटे राउटरों को "जुगाड़" करने की आवश्यकता होती है, जिस पर, एक ओर, क्षमताओं का विस्तार करने के लिए OpenWrt/Lede स्थापित होता है, और दूसरी ओर, राउटर के संसाधन (मेमोरी) पर्याप्त नहीं होते हैं प्रत्येक वस्तु के लिए।

संख्या बार नोट करें आपको राउटर के यूएसबी पोर्ट में फ्लैश ड्राइव स्थापित करने और राउटर की मेमोरी का विस्तार करने से क्या रोकता है?

अधिकतर, आवश्यकताएं संपूर्ण समाधान की लागत के लिए होती हैं, लेकिन कभी-कभी फॉर्म फैक्टर भी महत्वपूर्ण भूमिका निभाता है। उदाहरण के लिए, साइट पर एक टीपी-लिंक एमएल3020 है, इसका एकमात्र यूएसबी पोर्ट 2जी/3जी मॉडेम के लिए उपयोग किया जाता है, यह सब कुछ प्रकार के छोटे प्लास्टिक केस में लपेटा जाता है और कहीं ऊंचे, ऊंचे (मस्तूल पर) रखा जाता है। दूर, बहुत दूर (क्षेत्र में, निकटतम मोबाइल ऑपरेटर बेस स्टेशन से 30 किमी)। हां, आप यूएसबी हब प्लग इन कर सकते हैं और पोर्ट की संख्या बढ़ा सकते हैं, लेकिन अनुभव से पता चलता है कि यह बोझिल और अविश्वसनीय है।

इसलिए, मैंने आपको अपनी विशिष्ट स्थिति का वर्णन करने का प्रयास किया: “कहीं दूर, बहुत दूर, लिनक्स पर चलने वाला एक बहुत ही महत्वपूर्ण, अकेला और छोटा राउटर है। दिन में कम से कम एक बार यह जानना महत्वपूर्ण है कि वह "जीवित" है और, यदि आवश्यक हो, तो उसे आदेश भेजे जाते हैं, उदाहरण के लिए, "प्रिय, रिबूट!"

आइए कार्यान्वयन की ओर आगे बढ़ें:

1) राउटर की तरफ, क्रॉन के माध्यम से, हर 5/10/1440 मिनट में, या जब भी आप चाहें, आपको wget का उपयोग करके सर्वर पर एक http अनुरोध भेजना होगा, अनुरोध के परिणाम को एक फ़ाइल में सहेजना होगा, फ़ाइल को निष्पादन योग्य बनाना होगा , और इसे निष्पादित करें।

मेरी क्रॉन लाइन कुछ इस तरह दिखती है:

फ़ाइल /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 मेरे सर्वर का डोमेन है। मुझे तुरंत ध्यान दें: हां, आप सर्वर का एक विशिष्ट आईपी पता निर्दिष्ट कर सकते हैं, हम अपने राज्य तक ऐसा करते थे, संघर्ष के एक धार्मिक आवेग में, मैं कहूंगा, मुझे नहीं पता, शेर की पहुंच को अवरुद्ध कर दिया गया DigitalOcean और Amazon "क्लाउड" का हिस्सा। यदि आप एक प्रतीकात्मक डोमेन का उपयोग करते हैं, यदि ऐसी कोई घटना होती है, तो आप आसानी से एक बैकअप क्लाउड उठा सकते हैं, डोमेन को उस पर रीडायरेक्ट कर सकते हैं और डिवाइस मॉनिटरिंग को पुनर्स्थापित कर सकते हैं।

a.php सर्वर-साइड स्क्रिप्ट का नाम है। हां, मुझे पता है कि वेरिएबल्स और फ़ाइल नामों को एक ही अक्षर से नाम देना गलत है... मेरा सुझाव है कि इस तरह हम अनुरोध भेजते समय कुछ बाइट्स बचाते हैं :)
यू - उपयोगकर्ता नाम, हार्डवेयर लॉगिन
पी - पासवर्ड
"-O /tmp/wa.sh" रिमोट राउटर पर एक फ़ाइल है जहां सर्वर प्रतिक्रिया, उदाहरण के लिए रीबूट कमांड, सहेजी जाएगी।

नोट नंबर दो: आह, हम wget का उपयोग क्यों करते हैं और कर्ल का नहीं, क्योंकि कर्ल के माध्यम से आप https अनुरोध GET के साथ नहीं, बल्कि POST के साथ भेज सकते हैं? आह, क्योंकि, जैसा कि पुराने चुटकुले में है "एनई जार में चढ़ जाता है!" कर्ल में लगभग 2 एमबी आकार की एन्क्रिप्शन लाइब्रेरी शामिल है और इस वजह से यह संभावना नहीं है कि आप उदाहरण के लिए एक छोटे टीपी-लिंक एमएल3020 के लिए एक छवि को इकट्ठा करने में सक्षम होंगे। और wget के साथ - कृपया।

2) सर्वर साइड पर (मेरे पास उबंटू है) हम ज़ैबिक्स का उपयोग करेंगे। क्यों: मैं चाहता हूं कि यह सुंदर हो (ग्राफ़ के साथ) और सुविधाजनक हो (संदर्भ मेनू के माध्यम से आदेश भेजें)। ज़ैबिक्स के पास ज़ैबिक्स एजेंट जैसी अद्भुत चीज़ है। एजेंट के माध्यम से, हम सर्वर पर एक 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 रिपॉजिटरी से यहां डाउनलोड किया जा सकता है: 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();
?>		

खैर, अंतिम चरण: एक एजेंट को पंजीकृत करना और शेड्यूल जोड़ना।

यदि आपने अभी तक ज़ैबिक्स एजेंट स्थापित नहीं किया है, तो:

apt-get install zabbix-agent

फ़ाइल /etc/zabbix/zabbix_agentd.conf संपादित करें.

पंक्ति जोड़ें:

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

, जहां:
परीक्षण हमारे एजेंट का नाम है
"php /usr/share/zabbix/agent.php उपयोगकर्ता पासवर्ड" - डिवाइस पंजीकरण डेटा को इंगित करने वाली एक स्क्रिप्ट।

चार्ट जोड़ना: ज़ैबिक्स वेब इंटरफ़ेस खोलें, मेनू से चुनें:
सेटिंग्स -> नेटवर्क नोड्स -> एक नेटवर्क नोड बनाएं। यहां नेटवर्क होस्ट, उसके समूह और डिफ़ॉल्ट एजेंट इंटरफ़ेस का नाम निर्दिष्ट करना पर्याप्त है:

पोर्ट 80 के माध्यम से Lunix/OpenWrt/Lede आधारित उपकरणों की दूरस्थ निगरानी और नियंत्रण…

अब हमें इस नेटवर्क नोड के लिए एक डेटा तत्व जोड़ने की जरूरत है। दो फ़ील्ड पर ध्यान दें: "कुंजी" - यह बिल्कुल वही पैरामीटर है जो हमने /etc/zabbix/zabbix_agentd.conf फ़ाइल में लिखा था (हमारे मामले में यह परीक्षण है), और "अपडेट अंतराल" - मैंने इसे 5 मिनट पर सेट किया है , क्योंकि उपकरण भी हर पांच मिनट में एक बार सर्वर पर पंजीकृत होता है।

पोर्ट 80 के माध्यम से Lunix/OpenWrt/Lede आधारित उपकरणों की दूरस्थ निगरानी और नियंत्रण…

खैर, चलिए एक ग्राफ जोड़ते हैं। मैं रेंडरिंग शैली के रूप में "भरें" चुनने की अनुशंसा करता हूं।

पोर्ट 80 के माध्यम से Lunix/OpenWrt/Lede आधारित उपकरणों की दूरस्थ निगरानी और नियंत्रण…

आउटपुट कुछ बहुत संक्षिप्त है, उदाहरण के लिए इस तरह:

पोर्ट 80 के माध्यम से Lunix/OpenWrt/Lede आधारित उपकरणों की दूरस्थ निगरानी और नियंत्रण…

उचित प्रश्न के लिए: "क्या यह इसके लायक था?", मैं उत्तर दूंगा: ठीक है, निश्चित रूप से, लेख की शुरुआत में "साइकिल बनाने के कारण" देखें।

यदि मेरा पहला ग्राफोमेनियाक अनुभव पाठकों की रुचि जगाता है, तो निम्नलिखित लेखों में मैं यह बताना चाहता हूं कि दूरस्थ उपकरणों को कमांड कैसे भेजें। हम राउटरओएस (मिकरोटिक) पर आधारित उपकरणों के लिए पूरी योजना को लागू करने में भी कामयाब रहे।

स्रोत: www.habr.com

एक टिप्पणी जोड़ें