AAA DIAGNOSTIC MAP (AUTH + ACCOUNTING)

Назначение:
- Карта диагностики для FreeRADIUS rlm_perl + ACP auth/accounting модулей.
- Охватывает найденные в коде сценарии и сигнатуры логов.

======================================================================
1) БАЗОВЫЕ КОДЫ RLM (rlm_perl.pl)
======================================================================

RLM return code:
- 0 = RLM_MODULE_REJECT
- 1 = RLM_MODULE_FAIL
- 2 = RLM_MODULE_OK
- 3 = RLM_MODULE_HANDLED
- 4 = RLM_MODULE_INVALID
- 5 = RLM_MODULE_USERLOCK
- 6 = RLM_MODULE_NOTFOUND
- 7 = RLM_MODULE_NOOP
- 8 = RLM_MODULE_UPDATED

Accounting event code (RFC2866):
- Start -> 1
- Stop -> 2
- Alive -> 3
- Interim-Update -> 3
- Accounting-On -> 7
- Accounting-Off -> 8

======================================================================
2) ENTRY POINTS И ГДЕ СМОТРЕТЬ ЛОГИ
======================================================================

authorize():
- лог: "authorize Auth-Type: ..."

authenticate():
- лог: "authenticate Auth-Type: ..."

post_auth():
- лог: "post_auth Auth-Type: ... Post: ... User-Name: ... Q: ..."
- DHCP-ветка и non-DHCP-ветка расходятся именно здесь.

accounting():
- лог: "rlm_perl: accounting module='...' NAS_TYPE='...' Acct-Status-Type='...' code='...' ... connection_info='...'"
- далее управление уходит в выбранный accounting-модуль.

======================================================================
3) ROUTING КАКОЙ МОДУЛЬ ВЫБРАН
======================================================================

Accounting:
- выбирается по `$ACCT{ $nas->{NAS_TYPE} }`, иначе `Acct2`.
- диагностическая строка всегда показывает `module='...'`.

Auth (DHCP):
- если `DHCP-Message-Type` присутствует, `NAS_TYPE` принудительно становится `dhcp`,
  и вызывается auth-модуль для dhcp (обычно `Mac_auth`/`Mac_auth2` по конфигу).

Auth (не DHCP):
- идёт обычная post_auth-ветка с проверкой Post-Auth-Type, MSCHAP/eap и auth_().

======================================================================
4) AUTH ЛОГИКА: НАЙДЕННЫЕ ДИАГНОСТИЧЕСКИЕ МАРКЕРЫ
======================================================================

4.1 Auth2.pm
- "Auth2[mikrotik]: start; login='...' CID='...' NAS-IP='...'"

4.2 Mac_auth2.pm (mikrotik_dhcp ключевые сценарии)
- "Mac_auth2[mikrotik_dhcp] => Auth2[mikrotik]; ..."
  Значение: ранний переход из DHCP-логики в обычный Auth2 (логин не MAC).

- "Mac_auth2[mikrotik_dhcp]: continue DHCP; login(MAC)='...'"
  Значение: остаёмся в DHCP-логике (логин MAC).

- "Mac_auth2[mikrotik_dhcp]: continue DHCP; USER_MAC: ..., NAS_MAC: ..., PORT: ..., VLAN: ..., SERVER_VLAN: ..."
  Значение: распарсены opt82/привязки порта/VLAN.

- "Mac_auth2[mikrotik_dhcp]: after user_info UID=... SERVICE_ID=... INTERNET_DISABLE=... USER_DISABLE=... GUEST_MODE=..."
  Значение: после user_info получены/не получены ключевые параметры авторизации.

- "Mac_auth2[mikrotik_dhcp]: DISABLE branch INTERNET_DISABLE=... USER_DISABLE=... GUEST_MODE=..."
  Значение: вход в ветку ограничений/блокировок.

- "Mac_auth2[guest_mode]: NAS_TYPE=... MSG=... UID=... SERVICE_ID=... INTERNET_DISABLE=... USER_DISABLE=... OLD_GUEST_MODE=..."
  Значение: включён guest_mode и выбран сценарий ответа.

- "Mac_auth2[calls_update]: NAS_TYPE=... UID=... SERVICE_ID=... USER_NAME=... INTERNET_DISABLE=... USER_DISABLE=... GUEST_MODE=... IP=... MAC=..."
  Значение: актуализация online/calls состояния в контексте DHCP.

4.3 Общие auth warning/error (через Log::log_print)
- "Failed to load: <module>.pm" (rlm_perl)
- "REJECT WRONG_AUTH (...)" (rlm_perl)
- "For system Authentification you need root privileges" (Auth/Auth2/Me60_auth)
- "Can't load 'Digest::MD5' ..." (Auth/Auth2/Me60_auth)

======================================================================
5) ACCOUNTING ЛОГИКА: НАЙДЕННЫЕ ДИАГНОСТИЧЕСКИЕ МАРКЕРЫ
======================================================================

5.1 rlm_perl accounting общий вход
- "rlm_perl: accounting module='...' NAS_TYPE='...' Acct-Status-Type='...' code='...' login='...' SID='...' Framed='...' connection_info='...'"

Поля:
- module: выбранный accounting-модуль.
- NAS_TYPE: тип NAS из справочника.
- Acct-Status-Type/code: тип accounting события (см. таблицу code).
- connection_info: `Connect-Info` либо fallback в `NAS-Port-Id`.

5.2 Mikrotikk_acct2.pm / Mikrotik_acct2.pm
- "Mikrotikk_acct2[acct]: DEBUG: Check mikrotik_dhcp logic for User-Name='...'"
- "User-Name is MAC, trying to find user via Auth2 ..."
- "mikrotik_dhcp username substitution: <old> -> <new> (UID: ...)"
- "Auth2 lookup failed for MAC '...', trying user_info fallback"
- "user_info fallback substitution: ..."
- "username substitution failed for MAC '...'"
- "Normalized CID '1:xx:..' -> 'xx:..'"
- "failed to load Acct2: ..."
- "delegate to Acct2; Acct-Status-Type='...' code='...' ... connection_info='...'"

5.3 Acct2.pm
Start:
- "Acct2[start:debug]: lock route='...' total='...' errno='...' errstr='...' ..."
- "Acct2[start:debug]: update route='...' affected='...' errno='...' errstr='...' ..."
- "Acct2[start]: UPDATE online affected='...'"
- "Acct2[start:debug]: fallback add_unknown_session lock_route='...'"

Stop:
- "Acct2[stop]: DELETE online affected='...'"

Alive/Interim:
- "Acct2[alive:ipn]: UPDATE online affected='...'"
- "Acct2[alive]: UPDATE online affected='...' ... sum='...'"

Accounting-On/Off:
- "Acct2[acct 7/8]: UPDATE online affected='...'"

Unknown/lost-start recovery:
- "Acct2[add_unknown_session]: REPLACE online; ..."
- "Acct2[add_unknown_session]: REPLACE affected='...'"
- "Acct2[add_unknown_session]: DELETE stale IP entry affected='...'"

======================================================================
6) ROUTE/STATE ИНТЕРПРЕТАЦИЯ (online_* path)
======================================================================

route поля в Acct2 start debug:
- route='ACP/mysql/dbcore.pm'
  Метод online_* реально реализован в базовом dbcore.

- route='ACP/mysql/dbcore/<backend>.pm'
  Метод переопределён в backend-файле.

- route='ACP/mysql/main.pm'
  Сработал SQL fallback в main.pm.

- route='DB_HANDLE::online_*'
  Вызов пошёл в метод объекта DB-handle/обёртки.

state поля:
- total:
  результат lock SELECT.
  >0 = найдена запись для UPDATE, 0 = не найдено, fallback возможен.

- affected:
  сколько строк реально изменил UPDATE/DELETE/REPLACE.

- errno/errstr:
  признаки ошибки SQL/логики; пусто = ошибки нет.

======================================================================
7) ДИАГНОСТИЧЕСКИЕ ПАТТЕРНЫ "СИМПТОМ -> ПРИЧИНА -> ПРОВЕРКА"
======================================================================

Симптом:
- accounting идёт, но кажется "как авторизация".
Причина:
- в ветке mikrotik_dhcp accounting может делать username substitution через Auth2-поиск.
Проверка:
- смотреть Acct-Status-Type/code в строке delegate/accounting module.

Симптом:
- частый fallback add_unknown_session.
Причина:
- lock не находит подходящую online-запись (реально либо из-за несовпадения ключей).
Проверка:
- сравнить login/NAS_ID/SID/IP/CID в Start;
- смотреть lock total и route.

Симптом:
- DELETE online affected='0' или 'undef' на Stop.
Причина:
- запись уже удалена/не найдена/другой SID.
Проверка:
- сверить SID, NAS_ID, timing Start/Stop; проверить предыдущие alive/update.

Симптом:
- REJECT WRONG_AUTH.
Причина:
- Post-Auth-Type Reject либо auth_() вернул отказ.
Проверка:
- смотреть post_auth строку, Reply-Message, auth module логи.

Симптом:
- "Failed to load: <module>.pm" / "failed to load Acct2".
Причина:
- модуль не найден в @INC или ошибка компиляции.
Проверка:
- проверить путь, имя модуля в config, perl -c файла.

======================================================================
8) ЧЕК-ЛИСТ ИНЦИДЕНТА (ПОЛНЫЙ И РАЗВЁРНУТЫЙ)
======================================================================

Шаг 0. Границы инцидента:
- Зафиксировать время начала/окна проблемы.
- Указать затронутые NAS_IP, NAS_ID, NAS_TYPE.
- Указать затронутые сервисы: DHCP/PPPoE/оба.
- Указать масштаб: 1 абонент / сегмент / массово.

Шаг 1. Минимальный набор полей по кейсу:
- login (User-Name)
- SID (Acct-Session-Id)
- NAS-IP-Address
- Framed-IP-Address
- Calling-Station-Id (CID/MAC)
- Connect-Info / NAS-Port-Id (connection_info)
- Acct-Status-Type и code
- module и NAS_TYPE из строки accounting

Шаг 2. Подтвердить реальный тип события:
- Проверить соответствие Acct-Status-Type и code:
  Start=1, Stop=2, Alive/Interim=3, On=7, Off=8.
- Если тип строкой и code расходятся, считать приоритетным code из rlm_perl.
- Для спорных кейсов собрать соседние события по тому же SID (до/после 1–2 минуты).

Шаг 3. Проверка маршрута модуля:
- По строке `rlm_perl: accounting module='...'` подтвердить выбранный модуль.
- Сверить модуль с конфигом `$ACCT{NAS_TYPE}`.
- Если модуль неожиданный:
  - проверить NAS_TYPE в карточке NAS,
  - проверить runtime `config.pl`,
  - проверить наличие кеша/старых клонов rlm_perl.

Шаг 4. Проверка accounting цепочки Start:
- Найти пары строк:
  - `Acct2[start:debug]: lock ...`
  - `Acct2[start:debug]: update ...`
- Проверить lock:
  - route: где исполнился метод (dbcore/backend/main).
  - total: >0 ожидается при найденной записи.
  - errno/errstr: пусто в норме.
- Проверить update:
  - affected: ожидается >=1 при корректном update.
  - errno/errstr: пусто в норме.

Шаг 5. Проверка fallback lost-start:
- Если есть `fallback add_unknown_session`:
  - проверить lock total (обычно 0),
  - проверить `REPLACE affected`,
  - проверить `DELETE stale IP entry affected`.
- Нормально:
  - fallback редкий, точечный, REPLACE=1.
- Ненормально:
  - fallback массовый на одном NAS/в одном VLAN.

Шаг 6. Проверка Stop/Alive/Interim:
- Stop:
  - строка `Acct2[stop]: DELETE online affected='...'`.
  - affected=0 допустим при уже очищенной сессии.
- Alive/Interim:
  - строка `Acct2[alive]` или `Acct2[alive:ipn]`.
  - смотреть sum, affected и стабильность SID.
- Accounting-On/Off:
  - `Acct2[acct 7/8]` должно чисто обновлять online статус.

Шаг 7. Проверка auth цепочки (если есть жалобы на авторизацию):
- Проверить `post_auth` строку:
  - Auth-Type, Post-Auth-Type, User-Name, Q.
- Для DHCP:
  - проверить ветку `DHCP-Message-Type`.
  - проверить переходы в Mac_auth2:
    - `=> Auth2[mikrotik]` (не-MAC логин),
    - `continue DHCP` (MAC логин).
- Проверить Reply-Message и access_deny логи.
- При Reject:
  - искать `REJECT WRONG_AUTH` и контекст до него.

Шаг 8. Mikrotik DHCP/PPPoE пограничные случаи:
- Проверить username substitution:
  - строки `username substitution` / `user_info fallback`.
- Проверить нормализацию CID:
  - `Normalized CID '1:..' -> '..'`.
- Проверить, что PPP и DHCP не конфликтуют по одному IP:
  - по логам fallback/REPLACE и по active SID.

Шаг 9. Проверка route и backend для online_*:
- route='ACP/mysql/dbcore.pm':
  - базовая реализация dbcore.
- route='ACP/mysql/dbcore/<backend>.pm':
  - переопределённая backend-реализация.
- route='ACP/mysql/main.pm':
  - fallback SQL path.
- route='DB_HANDLE::online_*':
  - вызов через метод DB-handle/обёртки.
- Если route неожиданный:
  - сверить dbtype, DRIVER, ACP_DB_DRIVER, доступность backend модуля.

Шаг 10. Проверка данных сессии на консистентность:
- login в auth и accounting должен совпадать (после substitution).
- SID должен быть стабилен в Start/Alive/Stop.
- NAS_ID/NAS-IP должны совпадать с карточкой NAS.
- connection_info должен соответствовать интерфейсу/порту.
- CID должен быть нормализован в едином формате MAC.

Шаг 11. Проверка модулей и загрузки:
- При ошибках `failed to load`:
  - проверить наличие файла модуля,
  - проверить имя в config.pl,
  - проверить `@INC`,
  - выполнить `perl -c` для модуля и rlm_perl.pl.

Шаг 12. Проверка БД-стороны:
- internet_online:
  - есть ли запись по SID/login/NAS_ID/IP.
- признаки дублей:
  - несколько активных записей по одному SID или IP.
- stale-плейсхолдеры:
  - записи с `acct_session_id='IP'`/`'MAC'` и устаревшим временем.

Шаг 13. Контрольный набор SQL-проверок (оператор):
- По login+nas_id:
  - последние online записи (status, started, lupdated, SID, IP, CID, connect_info).
- По SID:
  - полная траектория online/log (Start/Alive/Stop).
- По IP:
  - активные записи и коллизии.

Шаг 14. Критерии "исправлено":
- Для проблемного кейса появляется последовательность:
  - Start lock total>0 -> update affected>=1 -> Alive стабильные -> Stop delete.
- fallback остаётся только как редкий recovery.
- Нет массовых `failed to load`, `REJECT WRONG_AUTH`, `total=undef`, `affected=undef`.

Шаг 15. Что приложить к постмортему:
- 5–10 строк логов до/после инцидента.
- Выбранный module/NAS_TYPE/code.
- route lock/update.
- SQL-выборка online по login/SID/IP.
- вывод конфигурации $AUTH/$ACCT для затронутого NAS_TYPE.
- перечень применённых изменений и время деплоя.