Syed Jahanzaib Personal Blog to Share Knowledge !

May 24, 2016

Mikrotik: Using Firewall Filters to Acquire Wan Data Usage via Email

Filed under: Mikrotik Related — Tags: , , , — Syed Jahanzaib / Pinochio~:) @ 11:32 AM



An Operator [from Amsterdam] wanted to receive email on daily basis for the Daily usage of WAN link on the Mikrotik. Something like Mikrotik should send simple reporting email on daily basis like ‘XXX MB were downloaded Yesterday via WAN link’.


Use following Script. All sections are well explained in comments sections. Make sure you read it carefully line by line, and modify items required.

In this example I used FILTER rules approach to collect the bytes. Surely there are more elegant ways to fetch the data like … Linux base MRTG, NMS like DUDE, above all SNMP  and many others. I just used this method. You may select other as it suites you. This one worked neatly for me 🙂

You can customize it as per your requirements, like multi wan report, monthly report etc.


Mikrotik 6.40.1

  1. Schedule this script to run after 5 (or xx) minutes. When DATE change occurs, it will reset the counter file and filter rules counters.
  2. Create two FILTER rules in Mikrotik as following. SFP1 is the wan interface, so do change it accordingly.
/ip firewall filter
add action=passthrough chain=forward comment=WAN_1_IN in-interface=sfp1
add action=passthrough chain=forward comment=WAN_1_OUT out-interface=sfp1

the Scripts !

first create a supporting script which will actually get previous date day/date.

1-) Script Name: func_shiftDate

# func_shiftDate - add days to date
# Input: date, days
# date - "jan/1/2017"
# days - number
# correct only for years >1918 uncomment for testing
#:local date "jan/01/2100"
#:local days 2560
#:put "$date + $days"
:local mdays {31;28;31;30;31;30;31;31;30;31;30;31}
:local months {"jan"=1;"feb"=2;"mar"=3;"apr"=4;"may"=5;"jun"=6;"jul"=7;"aug"=8;"sep"=9;"oct"=10;"nov"=11;"dec"=12}
:local monthr {"jan";"feb";"mar";"apr";"may";"jun";"jul";"aug";"sep";"oct";"nov";"dec"}

:local dd [:tonum [:pick $date 4 6]]
:local yy [:tonum [:pick $date 7 11]]
:local month [:pick $date 0 3]
:local mm (:$months->$month)
:set dd ($dd+$days)
:local dm [:pick $mdays ($mm-1)]
:if ($mm=2 && (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }
:while ($dd>$dm) do={
 :set dd ($dd-$dm)
 :set mm ($mm+1)
 :if ($mm>12) do={
 :set mm 1
 :set yy ($yy+1)
 :set dm [:pick $mdays ($mm-1)]
 :if ($mm=2 && (($yy&3=0 && ($yy/100*100 != $yy)) || $yy/400*400=$yy) ) do={ :set dm 29 }
:local res "$[:pick $monthr ($mm-1)]/"
:if ($dd<10) do={ :set res ($res."0") }
:set $res "$res$dd/$yy"
:return $res

Now create main script that we will schedule to run every five minutes.

2) wan1-total 

# Script to collect WAN DATA USAGE using Firewall FILTER rules, and send data to admin by Email Daily. (or whenever dates changes)
# And reset the counters on daily basis in night (or when date changes) . it will preserve the data in a file even if the router reboots.
# Syed Jahanzaib / aacable @ hotmail . com
# 1st Made : MAY-2015
# Revision : JAN-2018

# Calling another script which have datefunction
:local shiftDate [:parse [/system script get func_shiftDate source]]
:local DT ([/system clock get date])
:local LASTDAY [$shiftDate date=$DT days=-1]
#:put $LASTDAY

# Set comments for firewall filter rules, change them as required
:local INT 
# Set interface name which we want to monitor
:local INT "6-CIR"
# Make sure you add two firewall rules as showed below so that script can take bytes from it and reset it when date changes.
# Change the interface name accordingly, and make sure to enter the matching comments too.
# /ip firewall filter
#add action=passthrough chain=forward comment=WAN_1_IN in-interface=sfp1
#add action=passthrough chain=forward comment=WAN_1_OUT out-interface=sfp1
:local TOTAL
:local TOTALKB
:local TOTALMB
:local TOTALGB
:local TOTALTB
# Acquire in/out counters from firewall filter rule
:local BYTESOUT [/ip firewall filter get [/ip firewall filter find comment="$WAN1INCOMMENT"] bytes]
:local BYTESIN [/ip firewall filter get [/ip firewall filter find comment="$WAN1OUTCOMMENT"] bytes]

# Setting variables 
:local curDate [/system clock get date]
:local curYear [:pick $curDate 7 13]
:local curMon [ :pick $curDate 0 3 ]
:local curDay [:pick $curDate 4 6]
:local COMPANY "ISP"

# set DATE TIME 
:local date
:local time
:set date [/system clock get date];
:set time [/system clock get time];

# SET GMAIL for sending email, make sure you have configured in /TOOLS,EMAIL option of mikrotik.
:global gmailid
:set gmailid ""
:global gmailsmtp
:set gmailsmtp [:resolve ""];
# Set your GMAIL Account Password
:local gmailpass
# Set your email where you want to receieve the alert 
:local mailsendto1
:set mailsendto1

#Starting Script Functions

:if ([:len [/file find name="counter.txt"]] > 0) do={
#:log warning "Previous Data found, script is not running forthe first time...";
} else {
:log warning "It seems the script is running for the first time. creating necessary files to store counters..";
/file print file=counter.txt where name=counter.txt
/delay delay-time=2;
/file set counter.txt contents="0";
/delay delay-time=2;
/file print file=counterslastupdate.txt where name=counter.txt
/delay delay-time=2;
/file set counterslastupdate.txt contents="0";
/delay delay-time=2;
/file print file=counterslastupdatenormalformat.txt where name=counter.txt
/delay delay-time=2;
/file set counterslastupdatenormalformat.txt contents="0";
/delay delay-time=2;
/file set counterslastupdate.txt contents=$CURRENTDATE
/delay delay-time=2;
/file set counterslastupdatenormalformat.txt contents=$curDate
/delay delay-time=2;

# Setting variables 
:local CURRENTDATE "$curDay$curYear"
:local LASTUPDATEDATE value=[/file get counterslastupdate.txt contents]
:local LASTUPDATEDATENORMAL value=[/file get counterslastupdatenormalformat.txt contents]

# Update counters last update with current date time
/file set counterslastupdate.txt contents=$CURRENTDATE

# Calculate data in MB to be displayed in LOG and email
:set $TOTALKB ($TOTAL / 1024)
:set $TOTALMB ($TOTAL / 1024 / 1024)
:set $TOTALGB ($TOTAL / 1024 / 1024 /1024)
:set $TOTALTB ($TOTAL / 1024 / 1024 /1024 /1024)

if (($TOTAL>1) && ($TOTAL<1000000)) do={
#:log warning "Data is in KB - $TOTAL"
if (($TOTAL>1000000) && ($TOTAL<1000000000)) do={
#:log warning "Data is in MB - $TOTALMB"
if (($TOTAL>1000000000) && ($TOTAL<1000000000000)) do={
#:log warning "data is in GB - $TOTALGB"
if ($TOTAL>1000000000000) do={
#:log warning "data is in TB - $TOTALTB"

#:log info ( "Traffic out = " . $BYTESOUT . " bytes" )
#:log info ( "Traffic in = " . $BYTESIN . " bytes" )
#:log warning ( "TOTAL TRAFFIC = " . $TOTAL. " bytes" )
#:log warning "$TOTVALUEHUMANREADABLE have been downloaded via $INT link on $curDate"

# If date is changed (usually in night) , then send email using GMAIL , with the Data
#:log warning "Date not changed. No need to send email."

} else {
:log warning "DATE changed, sending email for last day data usage and also reset the Firewall Counters ..."
# Set Email Subject
:local shiftDate [:parse [/system script get func_shiftDate source]]
:local DT ([/system clock get date])
:local LASTDAY [$shiftDate date=$DT days=-1]
#:put $LASTDAY

:local es "$LASTDAY - $[/system identity get name] - $TOTALMB MB downloaded via $INT link."
# Set Email Body
:local eb "$[/system identity get name] \n\n$TOTVALUEHUMANREADABLE were downloaded via $INT link on $LASTDAY. \n\n $COMPANY"
# Finally send email 
/tool e-mail send to=$mailsendto1 subject=$es body=$eb start-tls=yes user=$gmailid password=$gmailpass
#/tool e-mail send to=$mailsendto2 subject=$es body=$eb start-tls=yes user=$gmailid password=$gmailpass
# Reset the firewall counters if date change is detected / zaib
/ip firewall filter reset-counters [find comment=$WAN1INCOMMENT ]
/ip firewall filter reset-counters [find comment=$WAN1OUTCOMMENT ]
/file set counter.txt contents="0";


# If current value is bigger then older, then update the counters,
# Helpfule to save counters, when router reboots.

# Get value from stored data for matching
:local before value=[/file get counter.txt contents]

:if ($TOTAL > $before) do={
/file set counter.txt contents=$TOTAL
} else= {
# Else update both values in the file
:set $TOTAL ($TOTAL+$before)
/file set counter.txt contents=$TOTAL

# Update Date time stamp in both files / zaib
/file set counterslastupdate.txt contents=$CURRENTDATE
/file set counterslastupdatenormalformat.txt contents=$curDate

# Regard's
# Syed Jahanzaib

End Results !

wan report





  1. I am using scripts to collect data usage on daily basics but i won’t used counter to reset after 24H

    date = may/23/2016
    Time =  17:41:13
    Uptime = 6d00:00:49
    CPU Load = 7
    WAN 1 = 0   GB WAN 1 RX= 0 MB WAN 1 TX= 0 MB
    WAN 2 = 58   GB WAN 2 RX= 52321 MB WAN 2 TX= 7882 MB
    WAN 3 = 0   GB WAN 3 RX= 0 MB WAN 4 TX= 0 MB
    WAN 4 = 20   GB WAN 4 RX= 18417 MB WAN 4 TX= 2643 MB
    Total RX+TX= 78 GB


    Comment by UmmarHussain — May 24, 2016 @ 11:51 AM

  2. for multiwan?


    Comment by antonio — May 24, 2016 @ 12:10 PM

  3. How did you run script? with scheduler ? which interval ? 24 hours ?


    Comment by Damir — May 24, 2016 @ 2:43 PM

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: