Обновляем ОС:
# dnf update
Устанавливаем репозитарии EPEL и CRB:
# dnf install epel-release
# dnf config-manager --set-enabled crb
Устанавливаем PostgreSQL 16-ой версии:
# dnf install perl-IPC-Run
Подключаем репозитарий с версиями PostgreSQL
# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
Отключаем встроенный модуль postgresql в репозитариях по умолчанию
# dnf -qy module disable postgresql
Проверка подключения репозитариев:
# yum repolist
Видим, что репозитарий в 16-ой версией присутсвует в списке доступных.
Вводим команду установки:
# dnf install postgresql16-server
# dnf install postgresql16-devel
Иницируем базу данных:
# /usr/pgsql-16/bin/postgresql-16-setup initdb
# systemctl start postgresql-16.service
# systemctl enable postgresql-16.service
Установка пакетов, необходимых для сборки FreeRADIUS из исходных кодов
# dnf groupinstall -y "Development Tools"
# dnf install -y gcc make readline-devel openssl-devel libtool pkg-config git python3 python3-devel sqlite-devel curl wget net-snmp-devel libxml2-devel popt-devel
# dnf install libtalloc-devel
Скачиваем пакет исходных кодов FreeRADIUS
# cd /usr/src
# wget https://github.com/FreeRADIUS/freeradius-server/releases/download/release_3_2_8/freeradius-server-3.2.8.tar.gz
# tar -xf freeradius-server-3.2.8.tar.gz
# cd freeradius-server-3.2.8
Конфигурируем сборку с поддержкой PostgreSQL
# ./configure \
--with-utils \
--with-postgresql-prefix=/usr/pgsql-16 \
CPPFLAGS="-I/usr/pgsql-16/include" \
LDFLAGS="-L/usr/pgsql-16/lib" \
PKG_CONFIG_PATH="/usr/pgsql-16/lib/pkgconfig" \
--sysconfdir=/etc/freeradius \
--localstatedir=/var/lib/freeradius \
--sbindir=/usr/sbin \
--with-user=freerad
В завешении листинга процесса конфигурирования должно отображаться:
<....>
rlm_sql ................. OK
rlm_sql_db2 ............. OK
rlm_sql_firebird ........ OK
rlm_sql_freetds ......... skipping (requires ctpublic.h libct)
rlm_sql_iodbc ........... skipping (requires libiodbc isql.h)
rlm_sql_mongo ........... OK
rlm_sql_mysql ........... skipping (requires libmysqlclient || libmysqlclient_r mysql.h)
rlm_sql_null ............ OK
rlm_sql_oracle .......... skipping (requires oci.h libclntsh libnnz(9-12))
rlm_sql_postgresql ...... OK
rlm_sql_sqlite .......... OK
rlm_sql_unixodbc ........ OK
rlm_sql_map ............. OK
rlm_sqlcounter .......... OK
rlm_sqlippool ........... OK
rlm_test ................ OK
<....>
Важно, что бы у пакета rlm_sql_postgresql был статус OK (rlm_sql_postgresql ...... OK)
Запуск сборки и установки:
# make clean
# make -j$(nproc)
# make install
# ldconfig
Далее необходимо провести первый запуск, что бы понять, что под root 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 39231
Listening on proxy address :: port 59954
Ready to process requests
Удаляем шаблоны, работающие по умолчанию default и inner-tunnel
# rm -f /etc/freeradius/raddb/sites-enabled/inner-tunnel
# rm -f /etc/freeradius/raddb/sites-enabled/default
Отключаем проксирование и вносим изменения в режим логирования:
# nano /etc/freeradius/raddb/radiusd.conf
Параметр proxy_requests ставим в "no" и комментируем директиву "$INCLUDE proxy.conf"
proxy_requests = no
#$INCLUDE proxy.conf
В секции log {...} прописываем параметры auth и timestamp:
auth = yes
timestamp = yes
Отключаем логирование модуля unix
# nano /etc/freeradius/raddb/mods-enabled/unix
Комментируем строку "radwtmp = ${logdir}/radwtmp"
#radwtmp = ${logdir}/radwtmp
Актируем функцию разбора Cisco AV Pair
# nano /etc/freeradius/raddb/mods-enabled/preprocess
with_cisco_vsa_hack = yes
Добавляем в словарь данные о типовых Cisco AV Pair для PPPoE подключений:
# nano /etc/freeradius/raddb/dictionary
Добавляем в конец:
ATTRIBUTE ppp-disconnect-cause 173 string
ATTRIBUTE disc-cause-ext 174 string
Создаем свой модуль работы с SQL: sql_sm
# touch /etc/freeradius/raddb/mods-available/sql_sm
# ln -s /etc/freeradius/raddb/mods-available/sql_sm /etc/freeradius/raddb/mods-enabled/sql_sm
Пока этот файл пустой.
Создаем шаблон для Cisco1001X на основе типового шаблона:
# cp /etc/freeradius/raddb/sites-available/default /etc/freeradius/raddb/sites-available/cisco1001X
# ln -s /etc/freeradius/raddb/sites-available/cisco1001X /etc/freeradius/raddb/sites-enabled/cisco1001X
Создаем пользователя под которым будет работать FreerADIUS
# groupadd freerad
# useradd -r -g freerad -s /sbin/nologin -d /var/lib/freeradius freerad
Даем пользователю права на логи:
# chown -R freerad:freerad /etc/freeradius/raddb/ /var/lib/freeradius
Проверяем еще раз запуск
# radiusd -X
Создаем unit systemd для FreeRADIUS:
# touch /etc/systemd/system/radiusd.service
# chmod +x /etc/systemd/system/radiusd.service
# ln -s /etc/systemd/system/radiusd.service /etc/systemd/system/multi-user.target.wants/radiusd.service
Наполнение юнита:
[Unit]
Description=FreeRADIUS multi-protocol policy server
After=network-online.target postgresql-16.service
[Service]
Type=forking
ExecStartPre=/usr/sbin/radiusd -Cx -lstdout
ExecStart=/usr/sbin/radiusd
PIDFile=/var/lib/freeradius/run/radiusd/radiusd.pid
User=freerad
Group=freerad
Restart=on-failure
RestartSec=5
ReadOnlyDirectories=/etc/freeradius/raddb/
ReadWriteDirectories=/var/lib/freeradius/log
PrivateTmp=true
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
Рестартуем демон systemd:
# systemctl daemon-reload
Теперь запуск сервера выполняем так:
# systemctl start radiusd.service
# systemctl status radiusd.service
# systemctl enable radiusd.service
Конфигурационные файлы FreeRADIUS тут /etc/freeradius/raddb/
Основной лог-файл: /var/lib/freeradius/log/radius/radius.log
Детальные accounting логи: /var/lib/freeradius/log/radius/radacct/
Для того что бы пользоваться без префикса утилитой radclient добавляем путь к утилите в переменные окружения:
# echo 'export PATH=$PATH:/usr/local/bin' >> ~/.bashrc
# source ~/.bashrc
Генерируем тестовый стартовый аккаутинговый пакет с помощью утилиты radclient:
# echo "User-Name = testuser, Acct-Status-Type = Start" | radclient -x localhost:1813 acct testing123
В ответ мы должны увидеть структурированный запрос и ответ сервера:
Sent Accounting-Request Id 87 from 0.0.0.0:39087 to 127.0.0.1:1813 length 36
User-Name = "testuser"
Acct-Status-Type = Start
Received Accounting-Response Id 87 from 127.0.0.1:1813 to 127.0.0.1:39087 length 20
В логах (/var/lib/freeradius/log/radius/radacct/127.0.0.1/detail-*) мы теперь должны видеть лог запроса.
Генерируем тестовый стоповый аккаутинговый пакет с помощью утилиты radclient.
Тут данные для формирования стопового пакета нужно записать в файл:
# cat > stoppak.txt << EOF
Acct-Status-Type = Stop
User-Name = samara260374
Acct-Session-Id = 1234567890
NAS-IP-Address = 192.168.1.1
NAS-Port = 1001
Acct-Session-Time = 3600
Acct-Terminate-Cause = User-Request
Acct-Input-Octets = 1048576
Acct-Output-Octets = 2097152
Acct-Input-Packets = 10000
Acct-Output-Packets = 15000
EOF
# radclient -x -4 10.0.1.52:1813 acct testing123 < stoppak.txt
В логах (/var/lib/freeradius/log/radius/radacct/127.0.0.1/detail-*) мы теперь должны увидеть лог стопового пакета.
Открываем в firewall порт 1813 для приема аккаутинговых пакетов:
# firewall-cmd --permanent --add-port=1813/udp
# firewall-cmd --reload
# firewall-cmd --list-all
Добавляем клиента (сетевое устройство) для работы с FreeRADIUS:
# nano /etc/freeradius/raddb/clients.conf
Добавляем:
client 10.10.0.2 {
ipaddr = 10.10.0.2
proto = *
secret = smtools123
shortname = ARS1001X_Samara
require_message_authenticator = yes
nas_type = cisco
}
# /usr/sbin/radiusd -C
# systemctl restart radiusd.service
Готовим базу данных PostgreSQL для приема аккаутинга:
# su - postgres
# psql
postgres=# CREATE DATABASE pppoelog;
postgres=# \c pppoelog;
postgres=# CREATE TABLE public.pppoelog_start_stop (
id bigserial NOT NULL,
nas_ip_address inet NULL,
cisco_nas_port text NULL,
session_id text NULL,
date_and_time timestamp NULL,
user_name text NULL,
mac macaddr NULL,
framed_ip_address inet NULL,
cisco_service_info text NULL,
acct_session_time int4 NULL,
acct_input_octets int8 NULL,
acct_output_octets int8 NULL,
acct_terminate_cause text NULL,
packet_type varchar(10) NULL,
acct_unique_session_id varchar(200) NULL,
CONSTRAINT pppoelog_start_stop_pkey PRIMARY KEY (id)
);
postgres=# CREATE INDEX i_date_and_time ON public.pppoelog_start_stop USING btree (date_and_time);
postgres=# CREATE INDEX i_framed_ip_address ON public.pppoelog_start_stop USING gist (framed_ip_address inet_ops);
postgres=# CREATE INDEX i_mac ON public.pppoelog_start_stop USING btree (mac);
postgres=# CREATE INDEX i_session_id ON public.pppoelog_start_stop USING btree (session_id);
postgres=# CREATE INDEX i_user_date_type_desc ON public.pppoelog_start_stop USING btree (user_name, packet_type, date_and_time DESC) WHERE ((packet_type)::text = 'stop'::text);
postgres=# CREATE INDEX i_user_name ON public.pppoelog_start_stop USING btree (user_name);
postgres=# CREATE USER pppoelog WITH ENCRYPTED PASSWORD 'superpassword';
postgres=# GRANT ALL privileges ON DATABASE pppoelog TO pppoelog;
postgres=# GRANT ALL ON pppoelog_start_stop TO pppoelog;
postgres=# GRANT USAGE ON SCHEMA public TO pppoelog;
postgres=# GRANT ALL ON ALL TABLES IN SCHEMA public TO pppoelog;
postgres=# GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO pppoelog;
postgres=# GRANT ALL ON ALL FUNCTIONS IN SCHEMA public TO pppoelog;
postgres=# GRANT ALL ON pppoelog_start_stop TO pppoelog;
postgres=# GRANT ALL ON SEQUENCE pppoelog_start_stop_id_seq TO pppoelog;
postgres=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO pppoelog;
postgres=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO pppoelog;
postgres=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO pppoelog;
postgres=# ALTER TABLE pppoelog_start_stop OWNER TO pppoelog;
postgres=# ALTER SEQUENCE pppoelog_start_stop_id_seq OWNER TO pppoelog;
postgres=# ALTER DEFAULT PRIVILEGES IN SCHEMA public OWNER TO pppoelog;
Формируем права доступа на базу данных:
# nano /var/lib/pgsql/16/data/pg_hba.conf
Вносим изменения:
# IPv4 local connections:
host all pppoelog 10.0.0.0/8 md5
Разрешаем прослушивание сетевых интерфейсов:
# nano /var/lib/pgsql/16/data/postgresql.conf
#listen_addresses = 'localhost' # what IP address(es) to listen on;
listen_addresses = '*'
Рестартуем базу:
# systemctl restart postgresql-16.service
Открываем доступ к базе по сети:
# firewall-cmd --permanent --add-port=5432/tcp
# firewall-cmd --reload
# firewall-cmd --list-all
Теперь активируем в экземпляре Freeradius модуль sql_sm
# nano /etc/freeradius/raddb/sites-enabled/cisco1001X
Вносим изменения в раздел "accounting"
accounting {
...
#-sql
sql_sm
...
}
Теперь заполняем данные для модуля SQL "sql_sm"
# nano /etc/freeradius/raddb/mods-enabled/sql_sm
sql sql_sm {
driver = "rlm_sql_postgresql"
dialect = "postgresql"
server = "10.0.1.52"
port = 5432
login = "pppoelog"
password = "superpassword"
radius_db = "pppoelog"
acct_table1 = "pppoelog_start_stop"
pool {
start = ${thread[pool].start_servers}
min = ${thread[pool].min_spare_servers}
max = ${thread[pool].max_servers}
spare = ${thread[pool].max_spare_servers}
uses = 0
retry_delay = 30
lifetime = 0
idle_timeout = 60
}
$INCLUDE /etc/freeradius/raddb/mods-config/sql/main/postgresql/queries_sqlsm.conf
}
В файле /etc/freeradius/raddb/mods-config/sql/main/postgresql/queries_sqlsm.conf необходимо прописать запросы для доступа к базе.
# touch /etc/freeradius/raddb/mods-config/sql/main/postgresql/queries_sqlsm.conf
# nano /etc/freeradius/raddb/mods-config/sql/main/postgresql/queries_sqlsm.conf
accounting {
reference = "%{tolower:type.%{%{Acct-Status-Type}:-none}.query}"
column_list = "\
nas_ip_address, \
cisco_nas_port, \
session_id, \
date_and_time, \
user_name, \
mac, \
framed_ip_address, \
cisco_service_info, \
acct_session_time, \
acct_input_octets, \
acct_output_octets, \
acct_terminate_cause, \
packet_type, \
acct_unique_session_id"
type {
accounting-on {
}
accounting-off {
}
start {
query = "\
INSERT INTO ${....acct_table1} \
(${...column_list}) \
VALUES(\
'%{NAS-IP-Address}', \
'%{Cisco-NAS-Port}', \
'%{Acct-Session-Id}', \
TO_TIMESTAMP(%{integer:Event-Timestamp}), \
'%{User-Name}', \
NULLIF('%{Calling-Station-Id}', '')::macaddr, \
NULLIF('%{Framed-IP-Address}', '')::inet, \
'%{Cisco-Service-Info}', \
0, \
0, \
0, \
'', \
'start', \
'%{Acct-Unique-Session-Id}')"
}
interim-update {
}
stop {
query = "\
INSERT INTO ${....acct_table1} \
(${...column_list}) \
VALUES(\
'%{NAS-IP-Address}', \
'%{Cisco-NAS-Port}', \
'%{Acct-Session-Id}', \
TO_TIMESTAMP(%{integer:Event-Timestamp}), \
'%{User-Name}', \
NULLIF('%{Calling-Station-Id}', '')::macaddr, \
NULLIF('%{Framed-IP-Address}', '')::inet, \
'%{Cisco-Service-Info}', \
NULLIF('%{Acct-Session-Time}', '')::bigint, \
(('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Input-Octets}:-0}'::bigint), \
(('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
'%{%{Acct-Output-Octets}:-0}'::bigint), \
'%{ppp-disconnect-cause}, %{disc-cause-ext}', \
'stop', \
'%{Acct-Unique-Session-Id}')"
}
none {
}
}
}
Рестартуем Freeradius:
# systemctl restart radiusd.service
Теперь аккаутинг должен записыватсья в базу данных PostgreSQL.
Нам больше не нужен лог файл с аккаутингом в файле.
# nano /etc/freeradius/raddb/sites-enabled/cisco1001X
Необходимо закомментировать модуль "detail" в секции "accounting"
accounting {
# Create a 'detail'ed log of the packets.
# Note that accounting requests which are proxied
# are also logged in the detail file.
#detail
...
}
И рестартовать Freeradius:
# systemctl restart radiusd.service