Вступление
Всем привет! Хотелось бы поделиться результатом своих наработок по небольшому личному проекту. Некоторое время назад пришлось покопаться в FreeRADIUS, и я подумал, почему бы не попробовать реализовать схему со вторым фактором для давно используемого Ocserv.
Дисклеймер
Хочу обратить ваше внимание, что содержание этой статьи — это работающий концепт, а не готовый продукт, который можно использовать в production-окружениях. Поэтому у нас будут множественные допущения, цель которых — упростить реализацию для лучшего понимания. В частности, мы не будем затрагивать темы безопасности, маршрутизации трафика и разделения привилегий.
С чего начнем
Синхронизация времени
TOTP генерируется на основе текущего времени. Если время на сервере и на устройстве клиента рассинхронизировано, сервер вычислит другое значение и не сможет подтвердить корректный одноразовый пароль, что приведёт к ложному отклонению доступа. Поэтому убедитесь, что на устройстве для генерации кода и на вашем сервере одинаковое время.
Окружение
В моем случае я использовал довольно стандартный стек:
-
Docker 29
-
Ubuntu 24.04
-
GIT
-
Google Authenticator (или любой подобный продукт)
Клонируем репозиторий
git clone https://github.com/scorsair/ocserv-freeradius-freeipa-totp.gitcd ocserv-freeradius-freeipa-totp
Сертификаты
Для работы Ocserv нам понадобятся сертификаты. Можете использовать certbot с вашим доменом или сделать проще и быстрее для теста:
cd ocservopenssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365 -subj "/CN=ocserv.ipa.local"cd -
Запуск и настройка сервисов
Поднимаем контейнеры
docker compose up -d# Первый запуск может занять продолжительное время из-за инициализации FreeIPAdocker compose logs -f freeipa # Дожидаемся вывода "FreeIPA server started"# Убеждаемся в том, что все три контейнера запущены и не имеют периодических рестартовdocker compose ps --status running
Ручные шаги
docker compose exec freeipa bash# Добавляем FreeRADIUS аттрибуты в схему LDAP нашей FreeIPAipa-ldap-updater -S /usr/share/dirsrv/data/60radius.ldifipactl restart# Authkinit admin # Вводим пароль: 9g5xTFf29b0C92Rz# Добавляем новый ObjectClass для будущих пользователей по умолчаниюipa config-mod --addattr=ipaUserObjectClasses=radiusprofile# Для пользователя admin добавляем принудительноipa user-mod --addattr=objectClass=radiusprofile admin# Добавляем RADIUS аттрибуты для пользователя admin, эти значения будут перехватываться FreeRADIUS и перенаправляться в Ocservipa user-mod admin --setattr="radiusFramedIPAddress=10.255.255.170"ipa user-mod admin --setattr="radiusFramedIPNetmask=255.255.255.255"ipa user-mod admin --setattr="radiusFramedRoute=10.255.255.0/24"ipa user-show admin --all | grep radius
OTP
Теперь нам нужно создать OTP-секрет для пользователя admin. Результатом выполнения команды будет QR-код, который надо отсканировать приложением Google Authenticator
ipa otptoken-add --type=totp --owner=admin
Привилегии
Так как мы используем того же пользователя admin для интеграции FreeRADIUS с FreeIPA, создадим необходимые привилегии и роли, которые назначим ему:
# Permissionsipa permission-add --attrs=userpassword --right='read' 'Read UserPassword' --type=useripa permission-add --attrs={radiusframedipaddress,radiusframedipnetmask,radiusframedroute} --right='read' 'Read RadiusAttr' --type=useripa permission-add --attrs={ipatokenOTPkey,ipatokenOwner,ipatokenUniqueID} --right={read,search} 'Read OTP'# Privilegeipa privilege-add 'Radius Server'ipa privilege-add-permission 'Radius Server' --permissions={'Read UserPassword','Read RadiusAttr','Read OTP'}# Roleipa role-add 'Radius'ipa role-add-privilege 'Radius' --privileges='Radius Server'# Назначаем рольipa role-add-member --users=admin 'Radius'
Вот и все, можно подключаться)
Подключение
Для подключения можно использовать OpenConnect VPN for Windows или Cisco AnyConnect. Так как у нас всё развернуто локально, используем URL: https://127.0.0.1. Вводим логин и OTP-код, подключаемся.
ссылка на оригинал статьи https://habr.com/ru/articles/1027944/