Добрый день!
Используем 5.3-004 без urfa + cisco в качестве pppoe
ip выдаются динамически из пула
помогите прикрутить freeradius вместо родного радиуса
может у кого есть рабочий вариант freeradius и биллинга?
freeradius utm5
тип подключения какой у вас?taf писал(а):Я сделал у нас связку freeradius+utm. Данные для авторизации берутся напрямую из ip_groups, аккаунтинг пишется в отдельную базу и в UTM никак не отображается (то есть ни в админке ни в л/к не видно ни сессий ни трафика). Работает на порядок надежнее родного радиуса.
могли бы поделиться конфигами freeradius на почту alexaaa@inbox.ru
-
- Сообщения: 4
- Зарегистрирован: Пн ноя 21, 2016 10:20
Добрый день. Не стал создавать новую тему, так как мой вопрос связан как раз со связкой utm5 и freeradius. С недавнего времени, когда на сервер доступа ломятся одновременно более 200-300 абонентов, freeradius просто перестает отвечать. Mikrotik пишет в логи, что timeout ответа от radius-сервера и не авторизует. Почему то при рестарте freeradius в первые несколько секунд он пропускает энное количество абонентов и снова перестает отвечать. В штатном режиме все работает хорошо, но если необходимо разорвать сессии (перезапустить pptp/l2tp к примеру) то при авторизации большого количества абонентов возникает данная ситуация. Базу Postgesql пылесосил, размер у нее не большой, отвечает она вроде шустро. Увеличение параметра max_request_time не помогает. Помогите, пожалуйста, в решении данной проблемы.
В лог пишет следующее:
В лог пишет следующее:
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 51800 - ID: 3 due to unfinished request 10
4324. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 43556 - ID: 5 due to unfinished request 10
4326. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 42499 - ID: 0 due to unfinished request 10
4321. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 57994 - ID: 6 due to unfinished request 10
4327. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 54593 - ID: 4 due to unfinished request 10
4325. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 42551 - ID: 2 due to unfinished request 10
4323. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 35950 - ID: 254 due to unfinished request
104319. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 40710 - ID: 1 due to unfinished request 10
4322. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 55948 - ID: 253 due to unfinished request
104318. Giving up on old request.
Jan 24 18:34:08 bill radiusd[20954]: Received conflicting packet from client "имя сервера доступа" port 43745 - ID: 252 due to unfinished request
104317. Giving up on old request.
У нас используется pppoe со статически назначенными адресами.alexaaa писал(а):тип подключения какой у вас?
могли бы поделиться конфигами freeradius на почту alexaaa@inbox.ru
В приложении архив с тремя файлами - хелпер на перл для прохождения процедуры авторизации и выдачи адресов, и схема и конфиг sql для аккаунтинга. Дольше всего пришлось поприседать вокруг аккаунтнговых запросов в конфиге. А, да, у нас помимо всего клиентам еще и v6 раздаются, что отразилось на криптах.
хелпер:
Код: Выделить всё
#!/usr/bin/perl
use strict;
use DBI;
use NetAddr::IP::Lite;
# use ...
# This is very important ! Without this script will not get the filled hashesh from main.
use vars qw(%RAD_REQUEST %RAD_REPLY %RAD_CHECK);
#use Data::Dumper;
# This is hash wich hold original request from radius
#my %RAD_REQUEST;
# In this hash you add values that will be returned to NAS.
#my %RAD_REPLY;
#This is for check items
#my %RAD_CHECK;
#
# This the remapping of return values
#
use constant RLM_MODULE_REJECT=> 0;# /* immediately reject the request */
use constant RLM_MODULE_FAIL=> 1;# /* module failed, don't reply */
use constant RLM_MODULE_OK=> 2;# /* the module is OK, continue */
use constant RLM_MODULE_HANDLED=> 3;# /* the module handled the request, so stop. */
use constant RLM_MODULE_INVALID=> 4;# /* the module considers the request invalid. */
use constant RLM_MODULE_USERLOCK=> 5;# /* reject the request (user is locked out) */
use constant RLM_MODULE_NOTFOUND=> 6;# /* user not found */
use constant RLM_MODULE_NOOP=> 7;# /* module succeeded without doing anything */
use constant RLM_MODULE_UPDATED=> 8;# /* OK (pairs modified) */
use constant RLM_MODULE_NUMCODES=> 9;# /* How many return codes there are */
# Global variables can persist across different calls to the module.
#
#
# {
# my %static_global_hash = ();
#
# sub post_auth {
# ...
# }
# ...
# }
my $dbh;
sub CLONE(){
$dbh = DBI->connect ("dbi:Pg:dbname=UTM_DATABASE;host=UTM_DATABASE_HOST",'UTM_DATABASE_USER', 'UTM_DATABASE_PASSWORD') or return RLM_MODULE_FAIL;
}
# Function to handle authorize
sub authorize {
# For debugging purposes only
&log_request_attributes;
# Here's where your authorization code comes
# You can call another function from here:
# &test_call;
my $query = $dbh->prepare("SELECT upass FROM ip_groups WHERE uname = LOWER('$RAD_REQUEST{'User-Name'}') AND is_deleted='0' LIMIT 1");
#&radiusd::radlog(1, "SELECT upass FROM ip_groups WHERE uname = LOWER('$RAD_REQUEST{'User-Name'}') AND is_deleted='0' LIMIT 1");
$query->execute();
my $row = $query->fetchrow_hashref;
#&radiusd::radlog(1, Dumper($row->{upass}));
$RAD_CHECK{'Cleartext-Password'} = $row->{upass};
# $RAD_CHECK{'Password'} = $row->{upass};
return RLM_MODULE_OK;
}
# Function to handle authenticate
sub authenticate {
# For debugging purposes only
# &log_request_attributes;
if ($RAD_REQUEST{'User-Name'} =~ /[[:^ascii:]]/i) {
# Reject user and tell him why
$RAD_REPLY{'Reply-Message'} = "Denied access by rlm_perl function";
return RLM_MODULE_REJECT;
} else {
# Accept user and set some attribute
$RAD_REPLY{'some-attribute'} = "null";
return RLM_MODULE_OK;
}
}
# Function to handle preacct
sub preacct {
# For debugging purposes only
# &log_request_attributes;
return RLM_MODULE_OK;
}
# Function to handle accounting
sub accounting {
# For debugging purposes only
# &log_request_attributes;
# You can call another subroutine from here
# &test_call;
return RLM_MODULE_OK;
}
# Function to handle checksimul
sub checksimul {
# For debugging purposes only
# &log_request_attributes;
return RLM_MODULE_OK;
}
# Function to handle pre_proxy
sub pre_proxy {
# For debugging purposes only
# &log_request_attributes;
return RLM_MODULE_OK;
}
# Function to handle post_proxy
sub post_proxy {
# For debugging purposes only
# &log_request_attributes;
return RLM_MODULE_OK;
}
# Function to handle post_auth
sub post_auth {
# For debugging purposes only
# &log_request_attributes;
my $query = $dbh->prepare(
"SELECT inet_ntoa_ipv6(ip,ip_ext) AS ip,
inet_ntoa_ipv6(mask,mask_ext) AS mask,
ip_type
FROM ip_groups
WHERE uname = LOWER('$RAD_REQUEST{'User-Name'}')
AND is_deleted = 0 ORDER BY ip_type");
$query->execute();
my $draft = $query->fetchall_arrayref;
for my $i ( 0 .. $#{$draft} )
{
if ($draft->[$i][2] == 256)
{
my $a = NetAddr::IP::Lite->new6($draft->[$i][0]."/".$draft->[$i][1]);
$RAD_REPLY{'Delegated-IPv6-Prefix'} = $a->network();
$RAD_REPLY{'Framed-IPv6-Prefix'} = $a->network();
}
else
{
$RAD_REPLY{'Framed-IP-Address'} = $draft->[$i][0];
$RAD_REPLY{'Framed-IP-Netmask'} = $draft->[$i][1];
}
}
$RAD_REPLY{'Session-Timeout'} = '604800';
return RLM_MODULE_OK;
}
# Function to handle xlat
sub xlat {
# For debugging purposes only
# &log_request_attributes;
# Loads some external perl and evaluate it
my ($filename,$a,$b,$c,$d) = @_;
&radiusd::radlog(1, "From xlat $filename ");
&radiusd::radlog(1,"From xlat $a $b $c $d ");
local *FH;
open FH, $filename or die "open '$filename' $!";
local($/) = undef;
my $sub = <FH>;
close FH;
my $eval = qq{ sub handler{ $sub;} };
eval $eval;
eval {main->handler;};
}
# Function to handle detach
sub detach {
# For debugging purposes only
# &log_request_attributes;
# Do some logging.
&radiusd::radlog(0,"rlm_perl::Detaching. Reloading. Done.");
}
#
# Some functions that can be called from other functions
#
sub test_call {
# Some code goes here
}
sub log_request_attributes {
# This shouldn't be done in production environments!
# This is only meant for debugging!
for (keys %RAD_REQUEST) {
&radiusd::radlog(1, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}");
}
}
Код: Выделить всё
sql {
#
# Set the database to one of:
#
# mysql, mssql, oracle, postgresql
#
database = "postgresql"
#
# Which FreeRADIUS driver to use.
#
driver = "rlm_sql_${database}"
# Connection info:
server = "UTM_DATABASE_HOST"
port = 5432
login = "UTM_DATABASE_USER"
password = "UTM_DATABASE_PASSWORD"
# Database table configuration for everything except Oracle
radius_db = "radius"
# If you are using Oracle then use this instead
# radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))"
# If you want both stop and start records logged to the
# same SQL table, leave this as is. If you want them in
# different tables, put the start table in acct_table1
# and stop table in acct_table2
acct_table1 = "radacct"
acct_table2 = "radacct"
# Allow for storing data after authentication
# postauth_table = "radpostauth"
# authcheck_table = "radcheck"
# authreply_table = "radreply"
# groupcheck_table = "radgroupcheck"
# groupreply_table = "radgroupreply"
# Table to keep group info
# usergroup_table = "radusergroup"
# If set to 'yes' (default) we read the group tables
# If set to 'no' the user MUST have Fall-Through = Yes in the radreply table
# read_groups = yes
# Remove stale session if checkrad does not see a double login
# deletestalesessions = yes
# Print all SQL statements when in debug mode (-x)
sqltrace = no
sqltracefile = ${logdir}/sqltrace.sql
# number of sql connections to make to server
#
# Setting this to LESS than the number of threads means
# that some threads may starve, and you will see errors
# like "No connections available and at max connection limit"
#
# Setting this to MORE than the number of threads means
# that there are more connections than necessary.
#
# num_sql_socks = ${thread[pool].max_servers}
num_sql_socks = 5
# number of seconds to dely retrying on a failed database
# connection (per_socket)
connect_failure_retry_delay = 60
# lifetime of an SQL socket. If you are having network issues
# such as TCP sessions expiring, you may need to set the socket
# lifetime. If set to non-zero, any open connections will be
# closed "lifetime" seconds after they were first opened.
lifetime = 0
# Maximum number of queries used by an SQL socket. If you are
# having issues with SQL sockets lasting "too long", you can
# limit the number of queries performed over one socket. After
# "max_qeuries", the socket will be closed. Use 0 for "no limit".
max_queries = 0
# Set to 'yes' to read radius clients from the database ('nas' table)
# Clients will ONLY be read on server startup. For performance
# and security reasons, finding clients via SQL queries CANNOT
# be done "live" while the server is running.
#
#readclients = yes
# Table to keep radius client info
# nas_table = "nas"
# Read driver-specific configuration
# $INCLUDE sql/${database}/dialup.conf
sql_user_name = "%{User-Name}"
accounting_onoff_query = "UPDATE ${acct_table1} \
SET Acct_Stop_Time = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
Acct_Session_Time = (EXTRACT(EPOCH FROM ('%S'::timestamp with time zone - \
Acct_Start_Time::timestamp with time zone - '%{%{Acct-Delay-Time}:-0}'::interval)))::BIGINT, \
Acct_Terminate_Cause = '%{Acct-Terminate-Cause}', \
Acct_Stop_Delay = 0 \
WHERE AcctStopTime IS NULL \
AND Nas_Ip_Address= '%{NAS-IP-Address}' \
AND Acct_Start_Time <= '%S'::timestamp"
accounting_update_query = "UPDATE ${acct_table1} \
SET Framed_IP_Address = NULLIF('%{Framed-IP-Address}', '')::inet, \
Framed_IPv6_Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
Acct_Session_Time = '%{Acct-Session-Time}', \
Acct_Input_Octets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
Acct_Output_Octets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
Acct_Input_Packets = ('%{%{Acct-Input-Packets}:-0}'::bigint), \
Acct_Output_Packets = ('%{%{Acct-Output-Packets}:-0}'::bigint) \
WHERE Acct_Session_Id = '%{Acct-Session-Id}' \
AND User_Name = '%{SQL-User-Name}' \
AND Nas_Ip_Address = '%{NAS-IP-Address}' \
AND Acct_Stop_Time IS NULL"
accounting_update_query_alt = "INSERT INTO ${acct_table1} \
(Acct_Session_Id, \
acct_unique_session_id, \
User_Name, \
Nas_Ip_Address, \
Nas_Port_Id, \
Nas_Port, \
Nas_Port_Type, \
Acct_Start_Time, \
Acct_Session_Time, \
Acct_Authentic, \
Acct_Input_Octets, \
Acct_Output_Octets, \
Called_Station_Id, \
Calling_Station_Id, \
Service_Type, \
Framed_Protocol, \
Framed_IP_Address, \
Framed_IPv6_Prefix) \
VALUES ( \
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
'%{NAS-IP-Address}', \
'%{NAS-Port-Id}', \
%{%{NAS-Port}:-NULL}, \
'%{NAS-Port-Type}', \
('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval - '%{%{Acct-Session-Time}:-0}'::interval), \
'%{Acct-Session-Time}', \
'%{Acct-Authentic}', \
(('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
(('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
NULLIF('%{Framed-IP-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Prefix}', '')::inet)"
accounting_start_query = "INSERT INTO ${acct_table1} \
(Acct_Session_Id, \
acct_unique_session_id, \
User_Name, \
Nas_Ip_Address, \
Nas_Port, \
Nas_Port_Id, \
Nas_Port_Type, \
Acct_Start_Time, \
Acct_Authentic, \
Called_Station_Id, \
Calling_Station_Id, \
Service_Type, \
Framed_Protocol, \
Framed_IP_Address, \
Framed_IPv6_Prefix, \
Acct_Start_Delay) \
VALUES ( \
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
'%{NAS-IP-Address}', \
%{%{NAS-Port}:-NULL}, \
'%{NAS-Port-Id}', \
'%{NAS-Port-Type}', \
('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
'%{Acct-Authentic}', \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
NULLIF('%{Framed-IP-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
0)"
accounting_start_query_alt = "UPDATE ${acct_table1} \
SET Acct_Start_Time = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
Acct_Start_Delay = 0, \
WHERE Acct_Session_Id = '%{Acct-Session-Id}' \
AND User_Name = '%{SQL-User-Name}' \
AND NAS_IP_Address = '%{NAS-IP-Address}' \
AND Acct_Stop_Time IS NULL"
accounting_stop_query = "UPDATE ${acct_table1} \
SET Acct_Stop_Time = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
Acct_Session_Time = CASE WHEN '%{Acct-Session-Time}' = '' THEN \
(EXTRACT(EPOCH FROM ('%S'::TIMESTAMP WITH TIME ZONE - Acct_Start_Time::TIMESTAMP WITH TIME ZONE \
- '%{%{Acct-Delay-Time}:-0}'::INTERVAL)))::BIGINT \
ELSE NULLIF('%{Acct-Session-Time}','')::BIGINT END, \
Acct_Input_Octets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
Acct_Output_Octets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
Acct_Terminate_Cause = '%{Acct-Terminate-Cause}', \
Acct_Stop_Delay = 0, \
Framed_IP_Address = NULLIF('%{Framed-IP-Address}', '')::inet, \
Framed_IPv6_Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet \
WHERE Acct_Session_Id = '%{Acct-Session-Id}' \
AND User_Name = '%{SQL-User-Name}' \
AND NAS_IP_Address = '%{NAS-IP-Address}' \
AND Acct_Stop_Time IS NULL"
accounting_stop_query_alt = "INSERT INTO ${acct_table1} \
(Acct_Session_Id, \
acct_unique_session_id, \
User_Name, \
NAS_IP_Address, \
NAS_Port, \
NAS_Port_Id, \
NAS_Port_Type, \
Acct_Start_Time, \
Acct_Stop_Time, \
Acct_Session_Time, \
Acct_Authentic, \
Acct_Input_Octets, \
Acct_Output_Octets, \
Called_Station_Id, \
Calling_Station_Id, \
Acct_Terminate_Cause, \
Service_Type, \
Framed_Protocol, \
Framed_IP_Address, \
Framed_IPv6_Prefix, \
Acct_Stop_Delay) \
VALUES ( \
'%{Acct-Session-Id}', \
'%{Acct-Unique-Session-Id}', \
'%{SQL-User-Name}', \
'%{NAS-IP-Address}', \
%{%{NAS-Port}:-NULL}, \
'%{NAS-Port-Id}', \
'%{NAS-Port-Type}', \
('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval - '%{%{Acct-Session-Time}:-0}'::interval), \
('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
NULLIF('%{Acct-Session-Time}', '')::bigint, \
'%{Acct-Authentic}', \
(('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
(('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
'%{Called-Station-Id}', \
'%{Calling-Station-Id}', \
'%{Acct-Terminate-Cause}', \
'%{Service-Type}', \
'%{Framed-Protocol}', \
NULLIF('%{Framed-IP-Address}', '')::inet, \
NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \
0)"
}
Код: Выделить всё
CREATE TABLE radacct (
rad_acct_id BIGSERIAL PRIMARY KEY,
user_name character varying(255) DEFAULT ''::character varying NOT NULL,
nas_ip_address inet DEFAULT '0.0.0.0'::inet NOT NULL,
nas_port integer DEFAULT 0 NOT NULL,
nas_port_id character varying(255),
nas_port_type character varying(32) DEFAULT ''::character varying NOT NULL,
service_type character varying(32) DEFAULT ''::character varying NOT NULL,
framed_protocol character varying(32) DEFAULT ''::character varying NOT NULL,
called_station_id character varying(255) DEFAULT ''::character varying NOT NULL,
calling_station_id character varying(255) DEFAULT ''::character varying NOT NULL,
acct_status_type character varying(32) DEFAULT ''::character varying NOT NULL,
acct_session_id character varying(64) NOT NULL,
acct_unique_session_id character varying(64) NOT NULL,
acct_authentic character varying(32),
acct_session_time bigint DEFAULT '0'::bigint NOT NULL,
acct_start_time timestamp with time zone,
acct_stop_time timestamp with time zone,
acct_input_octets bigint DEFAULT '0'::bigint NOT NULL,
acct_output_octets bigint DEFAULT '0'::bigint NOT NULL,
acct_input_packets bigint DEFAULT '0'::bigint NOT NULL,
acct_output_packets bigint DEFAULT '0'::bigint NOT NULL,
acct_terminate_cause character varying(32) DEFAULT ''::character varying NOT NULL,
acct_stop_delay integer,
framed_ip_address inet,
framed_ipv6_prefix inet,
acct_start_delay integer
);
ALTER TABLE ONLY radacct ADD CONSTRAINT radacct_acct_unique_session_id_key UNIQUE (acct_unique_session_id);
CREATE INDEX radacct_active_user_idx ON radacct USING btree (user_name, nas_ip_address, acct_session_id) WHERE (acct_stop_time IS NULL);
CREATE INDEX radacct_start_user_idx ON radacct USING btree (acct_start_time, user_name);
CREATE FUNCTION inet_ntoa_ipv6(ip bigint, ip_ext bigint) RETURNS text
LANGUAGE sql
AS $$
SELECT
LOWER(
CONCAT(
CASE
WHEN ip_ext != 0 THEN
CONCAT_WS(
':',
SUBSTR(LPAD(TO_HEX(ip_ext), 16, '0'), 1, 4),
SUBSTR(LPAD(TO_HEX(ip_ext), 16, '0'), 5, 4),
SUBSTR(LPAD(TO_HEX(ip_ext), 16, '0'), 9, 4),
RIGHT(LPAD(TO_HEX(ip_ext), 16, '0'), 4)
)
END,
CASE
WHEN ip_ext != 0 THEN
':'
END,
CASE
WHEN ip_ext != 0 THEN
CONCAT_WS(
':',
SUBSTR(LPAD(TO_HEX(ip), 16, '0'), 1, 4),
SUBSTR(LPAD(TO_HEX(ip), 16, '0'), 5, 4),
SUBSTR(LPAD(TO_HEX(ip), 16, '0'), 9, 4),
RIGHT(LPAD(TO_HEX(ip), 16, '0'), 4)
)
ELSE INET_NTOA(ip & x'ffffffff'::bigint)
END
)
)
as result
$$;