Mikrotik:Snippets

From My notepad
Jump to: navigation, search

Contents

Add all ip addresses assigned to interfaces to an address list

:foreach i in=[/ip address find] do={
   :local address [ip address get $i address]
   :set address [:pick $address 0 [:find $address "/"]]
   /ip firewall address-list add list=link-local-ip-addresses address=$address
}

:foreach i in=[/ip address find] do={
   :local address [ip address get $i address]
   /ip firewall address-list add list=allowed-management address=$address comment="link local"
}

Easily create bridge with admin-mac

Pick the one that matches the interface you want to use for the admin-mac:

/interface bridge add name=bridge-lan disabled=no admin-mac=[/interface ethernet get ether1 mac-address]
/interface bridge add name=bridge-lan disabled=no admin-mac=[/interface ethernet get ether2 mac-address]
/interface bridge add name=bridge-lan disabled=no admin-mac=[/interface ethernet get ether3 mac-address]
/interface bridge add name=bridge-lan disabled=no admin-mac=[/interface ethernet get ether4 mac-address]
/interface bridge add name=bridge-lan disabled=no admin-mac=[/interface ethernet get ether5 mac-address]
/interface bridge add name=bridge-lan disabled=no admin-mac=[/interface ethernet get wlan mac-address]

Printing a variable to the log

:local myVar "hello"
:log info ("$myVar")

Get list of routes using a specific gateway

:foreach i in=[/ip route find where gateway=10.77.0.78] do={:put [/ip route get $i dst-address ]}

Firewall Connections

This is how you find connections in the connection tracking table:

:put [/ip firewall connection find where dst-address~"8.8.8.8"]
:put [/ip firewall connection find where dst-address~":80"]

:put [/ip firewall connection find where src-address~"192.168.1.101"]
:put [/ip firewall connection find where src-address~"192.168.1.101:80"]

Here is a script to clear IAX2 connections from the connection table:

:local pbx "192.168.1.253"

:foreach i in=[/ip firewall connection find src-address~"$pbx:4569"] do={
   :log warning ("clear-iax-connections: clearing connection src-address:$pbx:4569 dst-address:$[/ip firewall connection get $i dst-address]")
   /ip firewall connection remove $i
}

Dynamically updating address lists

Set the comment if each list item you want to update to "resolve:fqdn" and then schedule the following script to run on an interval:

:foreach i in=[/ip firewall address-list find where comment~"resolve:"] do={
	:local comment [/ip firewall address-list get $i comment]
	:local isdynamic [:find $comment "resolve:"]
	:if ($isdynamic != 0) do={} else={
		:local listname [/ip firewall address-list get $i list]
		:local hostname [:pick $comment 8 [:len $comment]]
		:local currentipaddress [/ip firewall address-list get $i address]
		:local resolvedipaddress [:resolve $hostname]
		:if ($currentipaddress != $resolvedipaddress) do={
			/ip firewall address-list set $i address=$resolvedipaddress
			/log warning "updating address-list $listname host $hostname from $currentipaddress to $resolvedipaddress"
		}
	}
}

If you want to limit the address-list that is queried just change the first line find where statement.

Here is the pastable version:

/system script
add name=resolve-address-lists policy=ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive,api source=":foreach i in=[/ip firewall address-list fin\
    d where comment~\"resolve:\"] do={\r\
    \n\t:local comment [/ip firewall address-list get \$i comment]\r\
    \n\t:local isdynamic [:find \$comment \"resolve:\"]\r\
    \n\t:if (\$isdynamic != 0) do={} else={\r\
    \n\t\t:local listname [/ip firewall address-list get \$i list]\r\
    \n\t\t:local hostname [:pick \$comment 8 [:len \$comment]]\r\
    \n\t\t:local currentipaddress [/ip firewall address-list get \$i address]\r\
    \n\t\t:local resolvedipaddress [:resolve \$hostname]\r\
    \n\t\t:if (\$currentipaddress != \$resolvedipaddress) do={\r\
    \n\t\t\t/ip firewall address-list set \$i address=\$resolvedipaddress\r\
    \n\t\t\t/log warning \"updating address-list \$listname host \$hostname from \$currentipaddress to \$resolvedipaddress\"\r\
    \n\t\t}\r\
    \n\t}\r\
    \n}\r\
    \n"

/system scheduler
add disabled=no interval=1h name=resolve-address-lists on-event="/system script run resolve-address-lists" policy=\
    ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive,api start-date=jan/01/1970 start-time=00:00:00

Netwatch stuff

As of 5.13, the only way to pass information from a netwatch to a script is to use global variables:

Netwatch down/up-script:

:global nwghost 1.1.1.1
:global nwgsendemail true/false
/system script run handle-netwatch

handle-netwatch script:

:global nwghost               # you have to declare it to access it, this does not overwrite its current definition
:global nwgsendemail          # same for this one

:local nwhost $nwghost        # copy their values to local variables before we lose them (can you say possible race condition?)
:local nwsendemail $nwgsendemail # so far this is working nicely and things aren't being missed

:local hostname [/system identity get name]
:local nwhostcomment [/tool netwatch get [/tool netwatch find where host=$nwhost] comment]
:local nwhoststatus [/tool netwatch get [/tool netwatch find where host=$nwhost] status]

:global nwtdate [/system clock get date]
:global nwttime [/system clock get time]

:log warning ("Status $nwhoststatus for $nwhost ($nwhostcomment)")

:if ($nwsendemail = true) do={
  :local emailsubject "$nwhoststatus $nwhost from $hostname ($nwhostcomment)"
  :local emailbody "Status: $nwhost is $nwhoststatus\r\nHost notes: $nwhostcomment\r\nRouter identity: $hostname"
  /tool e-mail send to=msharp@bignetworks.com subject=$emailsubject body=$emailbody
}

Here are pastable version of the above two scripts:

/tool netwatch
add comment="This is 1.1.1.1 comment" disabled=yes host=1.1.1.1 interval=1m timeout=1s \
    down-script=":global nwghost 1.1.1.1\r\n:global nwgsendemail true\r\n/system script run handle-netwatch" \
    up-script=":global nwghost 1.1.1.1\r\n:global nwgsendemail true\r\n/system script run handle-netwatch"

/system script
add name=handle-netwatch source=":global nwghost\r\
    \n:global nwgsendemail\r\
    \n\r\
    \n:local nwhost \$nwghost\r\
    \n:local nwsendemail \$nwgsendemail\r\
    \n\r\
    \n:local hostname [/system identity get name]\r\
    \n:local nwhostcomment [/tool netwatch get [/tool netwatch find where host=\$nwhost] comment]\r\
    \n:local nwhoststatus [/tool netwatch get [/tool netwatch find where host=\$nwhost] status]\r\
    \n\r\
    \n:global nwtdate [/system clock get date]\r\
    \n:global nwttime [/system clock get time]\r\
    \n\r\
    \n:log warning (\"Status \$nwhoststatus for \$nwhost (\$nwhostcomment)\")\r\
    \n\r\
    \n:if (\$nwsendemail = true) do={\r\
    \n  :local emailsubject \"\$nwhoststatus \$nwhost from \$hostname (\$nwhostcomment)\"\r\
    \n  :local emailbody \"Status: \$nwhost is \$nwhoststatus\\r\\nHost notes: \$nwhostcomment\\r\\nRouter identity: \$hostname\"\r\
    \n  /tool e-mail send to=notify@bignetworks.com subject=\$emailsubject body=\$emailbody\r\
    \n}"

Here is a script that extracts the data I need to convert from existing netwatch notification scripts to the new style:

:local nwhost
:local nwinterval
:local nwtimeout
:local nwcomment

:foreach nw in [/tool netwatch find] do={
  :set nwhost [/tool netwatch get $nw host]
  :set nwinterval [/tool netwatch get $nw interval]
  :set nwtimeout [/tool netwatch get $nw timeout]
  :set nwcomment [/tool netwatch get $nw comment]
  :put ("./mikrotik-build-netwatch $nwhost $nwinterval $nwtimeout \"$nwcomment\" true")
}

Pastable version:

/system script
add name=extract-netwatch-data source=":local nwhost\r\
    \n:local nwinterval\r\
    \n:local nwtimeout\r\
    \n:local nwcomment\r\
    \n\r\
    \n:foreach nw in [/tool netwatch find] do={\r\
    \n  :set nwhost [/tool netwatch get \$nw host]\r\
    \n  :set nwinterval [/tool netwatch get \$nw interval]\r\
    \n  :set nwtimeout [/tool netwatch get \$nw timeout]\r\
    \n  :set nwcomment [/tool netwatch get \$nw comment]\r\
    \n  :put (\"./mikrotik-build-netwatch \$nwhost \$nwinterval \$nwtimeout \\\"\$nwcomment\\\" true\")\r\
    \n}"

Converting Netwatch

This script will convert blank netwatch entries to handle-netwatch entries:


:local nwhost ""
:local nwcomment ""
:local nwtimeout ""
:local nwinterval ""

:foreach i in=[/tool netwatch find where up-script ="" and down-script =""] do={
:set nwhost [/tool netwatch get $i host]
:set nwcomment [/tool netwatch get $i comment]
:set nwtimeout [/tool netwatch get $i timeout]
:set nwinterval [/tool netwatch get $i interval]
/tool netwatch remove $i

/tool netwatch add comment="$nwcomment" disabled=yes host=$nwhost interval=$nwinterval timeout=$nwtimeout \
    down-script=":global nwghost $nwhost\r\n:global nwgsendemail false\r\n/system script run handle-netwatch" \
    up-script=":global nwghost $nwhost\r\n:global nwgsendemail false\r\n/system script run handle-netwatch"

}

Find dynamic default gateway route

:foreach i in=[/ip route find where dynamic=yes and dst-address="0.0.0.0/0"] do={:put [ip route get $i gateway]}

Startup Notify

This script emails the log contents 30 seconds after startup. This is helpful in being notified of router reboots for whatever reason.

/system scheduler
add disabled=no interval=0s name=startup-notify on-event=":delay 30\r\
    \n/log print file=mikrotik.log.txt\r\
    \n/tool e-mail send to=notify@bignetworks.com subject=\"\$[/system identity get name] startup at \$[/system cl\
    ock get time] \$[/system clock get date]\" body=\"See attached log file\" file=mikrotik.log.txt\r\
    \n" policy=ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive,api start-time=startup

Make Polycom phone leases static

/ip dhcp-server lease
:foreach i in=[find where active-mac-address ~"00:04:F2" and dynamic =yes ] do={make-static $i}

Check tunnel Connections

:local message

/ip firewall connection
:foreach i in=[find where protocol="gre" or protocol="ipencap"] do={
    :set message ([get $i src-address] . " - " . [get $i dst-address] . " - " . [get $i reply-dst-address] . " - " . [get $i protocol])
    :if ([get $i src-address] != [get $i reply-dst-address]) do={
            /log warning ("removing connection" . $message)
            :put ("removing connection" . $message)
            remove $i
    } else={
        :put ("connection is good: " . $message)
    }
}

Pastable:

/system script
add name=check-tunnel-connections source=":local message\r\
    \n\r\
    \n/ip firewall connection\r\
    \n:foreach i in=[find where protocol=\"gre\" or protocol=\"ipencap\"] do={\r\
    \n    :set message ([get \$i src-address] . \" - \" . [get \$i dst-address] \
    . \" - \" . [get \$i reply-dst-address] . \" - \" . [get \$i protocol])\r\
    \n    :if ([get \$i src-address] != [get \$i reply-dst-address]) do={\r\
    \n            /log warning (\"removing connection\" . \$message)\r\
    \n            :put (\"removing connection\" . \$message)\r\
    \n            remove \$i\r\
    \n    } else={\r\
    \n        :put (\"connection is good: \" . \$message)\r\
    \n    }\r\
    \n}\r\
    \n"

Pastable scheduler:

/system scheduler
add disabled=no interval=10s name=run-check-tunnel-connections on-event=\
    "/system script run check-tunnel-connections" start-time=startup

VRRP Management Script

/system script run vrrp-cleanup
/ip ipsec installed-sa flush sa-type=all

#
# Written by: Mitch Sharp @ BIG Networks (http://www.bignetworks.com)
# Last Updated: 2012 May 23
#
# This script serves two purposes:
# 1. It is set as the vrrp-heartbeat on-master and on-backup scripts.
# 2. It should be scheduled to run on an interval to make sure the multiple
#    vrrp and other supporting interfaces don't get into a junk state.
#
# Requirements:
# In order for an interface to be checked by this script it must have the
# string "vrrp" in its comment.
#

:local checkStatus
:local currentStatus
:local interfaceName
:local msg
:local newStatus

:if ([/interface vrrp get vrrp-heartbeat master ] = true) do={
	:set checkStatus yes
	:set newStatus no
} else={
	:set checkStatus no
	:set newStatus yes
}

:put "checkStatus $checkStatus"
:put "newStatus $newStatus"

:foreach i in=[/interface find where comment ~"vrrp"] do={
	:set currentStatus [/interface get $i disabled]
	:set interfaceName [/interface get $i name]
	:set msg "vrrp-cleanup: $interfaceName disabled=$currentStatus"
	:if ( $interfaceName != "vrrp-heartbeat") do={
		:if ([/interface get $i disabled ] = $checkStatus) do={
			/interface set $i disabled=$newStatus
			:set msg " $msg - changed to disabled=$newStatus"
			/log warning message="$msg"
		}
		:put "$msg"
	}
}

/system script run check-gre-connections

script-check-isp script - multi-hop check-gateway

#
# script-check-isp
#
# The purpose of this script is to perform a function like check-gateway
# but over multiple hops. If there is a physical device between your router
# and the physical Internet connection, such as a cable modem business gateway,
# dsl modem, or t1 router, this script will ping through that device to test
# for connectivity.
#
# The hosts list is a list of IP addresses to ping.
# The pingCount is the number of pings to send to each host.
#
# A down condition is when no hosts respond to pings.
# An up condition is when the number of ping responses is more than 0.
#

:local routeComment "script-check - default route via isp2 - cable modem";
:local routingTable "isp2";
:local hosts "73.208.2.1,8.8.8.8,69.18.99.226";
:local pingCount 3;

:local expected 0;
:local responses 0;
:global scriptCheckISPStatus;

:if ($scriptCheckISPStatus = "") do={:set scriptCheckISPStatus "enabled"};

:foreach host in=[:toarray $hosts] do={
:set responses ([/ping $host count=$pingCount routing-table=$routingTable] + $responses);
:set expected ($expected + $pingCount);
};

:put "Received $responses out of $expected expected responses";

:if ($scriptCheckISPStatus = "enabled") do={
# what to do when route is currently enabled
	:if ($responses = 0) do={
		/ip route set [/ip route find where comment ~"$routeComment"] disabled=yes;
		:set scriptCheckISPStatus "disabled";
		:log info message="script-check $scriptCheckISPStatus route labeled $routeComment";
	};
} else={
# what to do when route is currently disabled
	:if ($responses > 0) do={
		/ip route set [/ip route find where comment ~"$routeComment"] disabled=no;
		:set scriptCheckISPStatus "enabled";
		:log info message="script-check $scriptCheckISPStatus route labeled $routeComment";
	};
};

Finding what bridge port devices are on

:foreach id in=[/ip arp find where address ~"192.168.0."] do={
	:local tmp
	:local tmplen
	:local idmac
	:local idip
	:local idiface
	:set idmac [/ip arp get $id mac-address]
	:set idip [/ip arp get $id address]
	:set tmp [/interface bridge host find where mac-address="$idmac"]
	:set tmplen [ :len $tmp ]
	:if ( $tmplen = 0 ) do={
		:put "$idmac $idiface --- Not found in bridge"
	} else={
		:set idiface [/interface bridge host get $tmp on-interface]
		:put "$idmac $idiface $idip"
	}
}

Finding what the ip addresses are of devices on a bridge port

:foreach id in=[/interface bridge host find where bridge ="bridge-name" and on-interface ="interface-name"] do={
	:local tmp
	:local tmplen
	:local idmac
	:local idip
	:set idmac [/interface bridge host get $id mac-address]
	:set tmp [/ip arp find where mac-address="$idmac"]
	:set tmplen [ :len $tmp ]
	:if ( $tmplen = 0 ) do={
		:put "$idmac --- Not found in arp"
	} else={
		:set idip [/ip arp get $tmp address]
		:put "$idmac $idip"
	}
}

List wireless registration ip addresses and hostnames from dhcp-server leases

:foreach i in=[interface wireless registration-table find] do={
	:local macaddress [/interface wireless registration-table get $i mac-address]
	:local hostname [/ip dhcp-server lease get [/ip dhcp-server lease find where mac-address="$macaddress"] host-name]
	:local ipaddress [/ip dhcp-server lease get [/ip dhcp-server lease find where mac-address="$macaddress"] address]
	:put "$macaddress - $ipaddress - $hostname"
}

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox