Some time ago I have administering ISP routers with many clients using static ips.
To make things more secure we added ip->arp entries for clientip+clientmac.
It was very boring and unreliable to add this rules manually.
So I invented this algorithm and implemented it in script.
1. search for all dynamic mac addresses whose ip not in whitelist (add router gateway subnet here and trusted ips)
2. make a database of dynamic mac with corresponding ip
3. monitor for 3 days for this ips to appear again
3.1. if ip appears again with the same mac in second day - add to list of "good" ips
3.2. if ip appears again with the different mac in second day - add ip to blacklist (not monitored) or you could just start monitoring over again
4. if it appears again with the same mac in the third day and ip is in the list of good ips, then make an ip->arp record
Very simply, isn't it?
But we used RouterOS version 2.8 and it takes a lot of time to implement it.
Few more word on environment:
1. script language is for RouterOS 2.8!
2. routers shouldn't be rebooted at least 3 days to script make one monitoring cycle
3. script can monitor N ips simultaneously (it's set in variable)
4. script should be scheduled to run every hour
5. all the used ips have ip->arp disabled record with any mac address (so, if user changes pc or router, you just disabled ip->arp record and script will monitor for the new mac) and not used ips have enabled ip->arp record with inexistent mac (00:00:00:00:00:00 for example).
I have used two script - first is the monitoring itself and second is for whitelist and blacklist (it shouldn't be erased on reboots, so I recorded it to different script).
To make things easier I'm not storing mac addresses in scripts or variables, I just add disabled ip->arp record.
Script also send e-mail with information about any new ip->arp record made by script.
MAC-ROBOT-v2.0:
Code: Select all
#MAC-ROBOT-v2.0 by whale at klub dot lv
#http://whale.klub.lv/
#number of simultaneously monitored ips
:global num
:set num 5
#create 3 empty arrays:
#ip-arp-list contains monitored ips
#hours-list contain number of hours corresponding ip been monitored
#hours-list check contain algorithm stage 3.1 good ips
#note, macs are not stored in variables, they are stored in ip->arp disabled records
:global ip-arp-list
:if ($ip-arp-list = "") do={ :set ip-arp-list (0)
:for n from=2 to=$num do={
:set ip-arp-list ($ip-arp-list . ",0")
}
}
:global hours-list
:if ($hours-list = "") do={ :set hours-list (0)
:for n from=2 to=$num do={
:set hours-list ($hours-list . ",0")
}
}
:global hours-list-check
:set hours-list-check ($hours-list)
:global day2-list
:if ($day2-list = "") do={ :set day2-list (0)
:for n from=2 to=$num do={
:set day2-list ($day2-list . ",0")
}
}
#let's make all the checks for every monitored ip
:for n from=1 to=$num do={
#1-arp-ip contain ip number "n" from array ip-arp-list
:local 1-arp-ip
:local count
:set count 1
:foreach k in $ip-arp-list do={
:if ($count = $n) do={:set 1-arp-ip $k}
:set count ($count+1)
}
#1-hours contain number of hours this ip been monitored
:local 1-hours
:set count 1
:foreach k in $hours-list do={
:if ($count = $n) do={:set 1-hours $k}
:set count ($count+1)
}
#1-day2 contain mark for good ip (algorithm stage 3.1)
:local 1-day2
:set count 1
:foreach k in $day2-list do={
:if ($count = $n) do={:set 1-day2 $k}
:set count ($count+1)
}
#if first ip not monitored let's monitor it!
:if ($1-arp-ip = "0") do={
:local iaddr
:local imac
:local stop
:local stop2
:set stop 0
#load whitelist and blacklist in environment
/system script run dynarp-statarp-robot-blacklist
#search for all dynamic macs
:foreach a in [/ip arp find dynamic=yes DHCP=no] do={
#still has no candidate for monitoring
:if ($stop = 0) do={
:set stop2 0
#get first dynamic mac and ip in variables
:set iaddr [/ip arp get $a address]
:set imac [/ip arp get $a mac-address]
#make sure ip not monitored already or in black/whitelists
:foreach b in ($ip-arp-list . "," . $mac-blacklist . "," . $mac-whitelist) do={
:if ($iaddr = $b) do={:set stop2 1}
}
:if (($stop = 0) && ($stop2 = 0) && ([/ip arp find address=$iaddr dynamic=no disabled=yes] != "") && ((a . $imac) != a)) do={
:set 1-arp-ip $iaddr
/ip arp set [/ip arp find address=$iaddr dynamic=no disabled=yes] mac-address=$imac
#if you want to know what ip is monitored uncomment following line
# /tool e-mail send to=a@b.c subject=($iaddr . " IS BEING MONITORED") body=("ip" . $iaddr . " was seen with this MAC " . [/ip arp get [/ip arp find address=$iaddr dynamic=no disabled=yes] mac-address])
:set stop 1
}
}}
#if this ip is monitored already, then let's make some MAC checks
} else={
#+1 hour to monitored time
:set 1-hours ($1-hours+1)
#if we haven't seen any mac fot this ip in second day or in third day, then cancel monitoring
:if (($1-hours >= 48) && ($1-day2 != 1)) do={
:set 1-arp-ip "0"
:set 1-hours "0"
:set 1-day2 "0"
}
:if ($1-hours > 72) do={
:set 1-arp-ip "0"
:set 1-hours "0"
:set 1-day2 "0"
}
:if ($1-arp-ip != "0") do={
:local imac-d
:local imac-s
:local imac-num
:set imac-num [/ip arp find address=$1-arp-ip dynamic=yes]
:if ($imac-num != "") do={
:set imac-d [/ip arp get $imac-num mac-address]
:set imac-s [/ip arp get [/ip arp find address=$1-arp-ip dynamic=no disabled=yes] mac-address]
#if mac stored in ip->arp disabled record is the same as we see now, then...
:if ($imac-d = $imac-s) do={
#...if it is second day of monitoring make the good ip mark
:if (($1-hours >= 24) && ($1-hours < 48)) do={
:set 1-day2 1
}
#...if it is third day make ip dependent on the MAC in ip->arp and inform someone by e-mail
:if (($1-hours >= 48) && ($1-hours < 72)) do={
/ip arp enable [/ip arp find address=$1-arp-ip dynamic=no disabled=yes]
/tool e-mail send to=a@b.c subject=($1-arp-ip . " depends on MAC" . "-" . $n) body=($1-arp-ip . " depends on MAC " . $imac-s)
:set 1-arp-ip "0"
:set 1-hours "0"
:set 1-day2 "0"
}
#if new mac is not the same as we seen earlier, then add it to blacklist
} else={
/system script set dynarp-statarp-robot-blacklist source=([/system script get dynarp-statarp-robot-blacklist source] . , . $1-arp-ip)
:set 1-arp-ip "0"
:set 1-hours "0"
:set 1-day2 "0"
}
}
}
}
#save all arrays with new data
:local temp
:set count 1
:foreach k in $ip-arp-list do={
:if ($count = 1) do={:if ($n = $count) do={:set temp $1-arp-ip} else={:set temp $k}}
:if ($count != 1) do={:if ($n = $count) do={:set temp ($temp . "," . $1-arp-ip)} else={:set temp ($temp . "," . $k)}}
:set count ($count+1)
}
:set ip-arp-list ($temp)
:set count 1
:foreach k in $hours-list do={
:if ($count = 1) do={:if ($n = $count) do={:set temp $1-hours} else={:set temp $k}}
:if ($count != 1) do={:if ($n = $count) do={:set temp ($temp . "," . $1-hours)} else={:set temp ($temp . "," . $k)}}
:set count ($count+1)
}
:set hours-list ($temp)
:set count 1
:foreach k in $day2-list do={
:if ($count = 1) do={:if ($n = $count) do={:set temp $1-day2} else={:set temp $k}}
:if ($count != 1) do={:if ($n = $count) do={:set temp ($temp . "," . $1-day2)} else={:set temp ($temp . "," . $k)}}
:set count ($count+1)
}
:set day2-list ($temp)
}
Code: Select all
#whitelisted ips not monitored and can be with dynamic mac forever
#blacklisted ips were monitored, then they have changed mac and now they are not monitored (ips dynamically added here by script)
:global mac-blacklist
:global mac-whitelist
:set mac-whitelist 1.1.1.1,2.2.2.2
:set mac-blacklist 1.1.1.1
So this is the script for RouterOS 2.8, but it should not take much time to rewrite it for v3 or v4.