Afstandsbediening van Mikrotik-scripts vanuit Telegram

Deze implementatie werd me aangereikt door Alexander Koryukin GeXoGeN met zijn publicatie «Afstandsbediening van de computer gratis, zonder SMS en zonder cloud, met behulp van Mikrotik«.

En een opmerking in een van de VK-groepen van Kirill Kazakov:

Ja, dat is echt niet veilig. Ik zou liever een Telegram-bot schrijven die alleen commando's van mijn account accepteert voor inschakeling.

Ik besloot zo'n bot te schrijven.

Dus, het eerste wat je moet doen – is een bot creëren in Telegram.

  • Zoek naar het account met de naam @botfather
  • Klik op de knop Start onderaan het scherm
  • Daarna typ je het commando /newbot

Vervolgens beantwoorden we 2 eenvoudige vragen:

  • De eerste vraag – de naam van de te creëren bot MyMikrotikROuter
  • De tweede vraag – de gebruikersnaam van de te creëren bot (moet eindigen op bot) MikrotikROuter_bot

Als antwoord krijgen we de token van onze bot, in mijn geval is dit:

Gebruik deze token om toegang te krijgen tot de HTTP API: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Afstandsbediening van Mikrotik-scripts vanuit Telegram
Zoek vervolgens onze bot op met de naam @MikrotikROuter_boten klik op de knop Start.

Daarna moet je de browser openen en de volgende regel invoeren:

 https://api.telegram.org/botXXXXXXXXXXXXXXXXXX/getUpdates

Waarbij XXXXXXXXXXXXXXXXXX – jouw bot-token is.

Een pagina zal ongeveer als volgt openen:

Afstandsbediening van Mikrotik-scripts vanuit Telegram

Zoek naar de volgende tekst:

«chat»:{«id»:631290,

Dus, we hebben alle benodigde informatie om scripts voor Mikrotik te schrijven, namelijk:

Token van de bot: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

ID van de chat, waar deze naar moet schrijven: 631290

Ter controle kunnen we via de browser gaan:

https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=test

We zouden resultaat moeten krijgen:

Afstandsbediening van Mikrotik-scripts vanuit Telegram

Voor ons gemak voegen we meteen commando's toe voor de bot:

Zoek naar het account met de naam @botfather
Daarna geven we hem het commando /setcommands

  • Hij zal vragen om welke bot

We schrijven:
@MikrotikROuter_bot

Voeg de volgende commando's toe:

  • helloworld< — Testbericht op chat 1
  • itsworking — Testbericht op chat 2
  • wolmypc — zet mijn PC aan

Nu, als we «/» in de chat invoeren, zouden we moeten krijgen:

Afstandsbediening van Mikrotik-scripts vanuit Telegram

Nu gaan we verder met MikroTik.

In RouterOS is er een console-tool voor het kopiëren van bestanden via ftp of http/https, de tool heet fetch, die gaan we gebruiken.

Open terminal en voer in:

/tool fetch url="https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=test " keep-result=no

Let op, in MikroTik is een «» nodig om het teken «?» in de URL te escapen.

We zouden resultaat moeten krijgen:

Afstandsbediening van Mikrotik-scripts vanuit Telegram

Nu gaan we verder met de scripts:

helloworld

system script add name="helloworld" policy=read source={/tool fetch url="https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=Hello,world! " keep-result=no}

itsworking

system script add name="itsworking" policy=read source={/tool fetch url="https://api.telegram.org/bot265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4/sendmessage?chat_id=631290&text=Test OK, it's Working " keep-result=no}

wolmypc

system script add name="wolmypc" policy=read source="/tool wol mac=XX:XX:XX:XX:XX:XX interface=ifnamer
    n/tool fetch url="https://api.telegram.org/boXXXXXXXXXXXXXXXXXXX?chat_id=631290&text=wol OK" keep-result=no"

Vergeet niet het juiste mac-adres en interface-naam op te geven, evenals de bot-token en chat_id.

Laat me nu kort uitleggen wat ze doen:

Het script "helloworld" verstuurt een bericht: "Hello, world!" naar onze chat met de bot.
Het script "itsworking" verstuurt een bericht: "Test OK, het werkt!" naar onze chat met de bot.
Deze scripts dienen ter demonstratie.
Ik heb het script "wolmypc" toegevoegd als een van de mogelijke implementaties.
Na het uitvoeren van het script zal de bot in de chat "wol OK" schrijven.
In principe kun je absoluut elk script uitvoeren.

We maken een taak aan:

Telegram.src

/system scheduler
add interval=30s name=Telegram on-event=":tool fetch url=("https://api.telegr
    am.org/".$botID."/getUpdates") ;r
    n:global content [/file get [/file find name=getUpdates] contents] ;r
    n:global startLoc 0;r
    n:global endLoc 0;r
    nr
    n:if ( [/file get [/file find name=getUpdates] size] > 50 ) do={r
    nr
    n:set startLoc  [:find $content "update_id" $lastEnd ] ;r
    n:set startLoc ( $startLoc + 11 ) ;r
    n:local endLoc [:find $content "," $startLoc] ;r
    n:local messageId ([:pick $content $startLoc $endLoc] + (1));r
    n:put [$messageId] ;r
    n:#log info message="updateID $messageId" ;r
    nr
    n:set startLoc  [:find $content "text" $lastEnd ] ;r
    n:set startLoc ( $startLoc  + 7 ) ;r
    n:local endLoc [:find $content "," ($startLoc)] ;r
    n:set endLoc ( $endLoc - 1 ) ;r
    n:local message [:pick $content ($startLoc + 2) $endLoc] ;r
    n:put [$message] ;r
    n:#log info message="message $message ";r
    nr
    n:set startLoc  [:find $content "chat" $lastEnd ] ;r
    n:set startLoc ( $startLoc + 12 ) ;r
    n:local endLoc [:find $content "," $startLoc] ;r
    n:local chatId ([:pick $content $startLoc $endLoc]);r
    n:put [$chatId] ;r
    n:#log info message="chatID $chatId ";r
    nr
    n:if (($chatId = $myChatID) and (:put [/system script find name=$messa
    ge] != "")) do={r
    n:system script run $message} else={:tool fetch url=("https://api.teleg
    ram.org/".$botID."/sendmessage?chat_id=".$chatId."&text=I can't t
    alk with you. ") keep-result=no} ;r
    n:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates?
    offset=$messageId") keep-result=no; r
    n} r
    n" policy=
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon 
    start-date=nov/02/2010 start-time=00:00:00
	
add name=Telegram-startup on-event=":delay 5r
    n:global botID "botXXXXXXXXXXXXXXXXXX" ;r
    n:global myChatID "631290" ;r
    n:global startLoc 0;r
    n:global endLoc 0;r
    n:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") 
    ;" policy=
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon 
    start-time=startup

Leesbare weergaveHet is onduidelijk waarom, maar het werkende script geeft geen globale gegevens vrij, ik heb het script toegevoegd bij het opstarten van het systeem.
Telegram-startup

:delay 5
:global botID "botXXXXXXXXXXXXXXXXXX" ;   token bot
:global myChatID "xxxxxx" ;                               chat_id
:global startLoc 0;
:global endLoc 0;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;

Telegram

:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates") ;
:global content [/file get [/file find name=getUpdates] contents] ;
:global startLoc 0;
:global endLoc 0;

:if ( [/file get [/file find name=getUpdates] size] > 50 ) do={

:set startLoc  [:find $content "update_id" $lastEnd ] ;
:set startLoc ( $startLoc + 11 ) ;
:local endLoc [:find $content "," $startLoc] ;
:local messageId ([:pick $content $startLoc $endLoc] + (1));
:put [$messageId] ;
#:log info message="updateID $messageId" ;

:set startLoc  [:find $content "text" $lastEnd ] ;
:set startLoc ( $startLoc  + 7 ) ;
:local endLoc [:find $content "," ($startLoc)] ;
:set endLoc ( $endLoc - 1 ) ;
:local message [:pick $content ($startLoc + 2) $endLoc] ;
:put [$message] ;
#:log info message="message $message ";

:set startLoc  [:find $content "chat" $lastEnd ] ;
:set startLoc ( $startLoc + 12 ) ;
:local endLoc [:find $content "," $startLoc] ;
:local chatId ([:pick $content $startLoc $endLoc]);
:put [$chatId] ;
#:log info message="chatID $chatId ";

:if (($chatId = $myChatID) and (:put [/system script find name=$message] != "")) do={
:system script run $message} else={:tool fetch url=("https://api.telegram.org/".$botID."/sendmessage?chat_id=".$chatId."&text=Ik kan niet met je praten.") keep-result=no} ;
:tool fetch url=("https://api.telegram.org/".$botID."/getUpdates?offset=$messageId") keep-result=no; 
} 

Hoe het werkt

We downloaden onze berichten "getUpdates" iedere 30 seconden en parseren dan om te weten update_id (berichtnummer) en text (onze commando's) en chat_id . Standaard geeft getUpdates 1 tot 100 berichten weer; om het gemakkelijker te maken, verwijderen we het bericht eenmaal gelezen. In de Telegram API staat dat om een bericht te lezen, je het berichtnummer + 1 nodig hebt.

/getUpdates?offset=update_id + 1

Alles is getest op Mikrotik rb915 RouterOS 6.37.1
Als je veel opdrachten tegelijk verstuurt, worden ze allemaal na elkaar uitgevoerd met een interval van 30 seconden.

P.S. Een grote dank aan Kirill Kazakov voor het idee en mijn vriend Alexander voor de hulp met de scripts.

Links

habrahabr.ru/post/313794
1spla.ru/index.php/blog/telegram_bot_for_mikrotik
core.telegram.org/bots/api
wiki.mikrotik.com/wiki/Manual:Scripting

upd:

03:11:16

Scripts aangepast:

Controle op chat_id toegevoegd
Een controle om te voorkomen dat iemand met onze bot communiceert, hij antwoordt: » Ik kan niet met jou praten. «, hij zal ook ons antwoorden als hij de opdracht niet herkent.
Na het uitvoeren van de opdracht, rapporteert de bot in de chat (zie script wolmypc)

UPD

We hebben gevonden met 7Stuntman7 dat een bestand met meer dan ~ 14 berichten stopt met reageren op de opdracht find (beperkingen Mikrotik). Daarom zal ik het script in de toekomst herschrijven naar lua, bedankt 7Stuntman7 daarvoor, ik wist niets over lua.

UPD 08.12.2016

in Telegram is blijkbaar een beetje veranderd hoe getUpdate werkt. nu moet in het hoofdschema de offset van het bericht van 2 naar 1 worden aangepast

wijzigingen

:local message [:pick $content ($startLoc + 2) $endLoc] ;

vervangen door :

:local message [:pick $content ($startLoc + 1) $endLoc] ;

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster