SIGN IN / UP
    opened image

    How to create a telegram bot for monitoring Mikrotik located behind a NAT

    In most cases, home routers are not accessible from the Internet, which makes it impossible to configure and monitor them remotely. Hiding devices behind NAT is a common practice of providers providing home Internet services, due, among other things, to security issues.

     

    In this article, we will consider the issue of monitoring the availability of the Mikrotik router, which is located behind the NAT of your Internet provider.

     

    There are several (in fact, more) ways to solve the issue of monitoring routers or even remotely managing them.:

     

    1. You can purchase a "white IP" service from a provider (public IP address, visible from the Internet). This is probably the easiest and fairly inexpensive way to solve the issue of monitoring and managing your home router, since it will be available on the provided white IP from anywhere on the Internet. This method is suitable for almost all router models, since it does not require additional settings on the router itself. The disadvantage of this solution is that you are responsible for organizing the security of both the router itself and your home network and all devices in it. In addition, not all providers provide a white IP service.

     

    If you already have a white IP, to create a router monitoring using a telegram bot, you can use the instruction: How to create a telegram bot to monitor remote hosts.

     

    2. Organization of your VPN network on a VPS server. The configuration and installed software on the server usually do not matter. In this case, it is enough to install a VPN server on the server (for example, WireGuard), and configure the WireGuard VPN client on Mikrotik (available from the 7th version of RouterOS). After that, the router will become available in the internal network of the VPS server. The method requires additional VPN network settings and the organization of monitoring within this network (for example, with a bash or python script).

     

    3. Provide the ability to periodically leave a "trace" by the router in the form of entries in the log file on the remote server. After that, on the server, analyze these records with a python script (we will use exactly python) to organize the sending of a message to telegrams if Mikrotik did not leave a "trace" in a given period of time.

     

    To implement this method, you need to make minimal settings on the router and place the finished python script on the VPS server. A web server must be running on the VPS server and a website must be hosted or a default website (stub site) created that opens by the server IP.

     

    In our example, a virtual server is used with the CentOS7 operating system and the VestaCP control panel.

    Let's get down to implementation.

     

    1. Setting up Mikrotik

     

    For changes on the router, we will use the standard WinBox program.

     

    1.1 Enable DDNS in case the ISP practices changing the external IP

    IP - Cloud - DDNS Enabled

     

     

    DNS Name - non-changing (unlike external IP) name of your router. Save the value of this field, we will need it for our monitoring script.

     

    Please note that the router itself will indicate that it is behind NAT and connection with it from the outside may not be available.

     

    1.2  Let's create a script in which the router will attempt to send an empty value to the server via http (or https) using the post method.

     

    System - Scripts - Add (+)

    Name: set an arbitrary script name (in Latin)

    Source: write the script

    /tool fetch http-method=post url="https://11.22.33.44/"

     

     

    Where 11.22.33.44 is the IP of the server where the monitoring script will run. Note that the url value can also contain a link to a specific site that is hosted on the same server. This value will determine which log log on the server you need to specify for analysis. Let's consider a variant specifying the IP of the server. In this case, the default site log (or stub site) will be used.

     

    1.3  Let's create a scheduler task to run the newly created script at a certain frequency.

     

    System - Scripts - Add (+)

    Name: set an arbitrary name of the scheduler task (in Latin)

    Interval: set the frequency of script execution (for example, once every 30 seconds)

    On Event: prescribe the launch line of the previously created script

     

    /system script run web_label

     

     

    Now the router will make an attempt to send a post request to the server every 30 seconds, leaving a "trace" about itself in the log on the server.

     

    2. Setting up the server and placing the monitoring script

     

    2.1  Create a stub site in the VestaCP panel using the Instructions.

     

    2.2  Create a telegram bot and a channel for posting notifications by following step 1 from the Instruction, then from the same instruction follow step 2 to prepare the server and step 3 to run the script: but in the main.py file, insert the following script code:

     

    import os
    import socket
    import requests
    import datetime
    import time
    from datetime import timedelta
    #------------------------
    logfile = '/var/log/httpd/domains/site.plug.log';  #log-file  
    hostname = 'f1*********b.sn.mynetname.net'    #RouterOS DDNS (IP - Cloud)
    time_period = 30    #equal to the period of the script run in the scheduler on RouterOS, sec
    time_pause = 60    #seconds, interval for check
    #-----------------------
    def SendMsgToTelegramChanel(msg):
        token="TOKEN"
        chat_id = 'CHAT_ID'
        params = {'chat_id': chat_id,'text': msg}
        response = requests.get('https://api.telegram.org/bot'+token+'/sendMessage', params=params)

    def GetIP(hname):                         #resolv hostname to IP 
        ips = ''
        try:
            ips = str(socket.gethostbyname(hname))
            if ips not in lastips:
                lastips.append(ips)
                print(ips,'was added to previous IPs list')
        except socket.gaierror as e:
            print(hname,'hostname Error')
            pass
        return ips

    def CheckPeriod(lfile, hip, tperiod):
        res = [False,'']
        if os.path.exists(lfile):
            lstr =  os.popen("grep 'Mikrotik' " + lfile + " | tail -1 | awk -F' ' '{print $1,$4}'").read()
            if lstr != '':
                #get ip from log
                logip = lstr.split(' ')[0]
                if (hip != logip):
                    print('Old IP: ' + logip + ', new IP: ' + hip) 
                # get last time from log
                now = datetime.datetime.now().time()
                nowtime = timedelta(hours = now.hour, minutes = now.minute, seconds = now.second)
                lasttime = nowtime
                indx = lstr.find(':') + 1
                if (indx > 0):
                    ctime = lstr[indx:indx+8]
                    ctime = ctime.split(':')   # hour = ctime[0], minutes= ctime[1], secund = ctime[2]
                    lasttime = timedelta(hours = int(ctime[0]), minutes = int(ctime[1]), seconds = int(ctime[2]))
                    res[1] = str(lasttime)
                rtime = nowtime - lasttime

                #check 
                if ((hip == logip) or (hip in lastips)) and (int(rtime.total_seconds()) <= tperiod):
                    res[0] = True

            else:
                res[1] =  'notag'
                print('Mikrotik tag not found in log file')                    
        else:
             print('File not found:',lfile)
        return res

    #-----------------------------------------------------------------------------------
    print(datetime.datetime.now(),'start monitoring:')
    chklabel = False 
    lastips = []       #last IPs

    while True:
        hostip = GetIP(hostname)
        chkperiod =  CheckPeriod(logfile, hostip, time_period)

        if (hostip == '') or (chkperiod[1] == ''):
            break

        if (chkperiod[0] == True and chklabel == True):
            chklabel = False
            SendMsgToTelegramChanel('Mikrotik is UP at ' + chkperiod[1] )
            print(datetime.datetime.now(),' ' + hostname + ' is UP at ' + chkperiod[1] )
        if (chkperiod[0] == False and chklabel == False):
            chklabel = True
            SendMsgToTelegramChanel('Mikrotik is DOWN at ' + chkperiod[1] )
            print(datetime.datetime.now(),' ' + hostname + ' is DOWN at ' + chkperiod[1])    

        time.sleep(time_pause)

     

    Pay attention to the variables in the script:

     

    logfile = '/var/log/httpd/domains/site.plug.log' -  contains the value of the path to the log file of the stub site. It is in this file that the Mikrotik router should leave a record every 30 seconds.

     

    hostname - enter the field value here DNS Name (WinBox - IP -Cloud). 

     

    token и chat_id we get from the previously created corresponding values of the telegram bot.

     

    As a result, you can monitor 24/7 the availability of the Mikrotik router, which is located behind the ISP's NAT.