The Mikrotik Hotspot / captive portal is a great feature, however its limited by the ability to expire a user based on the login time/date. The existing options available to expire a user are uptime (cumulative time online) or bytes sent/received. Something better suited to our office environment is to give a user access for a period of time, say one day or one week. For a small office deployment it seems excessive to deploy and support a RADIUS server for this task, Mikrotik User Manager also doesn’t seem to contain this feature either. To get around this limitation I have devised a couple of scripts which can be used to achieve this function.
The scripts work by setting a comment on the user when they log in for the first time, the comment contains the date the user is logging in. Another script is then scheduled to run daily to find all the users where the date has reached greater than the specified period and disable the accounts.
Form simplicity I’m just going to apply this to the default user profile under /ip hotspot user profile
The script to add the date comment:
{
:local date [ /system clock get date ]
:if ( [ /ip hotspot user get $user comment ] = "" ) do={
[ /ip hotspot user set $user comment=$date ]
}
}
And the script to expire users, this converts the current date to an integer by summing the day, months and year together and comparing it against the same addition on the comment we placed on each user above. If the user is to be disabled, we also disconnect them if they are active. You can change the offset variable to how many days you would like to expire the user after.
{
:local offset 7
:global today
{
:local date [ /system clock get date ]
:local montharray ( "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec" )
:local monthdays ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )
:local days [ :pick $date 4 6 ]
:local monthtxt [ :pick $date 0 3 ]
:local year [ :pick $date 7 11 ]
:local months ([ :find $montharray $monthtxt] )
:for nodays from=0 to=$months do={
:set days ( $days + [ :pick $monthdays $nodays ] )
}
:set days ($days + $year * 365)
:set today $days
}
:foreach i in [ /ip hotspot user find where disabled=no ] do={
:if ([ :find [ /ip hotspot user get $i comment ] ] = 0 ) do={
:local date [ /ip hotspot user get $i comment ]
:local montharray ( "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec" )
:local monthdays ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )
:local days [ :pick $date 4 6 ]
:local monthtxt [ :pick $date 0 3 ]
:local year [ :pick $date 7 11 ]
:local months ( [ :find $montharray $monthtxt ] )
:for nodays from=0 to=$months do={
:set days ( $days + [ :pick $monthdays $nodays ] )
}
:set days ($days + $year * 365)
:if ( ($days + $offset) < $today ) do={
:local name [/ip hotspot user get $i name]
:log info "HOTSPOT EXPIRE SCRIPT: Disabling Hotspot user $name first logged in $date"
[ /ip hotspot user disable $i ]
[ /ip hotspot active remove [find where user=$user] ]
}
}
}
}
Lastly we need to add this to the system scheduler to run each day. I run it at 5mins past midnight.
/system scheduler add name=expire-hotspot-users on-event="/system script run expire-hotspot-users" \
policy=read,write start-time=00:05:00 interval=1d
Here’s the entire export:
/ip hotspot user profile
set [ find default=yes ] idle-timeout=none keepalive-timeout=2m on-login=":local date [ /system clock get date ]\r\
\n:if ( [ /ip hotspot user get \$user comment ] = \"\" ) do={\r\
\n [ /ip hotspot user set \$user comment=\$date ]\r\
\n}" rate-limit=1024000/2048000 shared-users=unlimited
/system scheduler
add interval=1d name=expire-hotspot-users on-event="/system script run expire-hotspot-users" policy=read,write start-date=\
may/30/2012 start-time=00:05:00
/system script
add name=expire-hotspot-users policy=read,write, source="{\r\
\n :local offset 7\r\
\n :global today\r\
\n \r\
\n {\r\
\n :local date [ /system clock get date ]\r\
\n :local montharray ( \"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\"aug\",\"sep\",\"oct\",\"nov\",\
\"dec\" )\r\
\n :local monthdays ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )\r\
\n :local days [ :pick \$date 4 6 ]\r\
\n :local monthtxt [ :pick \$date 0 3 ]\r\
\n :local year [ :pick \$date 7 11 ]\r\
\n :local months ([ :find \$montharray \$monthtxt] )\r\
\n :for nodays from=0 to=\$months do={\r\
\n :set days ( \$days + [ :pick \$monthdays \$nodays ] )\r\
\n }\r\
\n :set days (\$days + \$year * 365) \r\
\n :set today \$days\r\
\n }\r\
\n \r\
\n :foreach i in [ /ip hotspot user find where disabled=no ] do={\r\
\n :if ([ :find [ /ip hotspot user get \$i comment ] ] = 0 ) do={\r\
\n :local date [ /ip hotspot user get \$i comment ]\r\
\n :local montharray ( \"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\"aug\",\"sep\",\"oct\",\"nov\"\
,\"dec\" )\r\
\n :local monthdays ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )\r\
\n :local days [ :pick \$date 4 6 ]\r\
\n :local monthtxt [ :pick \$date 0 3 ]\r\
\n :local year [ :pick \$date 7 11 ]\r\
\n :local months ( [ :find \$montharray \$monthtxt ] )\r\
\n :for nodays from=0 to=\$months do={\r\
\n :set days ( \$days + [ :pick \$monthdays \$nodays ] )\r\
\n }\r\
\n :set days (\$days + \$year * 365)\r\
\n :if ( (\$days + \$offset) < \$today ) do={ \r\
\n :local name [/ip hotspot user get \$i name]\r\
\n :log info \"HOTSPOT EXPIRE SCRIPT: Disabling Hotspot user \$name first logged in \$date\"\r\
\n [ /ip hotspot user disable \$i ]\r\
\n [ /ip hotspot active remove [find where user=\$user] ]\r\
\n }\r\
\n }\r\
\n }\r\
\n}"