==== Mikrotik: PPP Auth backup ====
Функционал позволяет пользователям авторизоваться если отсутствует связь между Микротиком и FreeRADIUS-сервером.
Включаем скрипт синхронизации аккаунтов в ''/etc/crontab''.
*/15 * * * * root /usr/abills/libexec/billd auth_export NAS_IDS=%NAS_ID%
**%NAS_ID%** - ID сервера доступа.
Все экспортированые аккаунты добавляются выключенными, для того, чтоб не мешать нормальному процесу авторизации.
Нам нужно, чтоб они включались только когда нет связи с радиусом.
\\
Создадим на Микротике скрипты для отслеживания ситуации потери связи с радиусом.
**Через winbox**
''/System/Scripts''
{{ :abills:docs:nas:mikrotik:script_add.png?nolink |}}
В область исходников (3), вставляем текст скрипта
# Script Name:Mikrotik Radius Accounting Backup
# Get log entry data from global variable and store it locally
:global logParseVar
:local logTime [:pick [:toarray $logParseVar] 0]
:local logTopics [:pick [:toarray $logParseVar] 1]
:local logMessage [:pick [:toarray $logParseVar] 2]
:set logParseVar ""
# Check for radius timeout
:if ( $logMessage ~ "radius timeout" ) do={
log info ("Radius is timeout. will activate all current ppp secrets")
/ppp secret enable numbers=[/ppp secret find where comment="ABillS Generated"]
}
Для того чтобы скрипт запустился когда потеряна связь с радиусом, нужно парсить лог, ожидая сообщения ''radius timeout''. Для этого создаём еще один скрипт, который будет выбирать из всех строк лога те, которые нам нужно.\\
Включаем логирование в память
/system logging action add memory-lines=100 memory-stop-on-full=no name=logParse target=memory
Включаем логирование топика ''ppp,error'' в область ''logParse''.
/system logging add action=logParse disabled=no prefix="" topics=ppp,error
Теперь создаём сам скрипт парсера, аналогично предыдущему с именем **log_parser** и исходным кодом:
# Script Name: Log-Parser
# This script reads a specified log buffer. At each log entry read,
# the global variable 'logParseVar' is set to ",,"
# then a parser action script is run. The parser action script reads the global variable, and performs specified actions.
# The log buffer is then cleared, so only new entries are read each time this script gets executed.
:local logBuffer "logParse"
:local logParserScript "accounting_backup"
# -----------------------------------
:global logParseVar ""
:local loglastparsetime
:local loglastparsemessage
:local findindex
:local property
:local value
:local logEntryTopics
:local logEntryTime
:local logEntryMessage
:local curDate
:local curMonth
:local curDay
:local curYear
:local clearedbuf
:local lines
# Get current date settings
:set curDate [/system clock get date]
:set curMonth [:pick [:tostr $curDate] 0 3]
:set curDay [:pick [:tostr $curDate] 4 6]
:set curYear [:pick [:tostr $curDate] 7 11]
:set clearedbuf 0
:foreach rule in=[/log print as-value where buffer=($logBuffer)] do={
# Now all data is collected in memory..
# Clear log buffer right away so new entries come in
:if ($clearedbuf = 0) do={
/system logging action {
:set lines [get ($logBuffer) memory-lines]
set ($logBuffer) memory-lines 1
set ($logBuffer) memory-lines $lines
}
:set clearedbuf 1
}
# End clear log buffer
:set logEntryTime ""
:set logEntryTopics ""
:set logEntryMessage ""
# Get each log entry's properties
:foreach k,value in=[:toarray $rule] do={
:if ([:tostr $k] = "time") do={ :set logEntryTime $value }
:if ([:tostr $k] = "topics") do={ :set logEntryTopics $value }
:if ([:tostr $k] = "message") do={ :set logEntryMessage $value }
# end foreach item
}
# Set logEntryTime to full time format (mmm/dd/yyyy HH:MM:SS)
:set findindex [:find [:tostr $logEntryTime] " "]
# If no spaces are found, only time is given (HH:MM:SS), insert mmm/dd/yyyy
:if ([:len $findindex] = 0) do={
:set logEntryTime ($curMonth . "/" . $curDay . "/" . $curYear . " " . \
[:tostr $logEntryTime])
}
# Only (mmm/dd HH:MM:SS) is given, insert year
:if ($findindex = 6) do={
:set logEntryTime ([:pick [:tostr $logEntryTime] 0 $findindex] . "/" . $curYear . \
[:pick [:tostr $logEntryTime] $findindex [:len [:tostr $logEntryTime]]])
}
# Only (mmm HH:MM:SS) is given, insert day and year
:if ($findindex = 3) do={
:set logEntryTime ([:pick [:tostr $logEntryTime] 0 $findindex] . "/" . $curDay . "/" . $curYear . \
[:pick [:tostr $logEntryTime] $findindex [:len [:tostr $logEntryTime]]])
}
# End set logEntryTime to full time format
# Skip if logEntryTime and logEntryMessage are the same as previous parsed log entry
:if ($logEntryTime = $loglastparsetime && $logEntryMessage = $loglastparsemessage) do={
} else={
# Set logParseVar, then run parser script
:set logParseVar ($logEntryTime . "," . $logEntryTopics . "," . $logEntryMessage)
/system script run ($logParserScript)
# Update last parsed time, and last parsed message
:set loglastparsetime $logEntryTime
:set loglastparsemessage $logEntryMessage
}
# end foreach rule
}
**Код взят из [[https://wiki.mikrotik.com/wiki/Log_Parser_-_Event_Trigger_Script|официальной вики Mikrotik]] и переписан для версии 6.2x+**
Поскольку, после того, как аккаунты включены, обращений к радиусу больше не будет, нужно отключать их через некоторое время. \\
Создаём 3-й скрипт с именем **disable_accounting_backup** и кодом:
/ppp secret disable numbers=[/ppp secret find where comment="ABillS Generated"]
Теперь, когда у нас есть все 3 скрипта, настроим их автозапуск \\
''/System/Sheduler''
Добавляем скрипт отключения аккаунтов
{{ :abills:docs:nas:mikrotik:sheduler_disable.png?nolink |}}
И скрипт проверки лога с интервалом на 1 секунду больше
{{ :abills:docs:nas:mikrotik:log_parse.png?nolink |}}
Всё. Теперь, когда в логе появится запись с текстом "radius timeout", у нас включатся сохранённые записи, которые отключатся через 5 минут. Если Radius сервер еще не будет отвечать к этому времени ( а проверка через секунду после отключения ), то они включатся снова.
** Если нужно более быстрое время реакции на неполадки, можно уменьшить время запуска в шедулере на 1 минуту для ''disable_accounting_backup'' и 10 секунд для ''log_parser''**