inet_contract_templates= Слушатель InetRadiusListener

Слушатель предназначен для обработки RADIUS-пакетов. Общие сведения о протоколе RADIUS доступны здесь.

Добавляется в контейнер следующим образом.

Код
<context name="radius">
    <!-- Cоздание процессора RADIUS-пакетов -->
 <bean name="radiusProcessor" class="ru.avantis.abilling.modules.inet.radius.InetRadiusProcessor"/>

 <!-- Служебный ScheduledExecutorService, необходимый для dataLogger -->
 <scheduledExecutorService name="hrlydtlggr" corePoolSize="1" />

 <!-- Cоздание dataLogger, сохраняющего RADIUS-пакеты на диск (только один экземпляр) -->
 <bean name="radiusDataLogger" class="ru.avantis.abilling.modules.inet.radius.RadiusHourlyDataLogger">
  <param name="scheduledExecutor">hrlydtlggr</param>
 </bean>

 <!-- Cоздание слушателя RADIUS-пакетов на порту с передачей ему процессора и dataLogger -->
 <bean name="radiusListener" class="ru.avantis.abilling.modules.inet.radius.InetRadiusListener">
  <constructor>
   <!-- Хост (интерфейс), на котором будет открыт сокет. Если пусто - на всех -->
   <param name="host" value=""/>
   <!-- Порт, на котором будет открыт сокет -->
   <param name="port" value="1812"/>
   <!-- Размер буфера приема слушателя -->
   <param name="recvBufferSize">512 * 1024</param>
   <!-- Рекомендуемый SO_RCVBUF-сокета -->
   <param name="soRCVBUF"></param>
   <!-- Количество потоков-обработчиков -->
   <param name="threadCount">10</param>
   <!-- Максимальное количество пакетов в очереди на обработку -->
   <param name="maxQueueSize">200</param>
   <!-- Передача процессора -->
   <param name="processor">radiusProcessor</param>
   <!-- Режим работы, RadiusListener.Mode.authentication -->
   <param name="mode">RadiusListener.Mode.authentication</param>
   <!-- Передача dataLogger -->
   <param name="dataLogger">radiusDataLogger</param>
  </constructor>
 </bean>
</context>

Параметры:

  • radiusProcessor - класс процессора, реализующий логику обработки пакетов;

  • radiusDataLogger - объект, осуществляющий запись бинарных логов, по умолчанию это объект типа ru.avantis.abilling.modules.inet.radius.RadiusHourlyDataLogger (сохранение бинарных логов с разбивкой по источникам и часам);

  • host - IP-адрес, на котором слушатель, пустое значение - прослушивать любой IP-адрес;

  • port - прослушиваемый UDP-порт;

  • soRCVBUF - рекомендуемый SO_RCVBUF (socket recieve buffer) для сокета. На FreeBSD большие значения могут вызвать ошибку и сервер не запустится;

  • byteBufferCapacity - размер буфера для приёма пакетов;

  • threadCount - число потоков-обработчиков пакетов, рекомендуемые значения 10-30, не рекомендуется указывать более 100;

  • maxQueueSize - максимальный размер очереди пакетов, при превышении размера очереди пакеты начинают отбрасываться и высылается аларм, рекомендуемые значения 200-1000. Следует учитывать, что если по какой-то причине сервер не успевает обрабатывать пакеты, очередь растет, то какие-то пакеты из очереди могут быть обработаны с опозданием и NAS уже выслал повторный запрос, который опять попадет в очередь и опять может быть обработан с опозданием. Поэтому большое значение вместо распределения нагрузки может вызвать ее увеличение;

  • mode - режим работы, может принимать значения RadiusListener.Mode.authentication для обработки Access-Request-пакетов в InetAccess и RadiusListener.Mode.accounting для обработки Accounting-пакетов в InetAccounting.

Процессор ru.avantis.abilling.modules.inet.radius.InetRadiusProcessor

Предназначен для авторизации и аккаунтинга по протоколу RADIUS большинства типов коммутируемых соединений.

Загружает список NAS’ов из дочерних узлов корневого узла сервера, начиная с самого корневого узла. Если нужно фильтовать по типам устройств (т.е. какие-то дочерние узлы не учитывать как NAS’ы), то в конфигурации корневого устройства в параметре radius.deviceTypeIds необходимо указать id типов устройств-NAS’ов через запятую. У устройства-NAS’а поле Идентификатор должно быть заполнено.

Поиск NAS’а для пришедшего пакета производится сначала по атрибуту NAS-Identifier с поиском по идентификатору устройства, затем, если устройство не найдено, по NAS-IP-Address с поиском по хостам устройств. Сессия сервиса привязывается к устройству, представляющему NAS.

Поиск сервиса/логина

При авторизации поиск сервиса Inet может осуществляться как по логину, так и по интерфейсу или VLAN’у. Для указания режима поиска необходимо прописать в конфигурации устройства-NAS’а или в конфиге любого его устройства-предка параметр:

# Режим поиска сервиса: 0 (по умолчанию) - по логину, 1 - по интерфейсу на устройстве (в предобработке должны быть
# проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или INTERFACE_ID), 2 - по VLAN на устройстве (в предобработке
# должны быть проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или VLAN_ID), 4 - по VLAN на устройстве или
# дочернем устройстве (в предобработке должны быть проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или VLAN_ID),
# 5 - по MAC-адресу на устройстве (в предобработке должна быть проставлена опция MAC_ADDRESS), 6 - по MAC-адресу на
# устройстве или дочернем устройстве (в предобработке должна быть проставлена опция MAC_ADDRESS).
radius.servSearchMode=0

radius.servSearchMode может принимать значения:

  • 0 - поиск по логину из атрибута User-Name;

  • 1 - поиск по интерфейсу на (найденном) устройстве;

  • 2 - поиск по VLAN’у на устройстве (в предобработке должны быть проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или VLAN_ID);

  • 4 - поиск по VLAN’у на устройстве и его дочерних устройствах (в предобработке должны быть проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или VLAN_ID);

  • 5 - поиск по MAC-адресу на устройстве (в предобработке должна быть проставлена опция MAC_ADDRESS);

  • 6 - поиск по MAC-адресу на устройстве и дочерних устройствах (в предобработке должна быть проставлена опция MAC_ADDRESS);

  • 7 - поиск по адресу, указанному в User-Name, из диапазона адресов сервиса (в типе сервиса должно быть указано serv.search.address=1);

  • 9 - поиск по адресу, указанному в User-Name, из диапазона адресов сервиса (в типе сервиса должно быть указано serv.search.address=1) на агентских (дочерних) устройствах;

  • 10 - поиск по MAC-адресу на всех устройствах.

Также возможен дополнительный поиск дочернего сервиса:

radius.servSearchMode=<servSearchMode>-<subServSearchMode>

<subServSearchMode> может принимать значения:

  • 0 или отсутсвует - нет поиска дочернего сервиса;

  • 1 - поиск дочернего сервиса по MAC-адресу, если такого дочернего сервиса нет - ошибка авторизации;

  • 2 - поиск дочернего сервиса по MAC-адресу, если такого дочернего сервиса нет - сессия будет привязана к родительскому сервису;

  • 5 - поиск дочернего сервиса по IP-адресу из поля User-Name, если такого дочернего сервиса нет - ошибка авторизации;

  • 6 - поиск дочернего сервиса по IP-адресу из поля User-Name, если такого дочернего сервиса нет - сессия будет привязана к родительскому сервису;

  • 7 - проверка IP-адреса из поля User-Name на совпадение с IP-адресом сервиса или поиск дочернего сервиса по IP-адресу, если не совпадает и такого дочернего сервиса нет - ошибка авторизации;

  • 8 - проверка IP-адреса из поля User-Name на совпадение с IP-адресом сервиса или поиск дочернего сервиса по IP-адресу, если не совпадает и такого дочернего сервиса нет - сессия будет привязана к родительскому сервису.

Например, radius.servSearchMode=1 - поиск по порту, radius.servSearchMode=2-1 - поиск по VLAN с проверкой MAC-адреса, radius.servSearchMode=2-7 - поиск по VLAN с проверкой IP-адреса.

Возможен последовательный поиск c разными режимами (если по первому режиму сервис не был найден - применяется следующий), для этого режимы нужно указать через запятую:

radius.servSearchMode=7,2

При поиске по логину поиск сервиса происходит по значению атрибута User-Name, по его совпадению с логином сервиса. После логина в атрибуте User-Name может быть указан реалм c разделителем @, например "vasya@local". Если реалм не указан, то предполагается, что пользователь использует реалм default. При этом принудительное указание реалма default (например, "vasya@default") не допускается.

По умолчанию перед поиском сервиса по логину из User-Name удаляется значение домена и не удаляются пробелы в начале и в конце. Также поиск идет с учетом регистра. Изменить поведение можно в конфигурации устройства (см. Пример конфигурации устройства-NAS’а).

Список допустимых реалмов указывается в параметре устройства/типа сервиса radius.realm через запятую, например:

#radius.realm=default
radius.realm=default, local

Параметр может быть указан как в конфигурации устройства (или типа устройтва), так и в конфигурации типа сервиса - в последнем случае значение будет главнее, чем тот же параметр в конфигурации устройства. По умолчанию допускается только реалм default.

При поиске по интерфейсу или VLAN’у, сервис может быть привязан к дочернему для NAS’а устройству - например, в случае Cisco ISG или Redback CLIPS - сервис привязан к коммутатору, NAS’ом выступает маршрутизатор. В этом случае необходимо в предобработке RADIUS-запроса установить опцию AGENT_REMOTE_ID со значением идентификатора дочернего коммутатора. Если опция будет присутствовать и такое дочернее устройство существует, то поиск сервиса будет идти относительно этого агентского устройства, иначе, по умолчанию, поиск идет относительно устройства-NAS’а.

request.setOption( InetRadiusProcessor.AGENT_REMOTE_ID, "1CBDB9E64878" );

Данную опцию необходимо устанавливать как в preprocessAccessRequest, так и в preprocessAccountingRequest. Значение обычно извлекается из RADIUS-атрибутов запроса, содержащих, например, значение субопций DHCP option 82. Значение можно установить как строкой, так и массивом байт (byte[]). В случае, если опция установлена в предобработке запроса, будет произведен поиск агентского устройства на совпадение с полем Идентификатор.

Также возможна схема с несколькими NAS’ами, работающими параллельно, в этом случае ветку с устройствами коммутаторами нужно завести отдельно (не делать ее дочерней по отношению к одному из устройств-NAS’ов), а в конфигурации устройств-NAS’ов указать параметр device.agentDeviceRootId=<x>, где <x> - ID устройства-папки, в котором находится подветка с коммутаторами:

Схема

Для определения интерфейса или VLAN возможны два способа: установка опции AGENT_CIRCUIT_ID или установка напрямую опции INTERFACE_ID/VLAN_ID. В первом случае значение номера интерфейся или VLAN из опции будет извлечено по параметрам конфигурации агентского устройства dhcp.option82.interfaceId.position, dhcp.82.interfaceId.length, dhcp.option82.vlanId.position, dhcp.option82.vlanId.length. Во втором - значение должно быть равно интерфейсу или порту.

Пример (установка опций из атрибутов-значений субоций DHCP option 82, данный код есть в обработчиках, которые входят в дистрибутив модуля):

RadiusAttribute<?> agentRemoteId = request.getAttribute( 2352, 96 );
if( agentRemoteId != null )
{
  ByteBuffer data = agentRemoteId.getData();
  data.position( 2 );
  data = data.slice();

  request.setOption( InetRadiusProcessor.AGENT_REMOTE_ID, data );
}

RadiusAttribute<?> agentCircuitId = request.getAttribute( 2352, 97 );
if( agentCircuitId != null )
{
  ByteBuffer data = agentCircuitId.getData();
  data.position( 2 );
  data = data.slice();

  // значение интерфейса или VLAN'а будет извлечено из этого параметра
  request.setOption( InetRadiusProcessor.AGENT_CIRCUIT_ID, data );
}

Пример (vlan per user - поиск по vlan):

/*
// Если агентское устройство всегда известно - раскомментарить, режим поиска 2;
// иначе - режим поиска 4 (по vlan с учетом всех дочерних устройств)
RadiusAttribute<?> agentRemoteId = request.getAttribute( 2352, 96 );
if( agentRemoteId != null )
{
  ByteBuffer data = agentRemoteId.getData();
  data.position( 2 );
  data = data.slice();

  request.setOption( InetRadiusProcessor.AGENT_REMOTE_ID, data );
}*/

Pattern vlanPattern = Pattern.compile( "(.+) vlan-id (\\d+)" );

String nasPortId = request.getStringAttribute( -1, 87, null );
if( nasPortId != null )
{
  Matcher m = vlanPattern.matcher( nasPortId );
  if( m.find() )
  {
    String vlanId = m.group( 2 );
    request.setOption( InetRadiusProcessor.VLAN_ID, vlanId );
  }
}

Таким образом для поиск сервиса возможен:

  • по атрибуту User-Name (по умолчанию);

  • по опциям AGENT_REMOTE_ID (идентификатор агентского устройства - устройства, на котором, собственно, интерфейс) и INTERFACE_ID (или AGENT_CIRCUIT_ID, содержащий номер интерфейса);

  • по опциям AGENT_REMOTE_ID (не обязательна, если в пределах NAS’а VLAN уникальны) и VLAN_ID (или AGENT_CIRCUIT_ID, содержащий номер VLAN'а).

При аутентификации во всех случаях происходит проверка пароля, поэтому в некоторых случаях пароль нужно устанавливать на NAS’е, в коде preprocessAccessRequest или, при необходимости, отключить проверку пароля для NAS’а:

# Включение (1, по умолчанию) или отключение (0) проверки пароля для NAS'а
#radius.password.verification=1

RADIUS-атрибуты

Когда сервис определён, определяется набор атрибутов сессии, последовательным добавлением:

  • атрибутов, определённых для реалма;

  • атрибутов, определенных для сервиса(логина);

  • атрибутов, определённых для опций.

Атрибуты задаются перечислением <имя атрибута>=<значение> через точку с запятой, если в значении атрибута должна присутствовать точка с запятой (т.е. это не разделение двух разных атрибутов), то её нужно указать два раза: ";;".

Атрибуты реалма

Атрибуты реалма определяются в конфигурации устройства-NASа следующим образом:

radius.realm.<realm>.attributes=<attributes>

Где:

  • <realm> - реалм;

  • <attributes> - атрибуты.

Пример:

Пример
radius.realm.default.attributes=Acct-Interim-Interval=300;Session-Timeout=604800

Есть возможность добавлять динамические атрибуты, с помощью макросов:

radius.realm.<realm>.attributes.macros=<attributes>

radius.realm.default.attributes.macros=Interface-Name=$ipParam(ifaceName)

Запись атрибутов производится в таком же виде, как и в параметрах radius.realm.<realm>.attributes, однако здесь поддерживаются макросы вида $имя или $имя(параметр1,параметр2), например:

radius.realm.default.attributes.macros=Interface-Name=$ipParam(ifaceName)

Поддерживаются следующие макросы:

  • $ipGate - значение поля "Роутер" IP-ресурса, из которого выдан IP-адрес;

  • $ipDns - значение поля "DNS" IP-ресурса, из которого выдан IP-адрес;

  • $ipSubnetMask - значение поля "Маска подсети" IP-ресурса, из которого выдан IP-адрес;

  • $ipParam(name) - значение параметра конфигурации IP-ресурса, из которого выдан IP-адрес, аргумент макроса - имя параметра, например $ipParam(ifaceName) вернет значение параметра ifaceName= конфигурации IP-ресурса;

  • $param($device,name,default) - значение параметра конфигурации устройства-NAS’а или агентского устройства (коммутатора), указывается так: $param($device,myParam,myDefault) или $param($agentDevice,myParam,myDefault);

  • $requestAttribute(vendor,type) или $requestAttribute(name) - значение атрибута из запроса, например $requestAttribute(User-Name).

Атрибуты опций

Полный набор опций сессии определяется объединением опций, указанных в самом сервисе и опций из тарифного плана. Соответствие кодов опций атрибутам определяется в конфигурации устройства-NASа следующим образом:

radius.inetOption.<option_id>.attributes=<attributes>

Где:

  • <option_id> - числовой код опции;

  • <attributes> - RADIUS атрибуты.

Пример конфигурации, где определены атрибуты для реалмов и опций:

radius.realm.default.attributes=Service-Name:1=RSE-SVC-EXT;Service-Options:1=1

radius.inetOption.1.attributes=Service-Parameter:1=Rate=100000 Burst=12500000
radius.inetOption.2.attributes=Service-Parameter:1=Rate=100000 Burst=12500000

Для удобства указания однотипных наборов атрибутов, например, для указания атрибутов скорости можно использовать шаблоны. Для этого опции скорости должны находиться в одной родительской опции (которую можно назвать, например, "Скорость"). В конфигурации устройства нужно будет указать:

radius.inetOption.<parent_option_id>.template=Service-Parameter:1=Rate=$rate Burst=$burst

где <parent_option_id> - ID родительской опции ("Скорость").

В конфигурации опций-скоростей необходимо указать необходимые значения rate= и burst=. Таким образом отпадает необходимость указания практически одинакового набора атрибутов для каждой опции-скорости в конфигурации устройства, достаточно лишь прописать один раз шаблон. Также значения параметров можно прописать в конфигурации родительской опции, для того чтобы использовать как значения по умолчанию (если значение не переопределено в дочерней опции) или просто как самостоятельную переменную шаблона.

Атрибуты сервиса/логина

Атрибуты специфичные для типа сервиса можно прописать в конфигурации типа сервиса:

serv.radius.realm.default.attributes=

При необходимости выдавать специфичные атрибуты (значения) индивидуально для сервиса, в конфигурации типа сервиса укажите

param.myParam.title=Мой параметр

Теперь на вкладке "Дополнительно" в редакторе сервиса на договоре можно будет добавить данный параметр, указав его значение. Теперь этот параметр можно использовать при выдаче RADIUS-атрибутов, прописав в конфигурации типа сервиса, в том же параметре serv.radius.<realm>.default.attributes атрибут с помощью макроса:

serv.radius.realm.default.attributes=My-Attribute=$myParam

Выдача IP-адреса

Выдача IP-адреса производится через атрибут Framed-IP-Address из диапазона (адреса), указанного в самом сервисе на договоре (т.е. выдача статического IP-адреса), либо, если адрес в сервисе не указан или занят другой сессий этого же сервиса - из пула, определённого в конфигурации устройства параметром radius.realm.<realm>.ipCategories=<cat_codes>, где:

  • <realm> - реалм;

  • <cat_codes> - id коды категорий ресурсов IP-адресов через запятую.

Например, выдача динамических адресов из категории IP-ресурсов с кодом 4:

radius.realm.default.ipCategories=4

Вы также можете выдавать адреса из разных пулов в зависимости от активной опции Inet, указав опцию в тарифе или статически в сервисе на договоре. Таким образом, можно в зависимости от различных условий выдавать адреса из разных подсетей (для ситуации, когда баланс меньше лимита смотрите ниже Reject-To-Accept). Благодаря гибкости тарифа можно выдавать адреса из разных пулов в зависимости от баланса, активных тарифных опций, групп договоров, времени, периода и других условий.

Для этого в конфигурации устройства-NAS’а или корневого устройства укажите именованный пул адресов. Пул состоит из имени и перечисления id категорий ресурсов IP-адресов через запятую: resource.ip.pool.<name>.ipCategories=<cat_codes>

resource.ip.pool.whitePool.ipCategories=5

Далее создайте опции Inet, например, создав опцию-ветку "Пулы IP-адресов" и внутри нее опцию "Белый пул IP-адресов". В конфигурации устройства или типа устройства-NAS’а или же корневого устройства укажите привязку данной опции к пулу IP-адресов, например, если у созданной опции "Белый пул IP-адресов" ID=72:

radius.inetOption.72.ipPool=whitePool

Теперь, если в сервисе договора будет активна (с помощью тарифа или указана статически в сервисе) опция "Белый пул IP-адресов", то адрес будет выдаваться из пула whitePool, который состоит из IP-адресов категорий, указанных в параметре resource.ip.pool.whitePool=, т.е. в данном примере - из категории IP-ресурсов с ID=5. Если же опция будет не активна - то адрес будет выдан из параметра radius.realm.<realm>.ipCategories=<cat_codes>, если он указан.

Также вместо указания списка IP-категорий для реалма можно воспользоваться указанием имени пула, т.е. вместо radius.realm.default.ipCategories=4 указать, например:

resource.ip.pool.greyPool.ipCategories=4
radius.realm.default.ipPool=greyPool

При использовании схем IPoE возможна ситуация, когда с Cisco/SE приходит подряд несколько Access-Request’ов. Например, абонентский DHCP-клиент шлет сразу несколько DHCP-Discover-пакетов, или в Cisco инициация сессии срабатывает не только на DHCP-Discover, но и на DHCP-Request. По умолчанию для динамической выдачи IP-адресов InetAccess на каждый Access-Request выдает Access-Accept с новым IP-адресом, что может быть проблемой для связки DHCP-клиент+Cisco/SE. В этом случае можно использовать параметр radius.address.authReserveTimeout. При выдаче адреса он будет запоминаться по ключу сервис+устройство-NAS+(агентское_устройство)User-Name(MAC-address)(CallingStationId)(identifier) и в течении указанного времени (в миллисекундах) на очередной Access-Request с таким же ключом будет предлагать тот же адрес.

# Кэширование выданного абоненту IP-адреса по ключу (для IPoE), по умолчанию - 0 (выкл)
radius.address.authReserveTimeout=3000

Выдача статической подсети

Для того, чтобы в Access-Accept биллинг выдавал подсеть в виде атрибутов Framed-IP-Address и Framed-IP-Netmask, то в типе сервиса нужно указать "Тип адреса": "статическая сеть", а также добавить в конфигурации типа сервиса:

# Выдаем в Access-Accept всю подсеть сервиса в виде Framed-IP-Address=<net> и Framed-IP-Netmask=<mask>
serv.radius.staticSubnet=1

Не выдавать адрес из диапазона сервиса

Возможен случай, когда в сервисе или дочернем сервисе нужно указать IP-адрес, диапазон или подсеть, которые будут нужны только для управления. Т.е. задача в том, чтобы из данного сервиса IP-адрес не выдавать. Например, в родительском сервисе мы указываем подсеть, а в дочерних сервисах - разрешенные абоненту IP-адреса из этой подсети (т.е. абонент должен получать адрес из дочерних сервисов, а не из родительского). Для того, чтобы адрес из сервиса не выдавался, в конфигурации типа сервиса нужно указать:

# Не выдаем IP-адреса из диапазона этого сервиса
serv.radius.skipStaticAddress=1

Не добавлять Framed-IP-Address в Access-Accept

В некоторых схемах, например, IP Subscriber, не требуется выдача IP-адреса в Access-Accept, т.к. IP-адрес у абонента уже есть, и адрес в сервисе указан только для того, чтобы найти абонента по нему при запросе Access-Request. В этом случае в конфигурации типа сервиса нужно указать:

# Не добавляем Framed-IP-Address в Access-Accept
serv.radius.noAddress=1

Выдача Framed-Route

Для того, чтобы выдавать в Access-Accept абоненту атрибут Framed-Route нужно создать тип сервиса, который будет дочерним, в поле "Тип адреса" выбрать значение "статическая сеть", указать в конфигурации типа сервиса:

# Данный сервис используется для указания Framed-Route
serv.radius.framedRoute=1

Reject-To-Accept

В случае ошибки авторизации высылается пакет AUTHENTICATION_REJECT с отображением ошибки и её кода в мониторе модуля. Допустимые коды ошибок данного процессора.

Вместо AUTHENTICATION_REJECT может быть выслан AUTHENTICATION_ACCEPT-пакет с дополнительными атрибутами. Перечень кодов ошибок, для которых производится подмена Reject-To-Accept определяется переменной конфигурации NAS’а radius.disable.accessCodes=<codes>, где <codes> - перечень кодов ошибок авторизации через запятую. Например:

radius.disable.accessCodes=1,2,3,4,10,11,12

Соответственно, для Reject-To-Accept могут быть собственные диапазоны IP-адресов, например:

radius.disable.ipCategories=3

Если же нужно выдавать статический IP-адрес такой же, как при обычном доступе (также, как когда не возникает ошибок авторизации), нужно указать режим:

# Режим выдачи статического адреса при ошибке авторизации:
# 0 (по умолчанию) - выдавать динамический адрес из категорий radius.disable.ipCategories,
# 1 - выдавать статический адрес как при удачной авторизации
radius.disable.mode=1

Если нужно выдавать динамический IP-адрес такой же, как при обычном доступе - то нужно прописать в radius.disable.ipCategories те же самые пулы.

При ошибке авторизации, атрибуты выдаются из параметра radius.disable.attributes:

# Атрибуты, выдаваемые при ошибке авторизации
radius.disable.attributes=
# атрибуты, выдаваемые при ошибке авторизации с кодом 1 (сервис/логин не найден), 2 или 3
#radius.disable.1,2,3.attributes=
# атрибуты с использованием макросов
#radius.disable.attribute.macros=

Атрибуты из опций Inet в данном режиме не выдаются.

Для поддержки Reject-To-Accept при ошибке с кодом 1 (Логин не найден), т.е. для предоставления гостевого доступа, необходимо создать договор с балансом меньше лимита и сервисом модуля Inet со статусом закрыт, а id сервиса прописать в конфигурации устройства:

radius.disable.servId=<inetServId>

Таким образом, сессии с ненайденным сервисом будут привязываться к указанному сервису.

При превышении числа сессий над ограничением, установленным для сервиса, генерируется ошибка авторизации. Данная ошибка также может быть обработана механизмом Reject-To-Accept с выдачей адреса из пула фиктивных адресов.

MAC-адрес и идентификатор

При RADIUS Access-Request можно также использовать MAC-адрес, чтобы авторизовывать запросы только с определенным MAC-адресом. MAC-адрес из Access-Request пакета устанавливается в Обработчике процессора протокола, в методе preprocessAccessRequest: request.setOption( InetRadiusProcessor.MAC_ADDRESS, macAddress ). Стандартные обработчики процессора протокола, поставляемые с модулем уже реализуют этот функционал, нужно только прописать в конфигурации устройства или типа устройства:

# Вендор атрибута, где хранится MAC-адрес
radius.macAddress.vendor=-1
# Код атрибута, где хранится MAC-адрес
radius.macAddress.type=31
# Префикс атрибута (если есть), где хранится MAC-адрес. Например, для cisco avpair
#radius.macAddress.prefix=client-mac-address=

Или:

# Вендор атрибута, где хранится MAC-адрес
radius.macAddress.vendor=9
# Код атрибута, где хранится MAC-адрес
radius.macAddress.type=1
# Префикс атрибута (если есть), где хранится MAC-адрес. Например, для cisco avpair
radius.macAddress.prefix=client-mac-address=

Таким образом, при извлечении MAC-адреса из RADIUS-пакета, он будет сравнен с MAC-адресом из аутентифицированного сервиса при условии, что в этом сервисе заведен MAC-адрес.

Для автоматического привязывания MAC-адреса к сервису в конфигурации модуля/типа сервиса/устройства/типа устройства можно прописать:

# Нужно ли автоматически проставлять в сервис MAC-адрес, если его еще нет.
# Можно указать в конфигурации модуля, конфигурации устройства, конфигурации типа сервиса.
# 0 - не привязывать, 1 - привязывать, если поле сервиса пустое, 2 - перетирать новым значением, 3 - добавлять
# (в последних двух случаях отказа в авторизации по MAC-адресу не будет)
serv.macAddress.auto=1

Таким образом при первой удачной авторизации MAC-адрес будет привязан к сервису и с другим MAC-адресом клиент уже не сможет авторизоваться.

Аналогично MAC-адресу можно использовать поле Идентификатор сервиса. Например, в качестве идентификатора использовать значение атрибута Calling-Station-Id, устанавливая в Обработчике процессора протокола, в методе preprocessAccessRequest: request.setOption( InetRadiusProcessor.IDENTIFIER, callingStationId ).

Для автоматического привязывания идентификатора к сервису в конфигурации модуля/типа сервиса/устройства/типа устройства можно прописать:

# Нужно ли автоматически проставлять в сервис идентификатор, если его еще нет.
# Можно указать в конфигурации модуля, конфигурации устройства, конфигурации типа сервиса.
# 0 - не привязывать, 1 - привязывать, если поле сервиса пустое, 2 - перетирать новым значением, 3 - добавлять
# (в последних двух случаях отказа в авторизации по идентификатору не будет)
serv.identifier.auto=1

Calling-Station-Id

Атрибут Calling-Station-Id используется для подстановки в поле сессии "С номера". При отсутствии данного атрибута можно настроить, чтобы обработчик процессора протокола (CoAProtocolHandler, SmartEdgeProtocolHandler, ISGProtocolHandler и другие) при предобработке RADIUS-запроса устанавливал значение в данный атрибут из другого, например, из атрибутра Mac-Address Redback (ID вендора 2352, ID типа атрибута 145):

# Копирование значения в атрибут Calling-Station-Id.
# ID вендора RADIUS-атрибута
radius.callingStationId.vendor=2352
# Тип RADIUS-атрибута
radius.callingStationId.type=145
# Префикс RADIUS-атрибута, если присутствует (будет удален из строки)
#radius.callingStationId.prefix=

Привязка сервиса к NAS’у или ветке NAS’ов

Для привязки сервиса к устройству - т.е. для того, чтобы клиент мог авторизоваться только на устройстве (NAS’е), привязанному к сервису, или являющимся дочерним по отношению к нему (устройству), необходимо указать в конфигурации устройства/типа устройства/типа сервиса:

# Привязка авторизации сервиса к устройству, указанному в сервисе договора
# 0 - клиент может авторизоваться на любом устройстве (NAS'е), 1 - клиент может авторизоваться только на прописанном в сервисе устройстве,
# 2 - клиент может авторизоваться только на прописанном в сервисе устройстве или являющимся дочерним по отношению к нему
serv.device.link=2

Действие при получении Access-Request при наличии активной сессии

При подключении абонента может быть ситуация, когда в биллинге сессия еще активна, а клиент на самом деле уже отключился и пытается подключиться заново. Это может произойти при потере связи с NAS’ом (т.е. STOP-пакет не пришел, но connection.close.timeout еще не произошел), или, например, при использовании IPoE с Cisco/Redback (когда абонент подключил другое устройство, а Cisco/Redback по таймауту DHCP-lease еще не поняли, что старое соединение можно закрывать). Для обработки такой ситуации можно использовать параметр конфигурации radius.connection.checkDuplicate. Он работает в связке с Calling-Station-Id - если происходит попытка авторизации, а количество активных соединений превышено и среди активных соединений есть соединение с таким же Calling-Station-Id, то при указании radius.connection.checkDuplicate:

  1. Происходит попытка сброса старого соединения (например, отправка PoD-пакета), абонента на этой авторизации не пускаем;

  2. Происходит попытка сброса старого соединения, его завершение в биллинге, абонента на этой авторизации не пускаем, должно пустить при следующей попытке, т.к. старой сессии уже не будет;

  3. Происходит завершение старого соединения в биллинге, абонента на этой авторизации не пускаем, должно пустить при следующей попытке, т.к. старой сессии уже не будет;

  4. Происходит попытка сброса старого соединения, затем через 5 секунд завершение в биллинге, абонента на этой авторизации не пускаем;

  5. Попытка сброса старого соединения в биллинге, завершение и пускаем немедленно (т.е. игнорируется ошибка );

  6. Завершение старого соединения в биллинге, пускаем абонента немедленно;

  7. Попытка в течении 5 секунд сбросить соединение, затем закрытие сессии в биллинге с ожиданием полного выполнения закрытия (т.е. IP-адрес станет свободным), пускаем абонента

  8. Попытка сброса и сразу закрытие в биллинге с ожиданием полного выполнения закрытия (т.е. IP-адрес станет свободным), пускаем абонента;

  9. Закрытие старого соединения в биллинге с ожиданием полного выполнения закрытия (т.е. IP-адрес станет свободным), пускаем абонента.

Для более быстрого подключения абонента при использовании и динамическим адресом рекомендуем использовать 4, 5, 6. Для статических адресов (чтобы абонент мог получить свой адрес) - 8,9.

Для обработки ситуации, когда количество активных соединений превышено, но соединения с таким Calling-Station-Id не найдено, и нужно отключить просто самое старое соединение, нужно указать цифру во втором разряде, например: 88.

Для сброса соединения с таким же Calling-Station-Id, даже если количество соединений не превышено, нужно указать цифру в третьем разряде, например, 808, 909, 888 или 818.

Этот параметр можно указать для типа сервиса, в конфигурации типа сервиса: serv.radius.connection.checkDuplicate.

В некоторых IPoE-схемах для обработки этого событие требуется использовать не Calling-Station-Id, а User-Name. Для этого нужно указать параметр radius.connection.checkDuplicate.type=1. В этом режиме будет проверяться User-Name из Access-Request с полем username сессии. Этот параметр можно указать для типа сервиса, в конфигурации типа сервиса: serv.radius.connection.checkDuplicate.type.

Т.к. параметр 8 и 9 (закрытие в биллинге с ожиданием полного выполнения закрытия, т.е. IP-адрес станет свободным) ожидает полного завершения соединения в биллинге, а необходимо такое ожидание только для некоторых схем, например, статических адресов, то рекомендуется задавать этот параметр в типе сервиса. Например, в конфигурации NAS’а radius.connection.checkDuplicate=5, в конфигурации типа сервиса для статических адресов radius.connection.checkDuplicate=8.
Без атрибута Calling-Station-Id в Access-Request-пакете данная функция работать не будет. При невозможности присылать Calling-Station-Id в Access-Request можно настроить подмену в обработчике процессора протокола (в предобработке RADIUS-запросов).

Блокировка частых Access-Request → Access-Reject

Спам-запросы на авторизацию порождаются, обычно, забытым оборудованием, самостоятельно предпринимающем попытки авторизации на RADIUS. Постоянные обращения при таких запросах могут существенно повышать загрузку. Признаком спам-запроса являются несколько Reject-ответов на одинаковые запросы авторизации в течение определённого интервала времени. В этом случае подобные запросы попадают в спам-кэш на определённое время и по ним автоматически выдаётся Reject-ответ без полных проверок, производимых при авторизации. Для включения антиспам-системы в конфигурации модуля добавьте (требуется перезапуск InetAccess):

antispam.key.attributes=<key_attributes>
antispam.reject.count=<reject_count>
antispam.reject.per.time=<per_time>
antispam.ban.time=<ban_time>

Где:

  • <key_attributes> - RADIUS-атрибуты, идентифицирующие запрос, через запятую;

  • <reject_count> - количество Reject, возвращённых на запрос с одинаковыми идентифицирующими атрибутами;

  • <per_time> - за какое количество секунд выдано указанное в <reject_count> количество Reject-ответов;

  • <ban_time> - время в секундах, на которое данный запрос попадает в спам-базу.

Например, запрос идентифицируется атрибутами User-Name и Calling-Station-Id. При десяти Reject-ответах в течении минуты запрос попадает в спам-базу на полчаса.

antispam.key.attributes=User-Name,Calling-Station-Id
antispam.reject.count=10
antispam.reject.per.time=60
antispam.ban.time=900

Посервисный аккаунтинг

Посервисный аккаунтинг

Для поддержки посервисного аккаунтинга (например, при использовании Cisco ISG или Redback CLIPS) в обработчике процессора протокола необходимо указывать AcctSessionId родительского соединения (аккаунтинга) и имя сервиса (ServiceName), по которому пришел аккаунтинг-пакет: request.setOption( InetRadiusProcessor.PARENT_ACCT_SESSION_ID, parentAcctSessionId ); и request.setOption( InetRadiusProcessor.SERVICE_NAME, serviceName );

Пример для Redback SmartEdge 100:

Код
@Override
public void preprocessAccountingRequest( RadiusPacket request, RadiusPacket response, ConnectionSet connectionSet )
    throws Exception
{
    int acctStatusType = request.getIntAttribute( -1, RadiusDictionary.Acct_Status_Type, -1 );

    switch( acctStatusType )
    {
        // если сервисный аккаунтинг
        case 101:
        case 102:
        case 103:
        {
            // получаем id родительского соединения
            final String parentAcctSessionId = request.getStringAttribute( -1, parentAcctSessionIdType, null );
            // получаем имя сервиса, по которому идет аккаунтинг
            final String serviceName = request.getStringAttribute( radiusVendor, serviceNameType, null );

            // подменяем Acct-Status-Type, чтобы биллинг понял типы пакетов
            request.setIntAttribute( -1, RadiusDictionary.Acct_Status_Type, acctStatusType - 100 );
            // устанавливаем id родительской сессии
            request.setOption( InetRadiusProcessor.PARENT_ACCT_SESSION_ID, parentAcctSessionId );
            // устанавливаем имя сервиса текущего аккаунтинга
            request.setOption( InetRadiusProcessor.SERVICE_NAME, serviceName );
        }
            break;

        default:
        {
        }
            break;
    }
}

Тогда Accounting считает данное соединение как дочернее родительскому, а в поле username соединения (в базе) устанавливается ServiceName.

При обработке трафиков используется ServiceName - он может выступать в качестве фильтра правила привязки трафиков: если указано ServiceName, то данное правило будет отрабатывать только для сервисной сессии с таким ServiceName, и наоборот, если поле ServiceName в правиле пусто, то данное правило не будет отрабатывать ни для какой сервисной сессии.

В поле ServiceName можно указать несколько сервисов через запятую (RSE-SVC-EXT, RSE-SVC-EXT1024) или же указать REGEXP внутри двух слешей (/^RSE-SVC-EXT.*$/).

Например, если у вас внешний трафик идет посервисным аккаунтингом с ServiceName=RSE-SVC-EXT, то нужно назначить такую привязку:

Привязка типов трафика

Пример конфигурации устройства-NAS’а

Конфигурация
# Используемый secret для общения по RADIUS-протоколу (по умолчанию - значение из поля Community/secret параметров устройства)
#radius.secret=<sercret устройства>

# Порт для отправки PoD и CoA-запросов (по умолчанию - порт, заданный в параметрах устройства Хост/порт)
#radius.port=<порт устройства>

# При выдаче Access-Accept добавлять запись в базу.
# Hеобходимо, если используется Reject-To-Accept и по Start-пакету нельзя определить в каком состоянии соединение
connection.start.fromAccept=1
# Бывают ситуации, когда Start-пакет не дошел до Accounting-сервера. В этом случае, при
# 1 (значение по умолчанию) - сессия создастся от текущего момента,
# 2 - Accounting проверит, что время сессии из Update/Stop пакета не больше, чем значение connection.close.timeout и создаст сессию от ее начала, иначе,
# если время сессии больше чем connection.close.timeout, сессия создастся от текущего момента,
# 0 - сессия без Start-пакета создана не будет.
#connection.start.fromUpdate=1
# При создании сессии по Update-пакету нужно ли игнорировать отсутствие IP-адреса сессии (Framed-Ip-Address). По умолчанию сессия
# по Update-пакету без адреса не создается (0).
#connection.start.fromUpdate.ignoreFramedIpLack=0

# Таймаут перевода соединения в статус suspended при остутствии радиус пакетов
connection.suspend.timeout=900
# Таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout)
connection.close.timeout=900
# При закрытии соединения по таймауту, 0 (по умолчанию) - просто закрыть,
# 1 - попытаться сбросить также на NAS'е (вызвать connectionClose у обработчика активации сервисов)
#connection.close.timeout.forceClose=1

# Атрибуты, выдаваемые при авторизации по реалму default (default - реалм по умолчанию)
radius.realm.default.attributes=

# Коды ошибок, при которых отвечать Access-Accept в состоянии disable (rejectToAccept)
radius.disable.accessCodes=
# Какие адреса выдавать при ответе Access-Accept в состоянии disable:
# 0 (по умолчанию) - из radius.disable.ipCategories, 1 - так же, как если бы не было ошибки (в том числе привязанные к сервису в договоре)
#radius.disable.mode=0

# Атрибуты, выдаваемые при ответе Access-Accept в состоянии disable
radius.disable.attributes=

# Id фиктивного сервиса, к которому будут привязываться сессии, по которым нормальный сервис не был найден (код ошибки: 1, логин не найден).
# Необходим, если в radius.disable.accessCodes присутствует код 1
#radius.disable.servId=

# Атрибуты, при наличии которых соединение должно считаться в состоянии DISABLE (т.е. с ограниченным доступом)
#radius.disable.pattern.attributes=

# Вендор атрибута, где хранится MAC-адрес
#radius.macAddress.vendor=9
# Код атрибута, где хранится MAC-адрес
#radius.macAddress.type=1
# Префикс атрибута (если есть), где хранится MAC-адрес. Например, для cisco avpair
#radius.macAddress.prefix=client-mac-address=


# Режим поиска сервиса: 0 (по умолчанию) - по логину, 1 - по интерфейсу на устройстве (в предобработке должны быть
# проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или INTERFACE_ID), 2 - по VLAN на устройстве (в предобработке
# должны быть проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или VLAN_ID), 4 - по VLAN на устройстве или
# дочернем устройстве (в предобработке должны быть проставлены опции AGENT_REMOTE_ID и AGENT_CIRCUIT_ID или VLAN_ID),
# 5 - по MAC-адресу на устройстве (в предобработке должна быть проставлена опция MAC_ADDRESS), 6 - по MAC-адресу на
# устройстве или дочернем устройстве (в предобработке должна быть проставлена опция MAC_ADDRESS).
#radius.servSearchMode=0
# Нужно ли проверять пароль: 0 - нет, 1 (по умолчанию) - да.
#radius.password.verification=1


# Проверка на повторную аутентификацию при Access-Request. Бывает нужна в случаях, когда NAS сбрасывает (теряет) сессию, но
# Stop-пакет не присылает и клиент пытается подключиться повторно, но у него стоит ограничение на максимум одну сессию. При совпадении
# callingStationId с одной из активных сессий и установленным параметром: 1 - осуществляется попытка закрытия старой сессии (connectionClose),
# 2 - попытка закрытия сессии (connectionClose) и завершение ее в базе, не дожидаясь стоп пакета, 3 - завершение в базе.
#radius.connection.checkDuplicate=0

# Нужно ли убирать домен перед поиском сервиса по логину из поля User-Name. По умолчанию - да (1).
# Следует отключить, если при посылке CoA и PoD пакетов NAS'у необходим атрибут User-Name.
radius.username.removeDomain=1
# Нужно ли убирать пробелы из поля User-Name перед поиском логина. По умолчанию - нет (0).
# Следует отключить, если при посылке CoA и PoD пакетов NAS'у необходим атрибут User-Name.
#radius.username.removeWhitespace=0
# Должен ли поиск по логину идти без учета регистра. По умолчанию - нет (0).
#radius.username.ignoreCase=0

# Включение (1, по умолчанию) или отключение (0) проверки пароля для NAS'а
#radius.password.verification=1

# Шаблон вывода ошибки в мониторе с использованием атрибутов из RADIUS-пакета
#radius.accessError.infoPattern=LOGIN:$User-Name


# Привязка кодов опций модуля к атрибутам
# данные атрибуты будут выдаваться в AccessAccept при удачной авторизации и при наличии активных опций в тарифе или сервисе
radius.inetOption.1.attributes=
radius.inetOption.2.attributes=
radius.inetOption.3.attributes=

# Параметры активации сервисов
# длина паузы, если возникла ошибка
#sa.error.pause=60
# количество заданий за раз
#sa.batch.size=20
# время (сек) ожидания завершения всех заданий (при асинхронной работе)
#sa.batch.wait=5
# пауза (сек) после обработки заданий
#sa.batch.pause=0
# время (сек) ожидания новой задачи перед вызовом disconnect.
#sa.batch.waitNext=5

# Параметры обработчика активации сервисов
# откуда при отправке CoA брать атрибуты опций (по умолчанию - те же атрибуты, что выдаются при удачной авторизации)
#sa.radius.option.attributesPrefix=nas.radius.inetOption.
#sa.radius.connection.attributes=NAS-Port, Acct-Session-Id, User-Name, Framed-IP-Address, NAS-IP-Address, NAS-Identifier
# атрибуты CoA-запроса для прекращения доступа (используется при sa.radius.connection.withoutBreak=1)
#sa.radius.disable.attributes={@radius.disable.attributes}
# фиксированные атрибуты, добавляемые в запрос перед отправкой CoA
#sa.radius.coa.attributes=
# добавлять ли при отправке CoA-атрибуты реалма (для default - из radius.realm.default.attributes)
#sa.radius.realm.addAttributes=0
# фиксированные атрибуты, добавляемые в запрос перед отправкой PoD
#sa.radius.pod.attributes=

Пересылка RADIUS-запросов

Иногда есть необходимость пересылать RADIUS Access/Accounting пакеты на сторонний сервер - например, на устройство СОРМ, для корректной его работы. Для дублирования полученных RADIUS-запросов на сторонний сервер в конфигурации устройства или типа устройства-NAS’а следует указать (также можно указать в конфигурации корневого устройства):

# хост, на который будут ретранслироваться пакеты-запросы, единственный обязательный параметр для включения функционала
radius.forward.host=<host>
# хост, на который будут ретранслироваться пакеты-ответы
radius.answer.forward.host=<host>
# порт, на который будут ретранслироваться пакеты-запросы, по умолчанию равен 1813
radius.forward.port=<port>
# порт, на который будут ретранслироваться пакеты-ответы
radius.answer.forward.port=<port>
# RADIUS-секрет, которым будет подписан пакет, по умолчанию берётся секрет NASа
radius.forward.secret=<secret>
# префикс к значению атрибута User-Name из accounting-пакета, если не указан - префикс не добавляется
radius.forward.user.name.prefix=<prefix>
# суффикс к значению атрибута User-Name из accounting-пакета, если не указан - суффикс не добавляется
radius.forward.user.name.suffix=<suffix>
# шаблон значения атрибута User-Name. Возможные значения:
# 1) $contractTitle - User-Name будет заменен на номер договора
# 2) $contractId - User-Name будет заменен на id договора из таблицы contract
# Для корректной работы данного механизма должен быть указан параметр radius.forward.after.process=1, т.к. номер договора будет известен только после обработки
#radius.forward.user.name.pattern=$contractTitle
# Размер очереди radius-пакетов для пересылки. По умолчанию равно 500. В случае переполнения данной очереди пакет будет проигнорирован.
#radius.forward.maxQueueSize=500

Данные параметры (если необходимы) нужно указывать в конфигурации модуля:

# если указано, отправка происходит после предобработки (по умолчанию - перед предобработкой)
#radius.forward.after.preprocess=0
# если указано, отправка происходит после обработки
#radius.forward.after.process=0
# если указано, то будут отправляться access-запросы после их обработки приложением.
#radius.forward.access.request=0

Где:

  • <host> - хост, на который будут ретранслироваться пакеты, единственный обязательный параметр для включения функционала;

  • <port> - порт, на который будут ретранслироваться пакеты, по умолчанию равен 1813;

  • <secret> - RADIUS-секрет, которым будет подписан пакет, по умолчанию берётся секрет NASа;

  • <prefix> - префикс к значению атрибута User-Name из аккаунтинг пакета, если не указан - префикс не добавляется;

  • <suffix> - суффикс к значению атрибута User-Name из аккаунтинг пакет, если не указан - суффикс не добавляется.

Суффикс и префикс могут быть полезны при необходимости ретранслирования пакетов с нескольких InetAccounting с пересекающимися логинами на единый сервер.

Например:

radius.forward.host=avantis.ru
radius.forward.port=4444
radius.forward.secret=4343
radius.forward.user.name.prefix=test_
radius.forward.user.name.suffix=_forv

Пример с подстановкой номера договора в атрибут User-Name, в конфигурации модуля:

radius.forward.after.process=1

В конфигурации типа устройства-NAS’а:

radius.forward.host=avantis.ru
radius.forward.port=4444
radius.forward.secret=4343
radius.forward.user.name.prefix=test_
radius.forward.user.name.suffix=_forv
radius.forward.user.name.pattern=$contractTitle