понедельник, 6 ноября 2023 г.

Установка FreeRADIUS с модулем Python3 в RockyLinux 9

Проведем установку FreeRADIUS, затем интегрируем в FreeRADIUS модуль Python, а затем добавим возможность использовать в модуле Python дополнительные библиотеки для работы с PostgreSQL и MySQL (MariaDB).

Обратившись на сайт https://freeradius.org/releases/ определяем последнюю стабильную версию FreeRADIUS. На ноябрь 2023 имеем следующую картину:

Актуальная, стабильная версия – 3.0.x, а именно – 3.0.26.
Определяем, какая версия дистрибутива содержится в наших стандартных репозитариях Rocky Linux 9:
# yum list freeradius
Получаем ответ: 3.0.21-37.el9. Это соответствует стабильной версии 3.0.х, поэтому просто выполняем установку FreeRADIUS стандартными средствами:
# yum install freeradius freeradius-utils
После выполнения установки, основная директория пакета FreeRADIUS будет находиться тут: /etc/raddb.
Основной конфигурационный файл: /etc/raddb/radiusd.conf
Директория с логами: /var/log/radius/

Далее необходимо сгенерировать сертификаты сервера FreeRADIUS, которые будут использоваться в механизмах EAP-TLS, PEAP и EAP-TTLS для установления зашифрованного соединения между авторизуемым клиентом и сервером FreeRADIUS.
Сначала нужно сгенерировать тестовые сертификаты:
# cd /etc/raddb/certs/
# ./bootstrap

И затем попробовать запустить FreeRADIUS
# radiusd –X
Запуск сервера должен пройти без ошибок и закончиться выводом:
Listening on auth address * port 1812 bound to server default
Listening on acct address * port 1813 bound to server default
Listening on auth address :: port 1812 bound to server default
Listening on acct address :: port 1813 bound to server default
Listening on auth address 127.0.0.1 port 18120 bound to server inner-tunnel
Listening on proxy address * port 41210
Listening on proxy address :: port 49147
Ready to process requests

Выход из запущенного процесса - CTRL+C

Далее для работы в действующей сети необходимо сгенерировать индивидуальные сертификаты сервера FreeRADIUS.
Удаляем все ранее созданные сертификаты:
# cd /etc/raddb/certs/
# rm -f *.pem *.der *.csr *.crt *.key *.p12 serial* index.txt*

Редактируем начальные данные корневого сертификата:
# nano ca.cnf
Изменяем пароли по умолчанию в разделе [ req ] на какие-то свои:
input_password = whatever
output_password = whatever

например, на
input_password = mypass01
output_password = mypass01

В разделе [certificate_authority] изменяем название страны, организации и пр. Значения по умолчанию:
countryName = FR
stateOrProvinceName = Radius
localityName = Somewhere
organizationName = Example Inc.
emailAddress = admin@example.org
commonName = "Example Certificate Authority"

например, на такие значения:
countryName = RU
stateOrProvinceName = Radius
localityName = BombeyRadius
organizationName = MyOrg
emailAddress = admin@example.ru
commonName = "CA Certificate Authority"

Затем запускаем генерацию корневого сертификата:
# make ca.pem
# make ca.der

Переходим к созданию сертификата сервера:
# nano server.cnf
Изменяем пароли по умолчанию в разделе [ req ] на какие-то свои:
input_password = whatever
output_password = whatever

например, на
input_password = mypass01
output_password = mypass01

В разделе [server] изменяем название страны, организации и пр. Значения по умолчанию:
countryName = FR
stateOrProvinceName = Radius
localityName = Somewhere
organizationName = Example Inc.
emailAddress = admin@example.org
commonName = "Example Server Certificate"

изменяем на:
countryName = RU
stateOrProvinceName = Radius
localityName = BombeyRadius
organizationName = MyOrg
emailAddress = admin@example.ru
commonName = "Certificate Serv Radius Bombey"

Согласно инструкции от FreeRADIUS, поле commonName в сертификате сервера должно отличаться от поля commonName в корневом сертификате. После редактирования файла запускаем генерацию cертификата сервера:
# make server.pem
# make server.csr

Затем открываем файл настроек EAP FreeRADIUS и указываем пароль сертификата в подсекции tls секции eap:
# nano /etc/raddb/mods-enabled/eap
eap {
     <..>
     tls-config tls-common {
        #private_key_password = whatever
        private_key_password = mypass01
        <..>
    }
    <..>
}

Вновь выполняем тестовый запуск FreeRADIUS
# radiusd -X
И вновь запуск команды должен пройти без ошибок.

Примечания:
>> Если не установить пароль сертификата в файле /etc/raddb/mods-enabled/eap, то возникнет ошибка:
tls: (TLS) Failed reading private key file "/etc/raddb/certs/server.pem"
tls: (TLS) error:1C800064:Provider routines::bad decrypt
tls: (TLS) error:11800074:PKCS12 routines::pkcs12 cipherfinal error
tls: (TLS) error:0A080009:SSL routines::PEM lib
rlm_eap_tls: Failed initializing SSL context
rlm_eap (EAP): Failed to initialise rlm_eap_tls
/etc/raddb/mods-enabled/eap[14]: Instantiation failed for module "eap"
>> Если не создать сертификатов сервера, получим следующую ошибку:
Unable to check file "/etc/raddb/certs/server.pem": No such file or directory
/etc/raddb/mods-enabled/eap[183]: Failed parsing configuration item "private_key_file"
rlm_eap_tls: Failed initializing SSL context
rlm_eap (EAP): Failed to initialise rlm_eap_tls
/etc/raddb/mods-enabled/eap[14]: Instantiation failed for module "eap"

Проведем тестовую авторизацию абонента. Для этого необходимо что бы клиент, откуда отправляется radius запрос, был добавлен в раздел клиентов сервера FreeRADIUS и пользователь, выполняющий авторизацию, был добавлен в раздел пользователей.
Клиенты сервера добавляются в файле: /etc/raddb/clients.conf
Тут уже должен быть создан клиент localhost. Ip адрес откуда ожидаются запросу - 127.0.0.1, секрет (пароль) для совершения запроса - testing123
# nano /etc/raddb/clients.conf
client localhost {
    ipaddr = 127.0.0.1
    secret = testing123
    <…>
}

Тестового пользователя добавим в файл /etc/raddb/mods-config/files/authorize
# nano /etc/raddb/mods-config/files/authorize
В первой строке файла пишем данные пользователя:
korolev Cleartext-Password := "pass123"
Тут задается пользовать «korolev» с паролем «pass123».
Вновь запускаем FreeRADIUS в тестовом режиме:
# radius -X
В соседнем окне терминала выполняет тестовую команду авторизации пользователя:
# radtest korolev pass123 127.0.0.1 0 testing123
Sent Access-Request Id 103 from 0.0.0.0:43064 to 127.0.0.1:1812 length 77
    User-Name = "korolev"
    User-Password = "pass123"
    NAS-IP-Address = 127.0.0.1
    NAS-Port = 0
    Message-Authenticator = 0x00
    Cleartext-Password = "pass123"
Received Access-Accept Id 103 from 127.0.0.1:1812 to 127.0.0.1:43064 length 20

Если мы получили в ответе «Access-Accept», значит авторизация пользователя прошла успешно. В случае неудачной авторизации ответ будет содержать «Access-Reject».

Переходим к установке python3 в FreeRADIUS.
Сначала устанавливаем сам python и дополнительные модули для работы с базами данных PostgeSQL и MySQL (MariaDB)
# yum install python3
# yum install pip
# pip install psycopg2-binary
# pip install mysql-connector

Проверяем, что python3 установлен и библиотеки могут быть использованы в коде:
# python3
Python 3.9.16 (main, Sep 12 2023, 00:00:00)
[GCC 11.3.1 20221121 (Red Hat 11.3.1-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import psycopg2
>>> import mysql.connector
>>>

Если никаких ошибок не возникает, значит все установилось верно.
Не закрывая среду python, узнаем все системные пути, которые использует python в работе. Они понадобятся далее для интеграции python в FreeRADIUS:
>>> import sys
>>> sys.path
['', '/usr/lib64/python39.zip', '/usr/lib64/python3.9', '/usr/lib64/python3.9/lib-dynload', '/usr/local/lib64/python3.9/site-packages', '/usr/local/lib/python3.9/site-packages', '/usr/lib64/python3.9/site-packages', '/usr/lib/python3.9/site-packages']
>>>

Выход из среды python – CTRL+D.
Теперь устанавливаем модуль python3 для FreeRADIUS
# yum install python3-freeradius
Подключаем модуль Python в рабочую конфигурацию:
# ln -s /etc/raddb/mods-available/python3 /etc/raddb/mods-enabled/python3
Открываем модуль python3 и вносим изменения в конфигурацию:
# nano /etc/raddb/mods-enabled/python3
python3 {
python_path="${modconfdir}/${.:name}:/usr/lib64/python39.zip:/usr/lib64/python3.9:/usr/lib64/python3.9/lib-dynload:/usr/local/lib64/python3.9/site-packages:/usr/local/lib/python3.9/site-packages:/usr/lib64/python3.9/site-packages:/usr/lib/python3.9/site-packages"
module = bombey
mod_authorize = ${.module}
func_authorize = authorize
<…>
}
В конфигурации модуля Python описывается, где будет лежать код модуля python3 и какие функции может обрабатывать этот модуль. В нашем случае модуль будет называться «bombey», функция, которая должна содержаться в модуле должна иметь имя «authorize», а сам файл модуля должен быть в директории ${modconfdir}/${.:name} (в «развернутом виде» – это /etc/raddb/mods-config/python3). В директиве python_path, кроме пути до модуля python3 нужно указать и все системные пути интерпретатора python. Мы получили эту информацию ранее, когда устанавливали python3. Теперь эти пути перечисляем здесь через двоеточие.

Создаем файл модуля bombey:
# nano /etc/raddb/mods-config/python3/bombey.py
И прописываем его содержимое:
#!/usr/bin/python3
import radiusd
def authorize(p):
    print("*** authorize bombey ***")
    print(p)
    return radiusd.RLM_MODULE_OK

Сохраняем файл и делаем его исполняемым:
# chmod +x /etc/raddb/mods-config/python3/bombey.py
В файле определяется функция authorize, которой передается набор данных о авторизации в переменной «p». Данная переменная содержит кортеж данных авторизации: имя пользователя, пароль, IP адрес NAS устройства, формирующего авторизационной пакет, а так же временная метка. Функция authorize в данном случае делает всего несколько вещей – это вывод в консоль текста *** authorize bombey ***, вывод в консоль набора данных переменной «p» и завершение работы функции возвращением переменной RLM_MODULE_OK.
Переменные RLM_MODULE_* содержаться в модуле /etc/raddb/mods-config/python3/radiusd.py и соответствуют кодам завершения обработки модуля python3:
RLM_MODULE_REJECT = 0
RLM_MODULE_FAIL = 1
RLM_MODULE_OK = 2
RLM_MODULE_HANDLED = 3
RLM_MODULE_INVALID = 4
RLM_MODULE_USERLOCK = 5
RLM_MODULE_NOTFOUND = 6
RLM_MODULE_NOOP = 7
RLM_MODULE_UPDATED = 8
RLM_MODULE_NUMCODES = 9
Если функция будет возвращать RLM_MODULE_OK – это говорит о том, что в модуле python3, авторизация прошла удачно. А если возвращается RLM_MODULE_REJECT - авторизация была неуспешной. В файле /etc/raddb/mods-config/python3/example.py имеется ряд примеров разных функций используемых в FreeRADIUS и примеры использования разных конструкций для обработки данных и формирования ответа.

Добавляем модуль python в рабочий экземпляр сервиса FreeRADIUS
# nano /etc/raddb/sites-enabled/default
Нужно добавить в блок authorize использование модуля python между auth_log и chap:
authorize {
    filter_username
    preprocess
    # auth_log
    python3
    chap
    <....>
}

Вновь запускам FreeRADIUS в тесте:
# radius -X
И в соседней консоли пытаемся авторизоваться:
# radtest korolev pass123 127.0.0.1 0 testing123
Авторизация должна пройти как и раньше – успешно. Самое интересное в окне работы сервера.
Обратившись к логам в окне с запущенным сервером FreeRADIUS мы увидим, что модуль python3 работает. В лог выводятся строки:
*** authorize bombey ***
(('User-Name', 'korolev'), ('User-Password', 'pass123'), ('NAS-IP-Address', '127.0.0.1'), ('NAS-Port', '0'), ('Message-Authenticator', '0x690954bf4f3e6a343368af3a92fdc767'), ('Event-Timestamp', 'Nov 5 2023 13:32:17 +04'))
(1) [python3] = ok

В первой строке выводиться просто информация о начале обработки в модуле. Это строка print("*** authorize bombey ***") в файле модуля python – bombey.py.
Затем выводятся данные переданные в модуль. Данные приходят в переменной «p» в виде кортежа: (('User-Name', 'korolev'), ('User-Password', 'pass123'), ('NAS-IP-Address', '127.0.0.1'), ('NAS-Port', '0'), ('Message-Authenticator', '0x690954bf4f3e6a343368af3a92fdc767'), ('Event-Timestamp', 'Nov 5 2023 13:32:17 +04')). Тут содержится все необходимое для авторизации: И имя пользователя, и пароль, и IP адрес устройства, откуда пришел запрос и время запроса.

Теперь подключим к модулю pyhon3 дополнительные модули python для работы с базами данным.
# nano /etc/raddb/mods-config/python3/bombey.py
Дополняем скрипт подключаемыми модулями:
#!/usr/bin/python3
import radius
import mysql.connector
import psycopg2

def authorize(p):
    print("*** authorize bombey ***")
    print(p)
    return radiusd.RLM_MODULE_OK

Перезапускаем сервис FreeRADIUS
# radiusd -X
И вновь пытаемся авторизоваться. Никаких ошибок при авторизации и в логах сервера быть не должно.

Примечание: На данном этапе может возникнуть следующая ошибка:
Python version: 3.9.16 (main, Sep 12 2023, 00:00:00) [GCC 11.3.1 20221121 (Red Hat 11.3.1-4)]
Failed loading libpython3.9m.so: libpython3.9m.so: cannot open shared object file: No such file or directory
Failed loading libpython symbols into global symbol table
python_function_load - Module 'bombey' not found
python_error_log:200, Exception type: <class 'ImportError'>, Exception value: /usr/lib64/python3.9/lib-dynload/_hashlib.cpython-39-x86_64-linux-gnu.so: undefined symbol: PyExc_ValueError
python_error_log:220, full_backtrace: ['Traceback (most recent call last):\n', ' File "/etc/raddb/mods-config/python3/bombey.py", line 4, in <module>\n import mysql.connector\n', ' File "/usr/local/lib/python3.9/site-packages/mysql/connector/__init__.py", line 37, in <module>\n from .connection import MySQLConnection\n', ' File "/usr/local/lib/python3.9/site-packages/mysql/connector/connection.py", line 31, in <module>\n from .authentication import get_auth_plugin\n', ' File "/usr/local/lib/python3.9/site-packages/mysql/connector/authentication.py", line 26, in <module>\n from hashlib import sha1\n', ' File "/usr/lib64/python3.9/hashlib.py", line 77, in <module>\n import _hashlib\n', 'ImportError: /usr/lib64/python3.9/lib-dynload/_hashlib.cpython-39-x86_64-linux-gnu.so: undefined symbol: PyExc_ValueError\n']
python_function_load - Failed to import python function 'bombey.authorize'
python_error_log:192, Unknown error
/etc/raddb/mods-enabled/python3[9]: Instantiation failed for module "python3"
Это говорит о том, что Python3, запущенный из как модуль FreeRADIUS не видит библиотеку libpython3.9m.so.
Проверяем, какие есть аналоги в нашей системе:
# ls -l /usr/lib64/libpython*
-rwxr-xr-x. 1 root root 3486512 Oct 5 21:10 /usr/lib64/libpython3.9.so.1.0
-rwxr-xr-x. 1 root root 14944 Oct 5 21:10 /usr/lib64/libpython3.so
И делаем символьную ссылку на наиболее подходящую:
# ln -s /usr/lib64/libpython3.9.so.1.0 /usr/lib64/libpython3.9m.so
Теперь сервер запуститься удачно.

Отключаем элементы сервиса FreeRADIUS, которые использовать не будем.
Например, можно отключить экземпляр FreeRADIUS, определенный в файле inner-tunnel. Для этого необходимо удалить символьную ссылку:
# rm -f /etc/raddb/sites-enabled/inner-tunnel
Затем можно отключить проксирование. Это делается в глобальном файле конфигурации:
# nano /etc/raddb/radiusd.conf
Устанавливаем директиву proxy_requests в no И комментируем строку $INCLUDE proxy.conf
proxy_requests = no
#$INCLUDE proxy.conf


Добавляем сервис FreeRADIUS в автозагрузку и стартуем:
# systemctl enable radiusd
# systemctl start radiusd

Проверка работы сервиса:
# systemctl status radiusd
# netstat -ltupn | grep radiusd



Для того что бы отключить использование IPv6, необходимо в настройках экземпляра сервиса FreeRADIUS default, закомментировать строки, касающиеся прослушивания портов ipv6:
##listen {
## type = auth
## ipv6addr = :: # any. ::1 == localhost
## port = 0
# interface = eth0
# clients = per_socket_clients
## limit {
## max_connections = 16
## lifetime = 0
## idle_timeout = 30
## }
##}
##listen {
## ipv6addr = ::
## port = 0
## type = acct
# interface = eth0
# clients = per_socket_clients
## limit {
# max_pps = 0
# idle_timeout = 0
# lifetime = 0
# max_connections = 0
## }
##}

И затем рестартовать сервис:
# systemctl start radiusd
# netstat -ltupn | grep radiusd


На этом базовая настройка FreeRADIUS с модулем python3 завершена.

Комментариев нет:

Отправить комментарий