==== 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''**