Add a VLAN to each ethernet interface in Mikrotik

by Jim Bouse 24. October 2019 07:46

I needed to add a VLAN to each interface on a large number of Mikrotik switches.  This is the script I worked up:

/interface bridge add name=Management disabled=no; 
:foreach i in=[/interface ethernet find] do={ 
  :local ifname [/interface get $i default-name]; 
  /interface vlan add interface=$i vlan-id=100 name=($ifname.".0100") disabled=no; 
  /interface bridge port add bridge=Management interface=($ifname.".0100") disabled=no; 


Mikrotik | WISP


Mikrotik Nightly Usage E-mail Script

by Jim Bouse 7. December 2017 08:12

One of my buddies asked for a script that would e-mail him the usage from his Mikrotik users.

I whipped this up to help him take care of it.

It assumes that you have simple queues for each user.

# Nightly E-mail Usage - Jim Bouse - Brazos WiFi - 2017-12-7

:local identity [/system identity get name];
:local email "asdf@asdf.com";
:local subject "Usage Report - $identity";
:local body "";

:put "Starting E-mail Usage Script";

:foreach queue in=[/queue simple find] do={
  :local bytes [/queue simple get $queue bytes];
  :local target [/queue simple get $queue target];
  :local name [/queue simple get $queue name];
  :local ul [:pick $bytes 0 [:find $bytes "/"]];
  :local dl [:pick $bytes ([:find $bytes "/"]+1) [:len $bytes] ];

  # Divide bytes by 1000 to get kB
  :set ul ($ul/1000);
  :set dl ($dl/1000);

  # Divide kB by 1000 to get MB
  :set ul ($ul/1000);
  :set dl ($dl/1000);

  :local line "$target - $name - $dl/$ul\n";
  :set body "$line$body";

  /queue simple reset-counters $queue;
:put "Sending e-mail";
/tool e-mail send to=$email subject=$subject body=$body;
:put "Sent e-mail";


Edit this text file to include your e-mail instead of asdf@asdf.com.  Then paste the whole TXT file contents into a terminal window for your Mikrotik.  It will create the script and set it to send daily at 11:50PM.

Nightly E-mail Usage.txt (1.46 kb)




Create Lots of VLANs on a Mikrotik Port

by Jim Bouse 29. May 2017 11:53

We have been switching to the UBNT EP-S16 on our towers instead of running cables down to the router at the bottom.  To segment things, you need to use VLANs.

This code snippet will create 16 VLANs on Port 3 of a Mikrotik with VLAN IDs of 1001-1016.

:for x from=1001 to=1016 do={/interface vlan add interface=ether3 vlan-id="$x" name="ether3.$x"}


Mikrotik | WISP


Mikrotik Workplace VPN Logging

by Jim Bouse 8. September 2014 10:41

I recently had a customer of my WISP ask if we could give her a way to log when her employees are working remotely.  She doesn't have a huge infrastructure with sophisticated logging abilities.  She felt that her employees were claiming to work when they really weren't even logged in.


This is a two part script.  One part runs on the Mikrotik, the other as a PHP script running on their server in the office.

Part 1(a) "create a script called 'vpn-log' on the Mikrotik":

:local urlRoot "";

:foreach i in=[/interface find where type="pptp-in"] do={ 
  :local pptpName [/interface get $i name];
  :local userName [:pick $pptpName ([:find $pptpName "-"]+1) [:find $pptpName ">"]];
  set urlRoot ($urlRoot.$userName.",");
/tool fetch url="$urlRoot" keep-result=no

Part 1(b) "create the schedule":

/system scheduler add interval=1m name="Run vpn-log" on-event="/system script run vpn-log" \
    ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive,api \

Part 2 "create the PHP file":


$string_data = file_get_contents("current_users_DONT_DELETE.txt");
$currentUsers = unserialize($string_data);

$userArr = explode(",", $_GET['users']);
file_put_contents("current_users_DONT_DELETE.txt", serialize($userArr));

foreach ($currentUsers as $currentUser) {
	if ($currentUser !== "") {
		if (!file_exists($currentUser)) {
			mkdir($currentUser, 0777, true);
		if (!in_array($currentUser, $userArr)) {
			file_put_contents($currentUser."/".date("Y-m-d").".txt", $currentUser . " - Log Out ".date('h:i A')."\r\n", FILE_APPEND);
			echo $currentUser . " - Log Out ".date('h:i A')."<BR>";

foreach ($userArr as $user) {
	if ($user !== "") {
		if (!file_exists($user)) {
			mkdir($user, 0777, true);
		if (!in_array($user, $currentUsers)) {
			file_put_contents($user."/".date("Y-m-d").".txt", $user . " - Log In ".date('h:i A')."\r\n", FILE_APPEND);
			echo $user . " - Log In ".date('h:i A')."\n";

Note: This only shows when people log in/out of the VPN.  It has no way to know if they actually worked.  Additionally the PHP script needs write access to the directory it is in.


Mikrotik | PHP | WISP


FreshBooks and Mikrotik Automatic Non-Payment Script

by Jim Bouse 9. October 2012 11:12

I have a WISP that has more customers that I would like to keep up with.  Most of the time is spent chasing down late payments.

I wrote the following combination of files to handle automating handling of Non-Payment customers.


  • Web server on a public IP address.
  • Domain Name.
  • FreshBooks account.
  • Simple Queue with a name EXACTLY matching the Last Name, First Name of the customer from FreshBooks.
  • Mikrotik Router with API access enabled.


  • In the Readme.txt



Zip File (v1.0)

From the Readme.txt:

Mikrotik Freshbooks Intergration Script v1.0

Jim Bouse
October 9, 2012

License: None... Feel free to use, modify, butcher, whatever, this code. I ask that if you add features, you send me a copy.

Plug: I own and operate an WISP that uses Ubiquiti and Mikrotik equipment. I also do consulting work and onsite assistance.


I needed to automatically block customers with overdue invoices. This is what I came up with.


config.php <-- all PHP variables set here
create_callback.php <-- creates callbacks on FreshBooks.com
email.php <-- queries FreshBooks for customers matching names in Simple Queues
index.php <-- responds to callback requests from FreshBooks.com
AND is the page the customer is redirected to on non-payment.
Readme.txt <-- This file.
routeros_api.class.php <-- API class downloaded from http://wiki.mikrotik.com/wiki/API_PHP_class


1. Setup a sub-domain for your files to reside on. (http://payments.example.com)
Place all files from zip there.

2. (OPTIONAL) Enable port 800 on web server.
This is needed if you don't have a dedicated IP for your payment server.
Also edit the PaymentServerPort to match in the Mikrotik Script at the bottom.

3. Setup the web server to redirect all 404 errors to index.php

4. Verify that the webserver can write to the directory of these files.
This is used for logging.

5. Modify config.php to match your environment.

6. Add the "Late Payment Fees" add-on in FreshBooks

7. Modify the default behavior of the late payment email to send a notice on day 20
and another notice on day 30. (FreshBooks ->Settings -> Emails)

8. Use create_callback.php to create the following Invoice "Past Due 2" and "Payment Create"

9. Run The script at the bottom on each of your Mikrotiks

Currently, the index.php script only responds to:


You can use the existing code as an example to create more.
Reminder: If you add new features, please send me the code so I can update the files for others.


Mikrotik Script:

:global PaymentServerIP "XXX.XXX.XXX.XXX"
:global PaymentServerPort "80"

/ip firewall nat add action=dst-nat chain=dstnat comment="Redirect Non-Payment HTTP"\
port=80 protocol=tcp src-address-list=NonPayment to-addresses=$PaymentServerIP\
/ip firewall filter add chain=forward comment="Allow Non-Payment HTTPS to FreshBooks"\
dst-port=443 protocol=tcp src-address-list=NonPayment
/ip firewall filter add chain=forward comment="Allow Non-Payment HTTP to Payment Server"\
dst-address=$PaymentServerIP port=800 protocol=tcp src-address-list=NonPayment
/ip firewall filter add chain=forward comment="Allow DNS" port=53 protocol=udp
/ip firewall filter add chain=forward comment="Allow DNS" port=53 protocol=tcp
/ip firewall filter add action=drop chain=forward comment="Drop Non-Payment tcp traffic"\
protocol=tcp src-address-list=NonPayment
/ip firewall filter add action=drop chain=forward comment="Drop Non-Payment udp traffic"\
protocol=udp src-address-list=NonPayment
:put "Done"

FreshBooks-And-Mikrotik-Automatic-Non-Payment-Scripts-v1.0.zip (26.49 kb)

Tags: , , ,

FreshBooks | Mikrotik | WISP


Set Simple Queue Burst Rates

by Jim Bouse 30. September 2012 19:56

I have a Mikrotik router as my bandwidth limiter for my ISP.  I use Simple Queues for each IP to assign them to a speed.  I recently decided to be nice and add bursting to the plans.  I decided that the customers would get 2X their purchased speed for 16 seconds (a standard time window).  Since I had about 100 IPs and Simple Queues, I defanately did not want to manually add bursting to my Simple Queues.  I wrote the following script.  It will loop through all your simple queues and add the 2X burst amount.

You can download the .txt here in case the formatting gets screwed up. - setSimpleQueueBurst.txt (1.46 kb)

:local rate
:local inboundrate
:local outboundrate
:local inboundburstrate
:local outboundburstrate
:local inboundburstthreshold
:local outboundburstthreshold
:local ip
/queue simple
:foreach i in=[find] do={
  :set ip [get $i target-addresses]
  :set rate [get $i max-limit]
  :set inboundrate [:pick $rate ([:find $rate "/"]+1) 999 ]
  :if ([:find [:tostr $inboundrate] "k" ] > 0) do={
    :set inboundrate ([:pick $inboundrate 0 [:find [:tostr $inboundrate] "k" ]]*1000)
  :if ([:find [:tostr $inboundrate] "M" ] > 0) do={
    :set inboundrate ([:pick $inboundrate 0 [:find [:tostr $inboundrate] "M" ]]*1000000)
  :set outboundrate [:pick $rate 0 ([:find $rate "/"]+1)]
  :if ([:find [:tostr $outboundrate] "k" ] > 0) do={
    :set outboundrate ([:pick $outboundrate 0 [:find [:tostr $outboundrate] "k" ]]*1000)
  :if ([:find [:tostr $outboundrate] "M" ] > 0) do={
    :set outboundrate ([:pick $outboundrate 0 [:find [:tostr $outboundrate] "M" ]]*1000000)
  :set inboundburstrate ($inboundrate*2)
  :set outboundburstrate ($outboundrate*2)
  :set outboundburstthreshold ($outboundrate*2)
  :set inboundburstthreshold ($inboundrate*2)
  :set inboundrate ($inboundrate/5)
  :set outboundrate ($outboundrate/5)
  set $i limit-at="$outboundrate/$inboundrate" burst-time="16s/16s" burst-threshold="$outboundburstthreshold/$inboundburstthreshold" burst-limit="$outboundburstrate/$inboundburstrate"
  :put "Set $ip simple queue burst."

Tags: , ,

Mikrotik | WISP


Low Cost Outdoor UPS

by Jim Bouse 30. July 2012 16:24

I own a small WISP and need an UPS in a small enclosure at the bottom of my towers to provide temporary power for when the grid drops for a few minutes/hours.

This is often coupled with a multi-port POE injector from Wifi-Soft and a router for a WISP tower location.

This comes to $387 for an outdoor UPS with a run time of about 8 hours without power for 2 - 8 watt radios and a RouterBoard.

Here is a similar version of what I have described.

Tags: , , , , ,

Mikrotik | Ubiquiti | WISP


Mikrotik Simple Queue Script

by Jim Bouse 24. February 2012 11:48

I needed to be able to create simple queues for the /27 I got from my upstream provider.  I wanted to do this with a script instead of typing by hand and perhaps creating a typo.

  • /queue simple add name="Purchased Bandwith" max-limit=10M/10M
  • :for x from=130 to=158 do={/queue simple add name="216.xxx.70.$x" target-addresses="216.xxx.70.$x" parent="Purchased Bandwith" max-limit=384k/1M }



Powered by BlogEngine.NET
Original Design by Laptop Geek, Adapted by onesoft