2026-09-16
Двухфакторная аутентификация для VPN и Wi-Fi через FreeRADIUS + OTP (TOTP/HOTP)

Двухфакторная аутентификация для VPN и Wi-Fi через FreeRADIUS + OTP (TOTP/HOTP)

FreeRADIUS — самый популярный RADIUS-сервер. На его базе можно сделать двухфакторную аутентификацию (пароль + OTP) для любого RADIUS-клиента: Mikrotik VPN (L2TP/IPsec, PPTP), гостевой Wi-Fi / Hotspot, RD Gateway. В статье — Ubuntu FreeRADIUS + RADIUS-клиент на Mikrotik и проверка OTP через модуль rlm_otp (или через скрипт TOTP).


Архитектура

[Пользователь] --[VPN/Wi-Fi/RDG]--> [Mikrotik / RD Gateway : радиус-клиент]
                                         |
                                        (UDP 1812/1813)
                                         v
                              [FreeRADIUS @ Ubuntu :1812]
                                         |
                              [OTP-модуль: TOTP/HOTP]
  • RADIUS-клиент (NAS) — Mikrotik (L2TP/IPsec, hotspot), Windows NPS, RD Gateway
  • RADIUS-сервер — FreeRADIUS на Ubuntu
  • OTP — TOTP (Google Authenticator/FreeOTP) или HOTP

Шаг 1. Установка FreeRADIUS

sudo apt update && sudo apt install -y freeradius

Проверка:

sudo freeradius -X

Ошибки конфига видны прямо в выводе.


Шаг 2. Базовые пароли пользователей

Первичная проверка (пароль из users):

/etc/freeradius/3.0/users:

# формат:  User-Name  Cleartext-Password := "пароль"
vpnuser01  Cleartext-Password := "Passw0rd!"

Список и проверка:

# из Ubuntu
echo "User-Name=vpnuser01, User-Password=Passw0rd!" | radclient localhost auth testing123

Ответ Access-Accept означает успех.

Пароли лучше хранить в hash: vpnuser01 Cleartext-Password := "..." НЕ рашлите в открытом виде — используйте NTHash/MD5/SSHA.


Шаг 3. Включаем модуль rlm_otp (TOTP)

В FreeRADIUS нет встроенного TOTP, но есть rlm_otp (HOTP) либо подключаем python/exec процедуру для TOTP. Простой рабочий путь — через exec и скрипт oathtool.

3.1. Установка oathtool

sudo apt install -y oathtool

3.2. Генерация секретов для пользователей

# Генерация случайного секрета (base32 для Google Authenticator)
SECRET=$(head -c 20 /dev/urandom | base32 | tr -d '=')
echo "Секрет пользователя: $SECRET"
# В Google Authenticator вводите этот секрет

3.3. Скрипт проверки OTP

Создайте /usr/local/bin/check_totp.sh:

#!/bin/bash
# $1 - логин, $2 - введённый OTP
USER="$1"
TOKEN="$2"
BASE32_SECRET=$(grep "^$USER:" /etc/freeradius/totp_secrets | awk -F: '{print $2}')
if [ -z "$BASE32_SECRET" ]; then
  echo "Auth-Type reject"
  exit 1
fi
# Допускаем окно -1,0,+1 (держит небольшой рассинхрон)
for ((off=-1; off<=1; off++)); do
  EXPECTED=$(oathtool --totp --base32 --time-step-size=30 --window=$off "$BASE32_SECRET" 2>/dev/null)
  if [ "$EXPECTED" = "$TOKEN" ]; then
    echo "Auth-Type accept"
    exit 0
  fi
done
echo "Auth-Type reject"
exit 1

Файл секретов /etc/freeradius/totp_secrets:

vpnuser01:BASE32SECRET123456
vpnuser02:ANOTHERBASE32SECRET

Засекречьте файл:

sudo chmod 600 /etc/freeradius/totp_secrets

3.4. Подключение к FreeRADIUS

/etc/freeradius/3.0/sites-enabled/otp:

authorize {
    if (User-Password =~ /^[0-9]{6}$/) {
        update {
            control:Packet-Type := Access-Accept
        }
    }
    else {
        update {
            control:Auth-Type := Reject
        }
    }
}

Или полнее через exec в authenticate:

В /etc/freeradius/3.0/modules/exec добавляем:

exec totp_check {
    wait = yes
    input = "dummy"
    program = "/usr/local/bin/check_totp.sh %{User-Name} %{User-Password}"
    output = none
}

В sites-enabled/otp:

authenticate {
    Auth-Type OTP {
        exec totp_check
    }
}

Шаг 4. RADIUS-клиент на Mikrotik (L2TP/IPsec)

Настроим Mikrotik как RADIUS-клиент — тогда при L2TP/IPsec VPN сервер спрашивает Username + Password у FreeRADIUS, где «Password» — OTP.

4.1. Добавляем RADIUS-сервер

/radius add service=pppoe,l2tp address=192.168.10.55 
    secret=radsecret ports=1812 timeout=3s comment="FreeRADIUS"

4.2. Включаем RADIUS для L2TP (VPN)

/ppp l2tp-server set enabled=yes authentication=mschap2 
    use-ipsec=yes ips-pool=vpn-pool

/ppp profile add name=vpn-radius change-address=none 
    bridge-mode=none use-radius=yes

4.3. Проверка из WinBox

Пользователь вводит в VPN-клиенте: логин vpnuser01, пароль <его OTP>. Если всё настроено — подключение проходит только при верном OTP.


Шаг 5. RD Gateway / Windows NPS через RADIUS

Связка со статьёй про RD Gateway:

  1. Установите роль Network Policy and Access Services (NPS).
  2. В NPS: RADIUS Clients → добавить FreeRADIUS.
  3. Для RD Gateway: настройте CAP обращение к RADIUS.
  4. Пользователь вводит доменную учётку, а NPS передаёт пароль как «password + OTP» (пароль8021x…). Стандартная практика: фиксированный-пароль в поле User-Password, но с FreeRADIUS гибче OTP-модуль.

Упрощённо: RD Gateway → NPS (Windows) → FreeRADIUS (OTP). В RNPS connection request policy укажите forwarded to FreeRADIUS.


Шаг 6. Hotspot/Wi-Fi через RADIUS (связка со статьёй про captive portal)

На Mikrotik-роутере для гостевого Wi-Fi:

/radius set service=hotspot address=192.168.10.55 secret=radsecret 
    timeout=3s
/ip hotspot profile set guest use-radius=yes
/ip hotspot user profile set default radius-accounting=yes

Теперь при входе на wiki-портал гость вводит логин + OTP — проверку делает FreeRADIUS.


Проверка всей цепочки

# 1. FreeRADIUS результаты
sudo tail -f /var/log/freeradius/radius.log

# 2. Конкретный e2e через radclient (без NAS):
#    - если OTP верный:
echo "User-Name=vpnuser01, User-Password=123456" | 
  radclient -x 127.0.0.1:1812 auth testing123
#    вывод: Access-Accept

# 3. От Mikrotik в логах FreeRADIUS появится NAS-адрес и User-Name

Тонкости и подводные камни

  • OTP бывает рассинхронизирован — окно ±1 шаг (30c) решает; если клиент вводит код после long-тики — настройте --window=2.
  • Не путайте пароль и OTP — в RADIUS User-Password один. Варианты: «пароль+OTP» через %{User-Password} склеивание, либо TOTP-only (как здесь). Для домашнего использования TOTP-only — норма.
  • Безопасность секретов — файл totp_secrets это root-only. Не делайте readable для freeradius-пользователя.
  • FreeRADIUS порт 1812/1813 — откройте в firewall:
    bash
    sudo ufw allow 1812/udp && sudo ufw allow 1813/udp
  • Mikrotik mschap2 подсекает OTP — с L2TP/IPsec используйте mschap-v2 с расширением: FreeRADIUS должен вернуть MS-CHAP2-Success. Для TOTP-only проще chap/mschap обычный — проверьте.
  • NAS-ключ (secret) — одинаковый в /radius add и в clients.conf: secret = radsecret. Иначе Access-Reject.

Шпаргалка

sudo apt install freeradius oathtool

# секрет для пользователя
SECRET=$(head -c 20 /dev/urandom | base32 | tr -d '=')
echo "user:$SECRET" >> /etc/freeradius/totp_secrets

# клиенты (NAS) в /etc/freeradius/3.0/clients.conf
# client mikrotik { ipaddr = 192.168.10.1 secret = radsecret }

# Mikrotik:
# /radius add service=l2tp address=192.168.10.55 secret=radsecret
# /ppp profile set default use-radius=yes

Проверено на: Ubuntu 22.04 + FreeRADIUS 3.x + RouterOS 7.
Дата: Сентябрь 2026.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *