Activation à distance des scripts Mikrotik depuis Telegram

Cette réalisation a été inspirée par Alexandre Korioukin GeXoGeN dans sa publication «Activation à distance gratuite de l'ordinateur, sans SMS ni cloud, avec Mikrotik«.

Et un commentaire dans l'un des groupes VK de Kirill Kazakov :

Oui, vraiment pas sécurisé. Je préfèrerais écrire un bot Telegram qui n'accepte que les commandes de mon compte pour l'activation.

J'ai décidé d'écrire un tel bot.

Alors, la première chose à faire est de créer un bot dans Telegram.

  • Nous cherchons dans la recherche le compte nommé @botfather
  • Nous cliquons sur le bouton Démarrer en bas de l'écran
  • Ensuite, nous lui écrivons la commande /newbot

Puis nous répondons à 2 questions simples :

  • La première question – le nom du bot à créer MyMikrotikROuter
  • La deuxième question – le pseudo du bot à créer (doit se terminer par bot) MikrotikROuter_bot

En réponse, nous obtiendrons le token de notre bot, dans mon cas c'est :

Utilisez ce token pour accéder à l'API HTTP : 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

Activation à distance des scripts Mikrotik depuis Telegram
Ensuite, nous devons chercher notre bot par son nom @MikrotikROuter_bot et cliquer sur le bouton Démarrer.

Après cela, ouvrez le navigateur et saisissez la ligne suivante :

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

Où XXXXXXXXXXXXXXXXXX est le token de votre bot.

Une page s'ouvrira ressemblant à ceci :

Activation à distance des scripts Mikrotik depuis Telegram

Nous trouvons le texte suivant :

«chat»:{«id»:631290,

Alors, nous avons toutes les informations nécessaires pour écrire des scripts pour Mikrotik, à savoir :

Token du bot : 265373548:AAFyGCqJCei9mvcxvXOWBfnjSt1p3sX1XH4

ID du chat où il doit écrire : 631290

Pour vérifier, nous pouvons y accéder via le navigateur :

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

Nous devrions obtenir un résultat :

Activation à distance des scripts Mikrotik depuis Telegram

Pour notre commodité, ajoutons immédiatement des commandes pour le bot :

Nous trouvons le compte avec le nom @botfather
Puis nous lui écrivons la commande /setcommands

  • Il demandera à quel bot

Nous écrivons :
@MikrotikROuter_bot

Ajoutons des commandes :

  • helloworld< — Message test sur le chat 1
  • itsworking — Message test sur le chat 2
  • wolmypc — réveiller mon PC

Maintenant, si nous tapons dans le chat «/», nous devrions recevoir :

Activation à distance des scripts Mikrotik depuis Telegram

Maintenant, passons à MikroTik.

Dans RouterOS, il existe un utilitaire en ligne de commande pour copier des fichiers via ftp ou http/https, cet utilitaire s'appelle fetch, et c'est celui-ci que nous allons utiliser.

Ouvrons terminal et saisissons :

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

Notez que dans MikroTik, un «» est nécessaire pour échapper le signe «?» dans l'URL.

Nous devrions obtenir un résultat :

Activation à distance des scripts Mikrotik depuis Telegram

Maintenant, passons aux 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, ça fonctionne " keep-result=no}

wolmypc

script système ajouter nom="wolmypc" politique=lecture source="/outil wol mac=XX:XX:XX:XX:XX:XX interface=ifnamer
    n/outil fetch url="https://api.telegram.org/boXXXXXXXXXXXXXXXXXXX?chat_id=631290&text=wol OK" garder-résultat=no"

N'oubliez pas d'indiquer le bon mac et le nom de l'interface, ainsi que le bot-token et chat_id.

Je vais maintenant expliquer ce qu'ils font :

Le script «helloworld» envoie le message : » Bonjour, le monde ! » dans notre chat avec le bot.
Le script «itsworking» envoie le message : » Test OK, ça fonctionne ! » dans notre chat avec le bot.
Ces scripts servent à démontrer le fonctionnement.
Le script «wolmypc» a été ajouté comme l'une des implémentations possibles.
Après l'exécution du script, le bot écrira dans le chat «wol OK».
Essentiellement, on peut exécuter n'importe quel script.

Créons une tâche :

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

Vue lisibleOn ne sait pas pourquoi mais le script opérationnel ne divulgue pas les données globales, j'ai ajouté un script lors du chargement du système.
Telegram-démarrage

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

Telegram

:outil 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={:outil fetch url=("https://api.telegram.org/".$botID."/sendmessage?chat_id=".$chatId."&text=Je ne peux pas parler avec vous. ") garder-résultat=no} ;
:outil fetch url=("https://api.telegram.org/".$botID."/getUpdates?offset=$messageId") garder-résultat=no;
} 

Comment cela fonctionne

Nous téléchargeons nos messages «getUpdates» toutes les 30 secondes, puis nous les analysons pour savoir update_id (numéro de message) et text (nos commandes) et chat_id . Par défaut, getUpdates affiche de 1 à 100 messages, pour plus de commodité, après avoir lu la commande, nous supprimons le message. Dans l'API Telegram, il est indiqué que pour lire un message, il faut le numéro de message + 1.

/getUpdates?offset=update_id + 1

Tout a été vérifié sur Mikrotik rb915 RouterOS 6.37.1.
Si plusieurs commandes sont envoyées en même temps, elles seront exécutées l'une après l'autre avec un intervalle de 30 secondes.

P.S. Un grand merci à Kirill Kazakov pour l'idée et à mon ami Alexander pour son aide avec les scripts.

Liens

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

J'ai amélioré les scripts :

Ajouté une vérification pour chat_id
Vérification de l'utilisateur, si quelqu'un écrit à notre bot, il lui répondra : » Je ne peux pas parler avec vous. «, il répondra de la même manière si la commande n'est pas reconnue.
À l'exécution de la commande, le bot envoie un message dans le chat (voir le script wolmypc)

MAJ

Nous avons trouvé avec 7Stuntman7 que le fichier contenant environ 14 messages cesse d’être traité par la commande find (limitations de Mikrotik). Par conséquent, je vais retravailler le script sur lua à l'avenir, merci 7Stuntman7 pour cela, je ne connaissais pas lua.

UPD 08.12.2016

dans Telegram, il semble qu'ils aient légèrement modifié la sortie de getUpdate. Maintenant, dans le script principal, il faut corriger le décalage du message de 2 à 1

modifications

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

remplacer par :

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

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster