Zdalne uruchamianie skryptów Mikrotik z Telegramu

Na tę realizację zmotywował mnie Aleksandr Koryukin GeXoGeN swoją publikacją „Zdalne włączanie komputera za darmo, bez SMS-ów i chmur, za pomocą Mikrotik«.

I komentarz w jednej z grup VKontakte Kirilla Kazakowa:

No tak, całkowicie niebezpieczne. Wolałbym napisać bota telegramowego, który akceptuje polecenia tylko z mojego konta na włączenie.

Postanowiłem napisać takiego bota.

Więc pierwsze, co musisz zrobić, to stworzyć bota w telegramie.

  • Szukamy konta z nazwą @botfather
  • Naciskamy przycisk Start na dole ekranu
  • Następnie piszemy mu polecenie /newbot

Potem odpowiadamy na 2 proste pytania:

  • Pierwsze pytanie – nazwa tworzonego bota MyMikrotikROuter
  • Drugie pytanie – nick tworzonego bota (musi kończyć się na bot) MikrotikROuter_bot

W odpowiedzi otrzymamy token naszego bota, w moim przypadku jest to:

Użyj tego tokena, aby uzyskać dostęp do API HTTP: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Zdalne uruchamianie skryptów Mikrotik z Telegramu
Następnie musisz znaleźć naszego bota w wyszukiwarce po imieniu @MikrotikROuter_bot i nacisnąć przycisk Start.

Po tym musisz otworzyć przeglądarkę i wpisać następujący ciąg:

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

Gdzie XXXXXXXXXXXXXXXXXX – token twojego bota.

Otworzy się strona o mniej więcej takim wyglądzie:

Zdalne uruchamianie skryptów Mikrotik z Telegramu

Na niej szukamy następującego tekstu:

„chat”:{„id”:631290,

A więc mamy wszystkie potrzebne informacje do napisania skryptów dla Mikrotika, a mianowicie:

Token bota: 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

ID czatu, do którego ma pisać: 631290

Dla sprawdzenia możemy zajrzeć przez przeglądarkę:

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

Powinniśmy uzyskać wynik:

Zdalne uruchamianie skryptów Mikrotik z Telegramu

Dla naszego komfortu, od razu dodajmy komendy dla bota:

Szukamy konta z nazwą @botfather
Następnie piszemy mu polecenie /setcommands

  • Zapyta, któremu botowi

Piszę:
@MikrotikROuter_bot

Dodajemy komendy:

  • helloworld< — Wiadomość testowa na czacie 1
  • itsworking — Wiadomość testowa na czacie 2
  • wolmypc — włącz mój komputer

Teraz, jeśli wpiszesz w czacie „/”, powinieneś otrzymać:

Zdalne uruchamianie skryptów Mikrotik z Telegramu

Teraz przechodzimy do MikroTik.

W RouterOS jest konsolowe narzędzie do kopiowania plików przez ftp lub http/https, nazywa się fetch i to właśnie nim będziemy się posługiwać.

Otwieramy terminal i wpisujemy:

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

Zauważ, że w MikroTik potrzebny jest „” do eskalacji znaku „?” w URL.

Powinniśmy uzyskać wynik:

Zdalne uruchamianie skryptów Mikrotik z Telegramu

Teraz przechodzimy do skryptów:

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

skrypt systemowy dodaj nazwę="wolmypc" polityka=odczyt źródło="/narzędzie wol mac=XX:XX:XX:XX:XX:XX interfejs=ifnamer
    /narzędzie pobierz url="https://api.telegram.org/boXXXXXXXXXXXXXXXXXXX?chat_id=631290&text=wol OK" zachowaj-wynik
    =nie"

Nie zapomnij podać poprawnego mac i nazwy interfejsu, a także tokena bota i chat_id.

Teraz trochę wyjaśnię, co one robią:

Skrypt „helloworld” wysyła wiadomość: » Witaj, świecie!» do naszego czatu z botem.
Skrypt „itsworking” wysyła wiadomość: » Test OK, działa !» do naszego czatu z botem.
Te skrypty służą do demonstracji działania.
Skrypt „wolmypc” dodałem jako jedną z możliwych realizacji.
Po wykonaniu skryptu bot napisze na czacie „wol OK”.
W zasadzie można uruchamiać absolutnie każdy skrypt.

Tworzymy zadanie:

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

Czytelny widoknie wiem dlaczego, ale z działającego skryptu nie ogłasza globalnych danych, dodałem skrypt przy uruchamianiu systemu.
Telegram-startup

:opóźnienie 5
:global botID "botXXXXXXXXXXXXXXXXXX" ;   token bota
:global myChatID "xxxxxx" ;                               chat_id
:global startLoc 0;
:global endLoc 0;
:narzędzie pobierz url=("https://api.telegram.org/".$botID."/getUpdates") ;

Telegram

:narzędzie pobierz url=("https://api.telegram.org/".$botID."/getUpdates") ;
:global content [/plik pobierz [/plik znajdź nazwa=getUpdates] zawartość] ;
:global startLoc 0;
:global endLoc 0;

:jeśli ( [/plik pobierz [/plik znajdź nazwa=getUpdates] rozmiar] > 50 ) zrób={

:ustaw startLoc  [:znajdź $content "update_id" $lastEnd ] ;
:ustaw startLoc ( $startLoc + 11 ) ;
:lokalny endLoc [:znajdź $content "," $startLoc] ;
:lokalny messageId ([:wybierz $content $startLoc $endLoc] + (1));
:put [$messageId] ;
#:log info message="updateID $messageId" ;

:ustaw startLoc  [:znajdź $content "text" $lastEnd ] ;
:ustaw startLoc ( $startLoc  + 7 ) ;
:lokalny endLoc [:znajdź $content "," ($startLoc)] ;
:ustaw endLoc ( $endLoc - 1 ) ;
:lokalny message [:wybierz $content ($startLoc + 2) $endLoc] ;
:put [$message] ;
#:log info message="wiadomość $message ";

:ustaw startLoc  [:znajdź $content "chat" $lastEnd ] ;
:ustaw startLoc ( $startLoc + 12 ) ;
:lokalny endLoc [:znajdź $content "," $startLoc] ;
:lokalny chatId ([:wybierz $content $startLoc $endLoc]);
:put [$chatId] ;
#:log info message="chatID $chatId ";

:jeśli (($chatId = $myChatID) i (:put [/system skrypt znajdź nazwa=$message] != "")) zrób={
:system skrypt uruchom $message} inaczaj={:narzędzie pobierz url=("https://api.telegram.org/".$botID."/sendmessage?chat_id=".$chatId."&text=Nie mogę z tobą rozmawiać. ") zachowaj-wynik=nie} ;
:narzędzie pobierz url=("https://api.telegram.org/".$botID."/getUpdates?offset=$messageId") zachowaj-wynik=nie; 
} 

Jak to działa

Pobieramy nasze wiadomości „getUpdates” co 30 sekund, a następnie przetwarzamy, aby dowiedzieć się update_id (numer wiadomości) i text (nasze komendy) i chat_id . Domyślnie getUpdates zwraca od 1 do 100 wiadomości, dla wygody, po odczytaniu komendy, wiadomość usuwamy. W API Telegramu napisano, że aby przeczytać wiadomość, potrzebny jest numer wiadomości + 1.

/getUpdates?offset=update_id + 1

Wszystko przetestowane na Mikrotik rb915 RouterOS 6.37.1
Jeśli wysłać od razu wiele komend, będą one wykonywane po kolei z interwałem 30 sek.

P.S. Ogromne podziękowania dla Kirilla Kazakowa za pomysł i mojemu przyjacielowi Aleksandrowi za pomoc w skryptach.

Linki

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

aktualizacja:

03:11:16

Zaktualizowałem skrypty:

Dodałem sprawdzenie chat_id
Sprawdzenie na durnia, jeśli ktoś napisze do naszego bota, ten odpowie: » Nie mogę z tobą rozmawiać. «, podobnie odpowie nam, jeśli nie rozpozna komendy.
Po wykonaniu komendy bot informuje w czacie (zob. skrypt wolmypc)

UPD

Znaleźliśmy z 7Stuntman7 że plik z powyżej ~ 14 wiadomości przestaje być przetwarzany przez komendę find (ograniczenia Mikrotik). Dlatego w przyszłości przerobię skrypt na lua, dziękuję 7Stuntman7 za to, nie wiedziałem o lua.

AKTUALIZACJA 08.12.2016

W Telegramie najwyraźniej nieco zmienili „wyjście” getUpdate. Teraz w głównym skrypcie trzeba poprawić przesunięcie wiadomości z 2 na 1

zmiany

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

zmienić na :

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

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster