ISG, схема со стартом сессии и ее авторизацией по IP, выдача адресов на основе option82 (Конфигурация BGBilling'а)

Материал из BiTel WiKi

(Различия между версиями)
Перейти к: навигация, поиск
м
 
(10 промежуточных версий не показаны.)
Строка 40: Строка 40:
| [[Файл:ISG-INET-0015.jpg|200px|thumb|left|Типы устройств: Switch (уровень доступа)]]  
| [[Файл:ISG-INET-0015.jpg|200px|thumb|left|Типы устройств: Switch (уровень доступа)]]  
|}
|}
-
и привязываем сервис INTERNET к всем этим типам (через абстрактный Access+Accounting):
+
 
 +
Для полной интеграции DHCP и ISG сессий, необходимо установить в тип устройства ASR ISG вместо стандартного ru.bitel.bgbilling.modules.inet.dyn.device.cisco.ISGServiceActivator его измененный вариант (на скриншоте 'Типы устройств: ASR ISG (BRAS)' он указан как ru.bitel.bgbilling.modules.inet.dyn.device.cisco.ISGIPServiceActivator):
 +
<source lang="java">import java.util.List;
 +
 
 +
import javax.annotation.Resource;
 +
 
 +
import org.apache.log4j.Logger;
 +
 
 +
import ru.bitel.bgbilling.modules.inet.access.Access;
 +
import ru.bitel.bgbilling.modules.inet.access.InetConnectionRuntime;
 +
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivator;
 +
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivatorEvent;
 +
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetConnection;
 +
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDevice;
 +
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDeviceType;
 +
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetServ;
 +
import ru.bitel.bgbilling.modules.inet.dyn.device.cisco.ISGServiceActivator;
 +
import ru.bitel.bgbilling.server.util.Setup;
 +
import ru.bitel.common.ParameterMap;
 +
import ru.bitel.common.inet.IpAddress;
 +
 
 +
public class ISGServiceActivatorDhcp
 +
    extends ISGServiceActivator
 +
    implements ServiceActivator
 +
{
 +
private static final Logger logger = Logger.getLogger( ISGServiceActivatorDhcp.class );
 +
 
 +
@Resource(name = "access")
 +
private Access access;
 +
 
 +
public ISGServiceActivatorDhcp()
 +
{
 +
super();
 +
}
 +
 
 +
/**
 +
* {@inheritDoc}
 +
*/
 +
@Override
 +
public Object init( Setup setup, int moduleId, InetDevice device, InetDeviceType deviceType, ParameterMap deviceConfig )
 +
    throws Exception
 +
{
 +
super.init( setup, moduleId, device, deviceType, deviceConfig );
 +
 
 +
// по умолчанию закрытие - logoff
 +
this.closeMode = deviceConfig.getInt( "sa.radius.connection.close.mode", CLOSE_MODE_SUBSCR_COMMAND );
 +
// по умолчанию, при переключении состояния из отлючен во включен и withoutBreak=false делаем тоже самое, что и при обычном закрытии сессии
 +
this.closeEnableMode = deviceConfig.getInt( "sa.radius.connection.close.enableMode", this.closeMode );
 +
 
 +
// никакой работы с вторичной авторизацией (InetDhcpHelperProcessor/InetRadiusHelperProcessor) нет
 +
this.closeRemoveFromKeyMap = deviceConfig.getInt( "sa.radius.connection.close.removeFromKeyMap", 0 ) > 0;
 +
 
 +
// при закрытии соединения не отправляем дополнительно запросы на отключение сервисов
 +
this.disableServicesOnClose = deviceConfig.getInt( "sa.radius.connection.close.disableServices", 0 ) > 0;
 +
 
 +
logger.debug( this.closeMode );
 +
 
 +
return null;
 +
}
 +
 
 +
@Override
 +
public Object connectionModify( ServiceActivatorEvent e )
 +
    throws Exception
 +
{
 +
logger.debug( "connectionModify" );
 +
 
 +
if( e.getConnection().getDeviceId() != this.deviceId )
 +
{
 +
logger.debug( "Skip " + e.getConnection() + " " + this.deviceId );
 +
return null;
 +
}
 +
 
 +
return super.connectionModify( e );
 +
}
 +
 
 +
@Override
 +
public Object connectionClose( ServiceActivatorEvent e )
 +
    throws Exception
 +
{
 +
logger.debug( "connectionClose" );
 +
 
 +
if( e.getConnection().getDeviceId() != this.deviceId )
 +
{
 +
logger.debug( "Skip " + e.getConnection() + " " + this.deviceId );
 +
return null;
 +
}
 +
 
 +
return super.connectionClose( e );
 +
}
 +
 
 +
@Override
 +
public Object onAccountingStart( ServiceActivatorEvent e )
 +
    throws Exception
 +
{
 +
return super.onAccountingStart( e );
 +
}
 +
 
 +
@Override
 +
public Object onAccountingStop( ServiceActivatorEvent e )
 +
    throws Exception
 +
{
 +
logger.info( "onAccountingStop" );
 +
 +
final InetConnection dhcpConnection = e.getConnection();
 +
// ISG соединение - не обрабатываем
 +
if( dhcpConnection.getDeviceId() == deviceId )
 +
{
 +
return super.onAccountingStop( e );
 +
}
 +
 
 +
if( connectionClose( dhcpConnection, dhcpConnection.getServId() ) )
 +
{
 +
return super.onAccountingStop( e );
 +
}
 +
 
 +
List<InetServ> childrenServs = e.getNewInetServ().getChildren();
 +
if( childrenServs != null )
 +
{
 +
for( InetServ serv : childrenServs )
 +
{
 +
if( connectionClose( dhcpConnection, serv.getId() ) )
 +
{
 +
break;
 +
}
 +
}
 +
}
 +
 
 +
return super.onAccountingStop( e );
 +
}
 +
 
 +
private boolean connectionClose( InetConnection dhcpConnection, int servId )
 +
    throws Exception
 +
{
 +
List<InetConnectionRuntime> connectionRuntimeList = access.connectionManager.getByServId( servId );
 +
if( connectionRuntimeList == null )
 +
{
 +
return false;
 +
}
 +
 
 +
for( InetConnectionRuntime connectionRuntime : connectionRuntimeList )
 +
{
 +
final InetConnection isgConnection = connectionRuntime.connection;
 +
if( isgConnection.getId() != dhcpConnection.getId() && isgConnection.getDeviceId() == deviceId &&
 +
    IpAddress.equals( isgConnection.getInetAddressBytes(), dhcpConnection.getInetAddressBytes() ) )
 +
{
 +
super.connectionClose( isgConnection, closeMode, null );
 +
return true;
 +
}
 +
}
 +
 
 +
return false;
 +
}
 +
}</source>
 +
 
 +
Создаем тип сервиса INTERNET:
{|
{|
| [[Файл:ISG-INET-0010.jpg|200px|thumb|left|Сервис INTERNET, типы устройств]]  
| [[Файл:ISG-INET-0010.jpg|200px|thumb|left|Сервис INTERNET, типы устройств]]  
|}
|}
 +
Указываем в конфигурации типа сервиса:
 +
 +
# не выдавать IP-адрес в Framed-IP-Address в Access-Accept-пакете
 +
serv.radius.noAddress=1
 +
Создаем сами устройства (соответствующих типов):
Создаем сами устройства (соответствующих типов):
{|
{|
Строка 87: Строка 246:
<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
<param name="mq.user" value="bill"/>
<param name="mq.user" value="bill"/>
-
<param name="mq.pswd" value="bgbilling"/>
+
<param name="mq.pswd" value="***"/>
<!-- id модуля -->
<!-- id модуля -->
Строка 190: Строка 349:
в <param name="rootDeviceId" value="'''1'''"/> цифра '''1''' - это ID устройства Access+Accounting.
в <param name="rootDeviceId" value="'''1'''"/> цифра '''1''' - это ID устройства Access+Accounting.
-
Запускаем, подключаем клиента и вот результат:
+
Далее ставим ''BGInetAccounting сервер для модуля Inet'' (выполняет функции RADIUS-аккаунтинга). Конфиг (файл inet-accounting.xml):
 +
<source lang="bash">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<application context="accounting">
 +
<!-- Уникальное имя приложения -->
 +
<param name="app.name" value="BGInetAccounting"/>
 +
<!-- Уникальный числовой id приложения -->
 +
<param name="app.id" value="10102"/>
 +
 
 +
<!-- Параметры подключения к БД -->
 +
<param name="db.driver" value="com.mysql.jdbc.Driver"/>
 +
<param name="db.url" value="jdbc:mysql://127.0.0.1/bgbilling?useUnicode=true&amp;characterEncoding=Cp1251&amp;allowUrlInLocalInfile=true&amp;zeroDateTimeBehavior=convertToNull&amp;jdbcCompliantTruncation=false&amp;queryTimeoutKillsConnection=true&amp;connectTimeout=1000"/>
 +
<param name="db.user" value="bill"/>
 +
<param name="db.pswd" value="***"/>
 +
<param name="db.validationTimeout" value="10"/>
 +
 +
<!-- Параметры подключения к MQ -->
 +
<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
 +
<param name="mq.user" value="bill"/>
 +
<param name="mq.pswd" value="***"/>
 +
 
 +
<!-- id модуля -->
 +
<param name="moduleId" value="2"/>
 +
<!-- id корневого устройства -->
 +
<param name="rootDeviceId" value="1"/>
 +
 
 +
<!-- Внутренняя переменная приложения, не изменять -->
 +
<param name="commonIdentifierName" value="rootDeviceId"/>
 +
 +
<!-- Параметры сохранения radius-пакетов в файлы логов -->
 +
<!-- Директория, в которую сохранять radius логи -->
 +
<param name="datalog.radius.dir" value="data/radius" />
 +
<!-- Размер блока данных в файле лога, также размер буфера на лог файл -->
 +
<param name="datalog.radius.chunk.size" value="524288" />
 +
<!-- Сжимать radius логи: 0 - не сжимать, 1 - zlib -->
 +
<param name="datalog.radius.compression.type" value="1" />
 +
 
 +
<!-- Создание Accounting -->
 +
<bean name="accounting" class="ru.bitel.bgbilling.modules.inet.accounting.Accounting"/>
 +
 
 +
<context name="radius">
 +
<!-- Cоздание процессора radius-пакетов -->
 +
<bean name="radiusProcessor" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusHelperProcessor"/>
 +
 
 +
<!-- Служебный ScheduledExecutorService, необходимый для dataLogger -->
 +
<scheduledExecutorService name="hrlydtlggr" corePoolSize="1"/>
 +
 
 +
<!-- Cоздание dataLogger, сохраняющего radius-пакеты на диск (только один экземпляр) -->
 +
<bean name="radiusDataLogger" class="ru.bitel.bgbilling.modules.inet.radius.RadiusHourlyDataLogger">
 +
<param name="scheduledExecutor">hrlydtlggr</param>
 +
</bean>
 +
 
 +
<!-- Cоздание слушателя radius-пакетов на порту с передачей ему процессора и dataLogger -->
 +
<bean name="radiusListener" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusListener">
 +
<constructor>
 +
<!-- Хост (интерфейс), на котором будет открыт сокет. Если пусто - на всех -->
 +
<param name="host" value=""/>
 +
<!-- Порт, на котором будет открыт сокет -->
 +
<param name="port" value="1813"/>
 +
<!-- Размер буфера приема слушателя -->
 +
<param name="recvBufferSize">1 * 1024 * 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.accounting -->
 +
<param name="mode">RadiusListener.Mode.accounting</param>
 +
<!-- Передача setup -->
 +
<param name="setup">setup</param>
 +
<!-- Передача dataLogger -->
 +
<param name="dataLogger">radiusDataLogger</param>
 +
</constructor>
 +
</bean>
 +
</context>
 +
</application>
 +
</source>
 +
 
 +
Запускаем BGInetAccess и BGInetAccounting, подключаем клиента и вот результат:
{|
{|
| [[Файл:ISG-INET-0027.jpg|200px|thumb|left|Монитор (активные сессии договора)]]  
| [[Файл:ISG-INET-0027.jpg|200px|thumb|left|Монитор (активные сессии договора)]]  
Строка 201: Строка 441:
access.group=1
access.group=1
-
#типы устройств - Nas-ов
+
# Типы устройств - NAS-ов
#radius.deviceTypeIds=3,4
#radius.deviceTypeIds=3,4
-
#типы устройств, являющиеся dhcp relay
+
# Типы устройств, являющиеся dhcp relay (нужно указывать все типы устройств-коммутаторы, через которые передается DHCP-пакет или же оставить значение пустым)
#dhcp.relay.deviceTypeIds=
#dhcp.relay.deviceTypeIds=
-
#привязка по ip
+
# Привязка DHCP и ISG сессий по IP-адресу - здесь указывается тип устройства ASR ISG
radius.key.deviceTypeIds=3
radius.key.deviceTypeIds=3
-
#количество потоков на worker'а
+
# Количество потоков на worker'а
accounting.worker.1.thread.count=1
accounting.worker.1.thread.count=1
-
#тарификатор:
+
# тарификатор:
-
#минимальная сумма трафика, при которой тарифицировать соединение
+
# минимальная сумма трафика, при которой тарифицировать соединение
accounting.worker.1.tariffication.1.minDeltaAmount=0
accounting.worker.1.tariffication.1.minDeltaAmount=0
-
#пауза между заданиями тарификации
+
# пауза между заданиями тарификации
accounting.worker.1.tariffication.1.delay=1
accounting.worker.1.tariffication.1.delay=1
-
#максимальное количество тарифицируемых соединений за задание
+
# максимальное количество тарифицируемых соединений за задание
accounting.worker.1.tariffication.1.batchSize=100
accounting.worker.1.tariffication.1.batchSize=100
-
#трекер (обработка сессий без наработки):
+
# трекер (обработка сессий без наработки):
-
#пауза между заданиями трекинга
+
# пауза между заданиями трекинга
accounting.worker.1.tracking.1.delay=2
accounting.worker.1.tracking.1.delay=2
-
#максимальное количество проверенных соединений за задание
+
# максимальное количество проверенных соединений за задание
accounting.worker.1.tracking.1.batchSize=100
accounting.worker.1.tracking.1.batchSize=100
   
   
-
#количество потоков на worker'а
+
# Количество потоков на worker'а
accounting.worker.2.thread.count=1
accounting.worker.2.thread.count=1
-
#сброс в базу трафиков и наработки
+
# сброс в базу трафиков и наработки
-
#минимальная наработка, при которой сбрасывать соединения в базу
+
# минимальная наработка, при которой сбрасывать соединения в базу
accounting.worker.2.flushing.1.minDeltaAccount=0
accounting.worker.2.flushing.1.minDeltaAccount=0
-
#пауза между заданиями сброса в базу
+
# пауза между заданиями сброса в базу
accounting.worker.2.flushing.1.delay=2
accounting.worker.2.flushing.1.delay=2
-
#максимальное количество сброшенных соединений в базу за задание
+
# максимальное количество сброшенных соединений в базу за задание
accounting.worker.2.flushing.1.batchSize=500
accounting.worker.2.flushing.1.batchSize=500
-
#количество потоков на worker'а
+
# Количество потоков на worker'а
accounting.worker.3.thread.count=1
accounting.worker.3.thread.count=1
-
#завершатель соединений
+
# завершатель соединений
-
#пауза между заданиями
+
# пауза между заданиями
accounting.worker.3.finishing.1.delay=2
accounting.worker.3.finishing.1.delay=2
-
#максимальное количество сброшенных соединений в базу за задание
+
# максимальное количество сброшенных соединений в базу за задание
accounting.worker.3.finishing.1.batchSize=500
accounting.worker.3.finishing.1.batchSize=500
   
   
connection.start.fromAccept=1
connection.start.fromAccept=1
-
#таймаут перевода соединения в статус suspended при остутствии радиус пакетов
+
# таймаут перевода соединения в статус suspended при остутствии радиус пакетов
connection.suspend.timeout=900
connection.suspend.timeout=900
-
#таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout)
+
# таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout)
connection.close.timeout=1300
connection.close.timeout=1300
-
#таймаут перевода соединения в статус suspended при остутствии радиус пакетов (для сессий с ограниченным доступом)
+
# таймаут перевода соединения в статус suspended при остутствии радиус пакетов (для сессий с ограниченным доступом)
connection.disable.suspend.timeout=900
connection.disable.suspend.timeout=900
-
#таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout, для сессий с ограниченным доступом)
+
# таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout, для сессий с ограниченным доступом)
connection.disable.close.timeout=1300
connection.disable.close.timeout=1300
-
#Radius-STOP
+
# таймаут завершения соединения после стоп-пакета (обычно используется для ожидания запоздавших Netflow-пакетов)
connection.finish.timeout=5
connection.finish.timeout=5
Строка 278: Строка 518:
dhcp.option82.agentRemoteId.position=0
dhcp.option82.agentRemoteId.position=0
-
# Поиск сервиса Inet по  
+
# Поиск сервиса Inet по устройству и интерфейсу
dhcp.servSearchMode=1
dhcp.servSearchMode=1
# выдавать тот же IP адрес, что при открытом доступе
# выдавать тот же IP адрес, что при открытом доступе
dhcp.disable.mode=1
dhcp.disable.mode=1
 +
 +
# при появлении нового DISCOVER закрываем предыдущую сессию в биллинге
 +
#dhcp.connection.closeOnNew=1
# Отключаем проверку пароля
# Отключаем проверку пароля
Строка 311: Строка 554:
# Коды ошибок, при которых вместо reject выдавать accept с заданными атрибутами
# Коды ошибок, при которых вместо reject выдавать accept с заданными атрибутами
-
#(пользователю выдается серый адрес и устанавливается HTTP-редирект)
+
# (пользователю выдается серый адрес и устанавливается HTTP-редирект)
#radius.disable.accessCodes=1,2,3,4,10,11,12,46
#radius.disable.accessCodes=1,2,3,4,10,11,12,46
# атрибуты, выдаваемые при rejectToAccept
# атрибуты, выдаваемые при rejectToAccept
Строка 390: Строка 633:
# выдавать тот же IP адрес, что при открытом доступе
# выдавать тот же IP адрес, что при открытом доступе
dhcp.disable.mode=1
dhcp.disable.mode=1
 +
 +
# при появлении нового DISCOVER закрываем предыдущую сессию в биллинге
 +
#dhcp.connection.closeOnNew=1
# Берем адрес из Access-Request
# Берем адрес из Access-Request
Строка 555: Строка 801:
#Опция ISG-5MBPS
#Опция ISG-5MBPS
radius.inetOption.2.attributes=cisco-avpair=ip:traffic-class=in access-group 101 priority 201;cisco-avpair=ip:traffic-class=out access-group 102 priority 201;cisco-SSG-Service-Info=QU;;5120000;;384000;;768000;;D;;5120000;;960000;;1920000
radius.inetOption.2.attributes=cisco-avpair=ip:traffic-class=in access-group 101 priority 201;cisco-avpair=ip:traffic-class=out access-group 102 priority 201;cisco-SSG-Service-Info=QU;;5120000;;384000;;768000;;D;;5120000;;960000;;1920000
-
</service>
+
</source>
Во вторых - на сервер устанавливаем еще одну копию ''BGInetAccess сервер для модуля Inet'' (переименовав его из BGInetAccess, к примеру, в BGInetServiceAccess) и в нем указываем в качестве root-устройства вершину второй иерархии: Service Auth (типа Access+Accounting):
Во вторых - на сервер устанавливаем еще одну копию ''BGInetAccess сервер для модуля Inet'' (переименовав его из BGInetAccess, к примеру, в BGInetServiceAccess) и в нем указываем в качестве root-устройства вершину второй иерархии: Service Auth (типа Access+Accounting):
<source lang="bash">  
<source lang="bash">  
Строка 580: Строка 826:
<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
<param name="mq.user" value="bill"/>
<param name="mq.user" value="bill"/>
-
<param name="mq.pswd" value="bgbilling"/>
+
<param name="mq.pswd" value="***"/>
<!-- id модуля -->
<!-- id модуля -->
Строка 651: Строка 897:
Запускаем и получаем второй radius-сервер (на порту 1811).
Запускаем и получаем второй radius-сервер (на порту 1811).
-
Теперь нужно завести специальный договор, в котором для устройства ''Access+Accounting: Service Auth'' (вершина второй иерархии устройств, к которой и привязан второй радиус) будут созданы сервисы (не путать с ISG сервисами, те - назначаются на ISG сессию на циске, а эти - нечто вроде аккаунтов для доступа к услугам в BGBilling'е) с логинами равными именами ISG сервисов:  
+
Создаем новый тип сервиса (не путать с ISG сервисами, те - назначаются на ISG сессию на циске, а эти - нечто вроде аккаунтов для доступа к услугам в BGBilling'е), который и будет описывать как биллингу авторизовывать радиус запросы с логинами равными именам ISG сервисов:
 +
{|
 +
| [[Файл:ISG-INET-0036.jpg|200px|thumb|left|Типы сервисов: ISG Service (конфигурация)]]
 +
| [[Файл:ISG-INET-0037.jpg|200px|thumb|left|Типы сервисов: ISG Service (типы устройств)]]
 +
|}
 +
 
 +
Теперь нужно завести отдельный договор, в котором для устройства ''Access+Accounting: Service Auth'' (вершина второй иерархии устройств, к которой и привязан второй радиус) будут созданы сервисы (типа ISG Service) с логинами равными именами ISG сервисов:  
{|
{|
| [[Файл:ISG-INET-0033.jpg|200px|thumb|left|Договор ISG_SERVICE, сервисы]]  
| [[Файл:ISG-INET-0033.jpg|200px|thumb|left|Договор ISG_SERVICE, сервисы]]  
Строка 658: Строка 910:
В результате, второй радиус сервер будет отвечать ACCESS-ACCEPT для запросов от BRAS'а, в которых логин=имя ISG сервиса.
В результате, второй радиус сервер будет отвечать ACCESS-ACCEPT для запросов от BRAS'а, в которых логин=имя ISG сервиса.
-
Теперь осталось только привязать к этому сервису (не к ISG сервису, а к сервису договора, с логином равным имени ISG сервиса) соответствующую опцию:
+
Теперь осталось только привязать к этому сервису (не к ISG сервису, а к сервису договора, с логином сервиса равным имени ISG сервиса) соответствующую опцию:
{|
{|
| [[Файл:ISG-INET-0035.jpg|200px|thumb|left|Договор ISG_SERVICE, сервис ISG-5MBPS, опции]]  
| [[Файл:ISG-INET-0035.jpg|200px|thumb|left|Договор ISG_SERVICE, сервис ISG-5MBPS, опции]]  

Текущая версия на 13:44, 4 сентября 2014

Устанавливаем модуль inet_5.2_1118.zip, создаем его в редакторе модулей и услуг, добавляем услуги.
Затем, создаем Опции (имена ISG сервисов), типы трафика и тарифный план (в нем прописываем стоимости типов трафика и подключаем Опции, т.е. ISG сервисы):

Модуль, услуги
Опции (ISG сервисы)
Типы трафика
Тарифный план: стоимость трафика и подключение опций (ISG сервисов)

Описываем откуда брать информацию о количестве каждого из типов трафика (можно конечно использовать netflow, но я ограничился Acct-Input-Octets и Acct-Output-Octets из radius аккаунтинга, так как тарифов по траффику у меня нет и эта информация нужна всего лишь для статистики):

Привяка типов трафика: Local Upstream
Привяка типов трафика: Local Downstream
Привяка типов трафика: Internet Upstream
Привяка типов трафика: Internet Downstream

Далее, создаем пул IP адресов - они должны быть из диапазона адресов интерфейса Loopback52 (на свиче уровня аггрегации), а default gateway должен быть адрес интерфейса Loopback52.
Создаем сервис INTERNET, который будем подключать к договору в биллинге (не путать с ISG сервисом, назначаемым на ISG сессию абонента на циске), чтобы собственно предоставить ему (договору) доступ в интернет через модуль Inet.

IP-ресурсы
Сервис INTERNET

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

Сущности
Атрибуты

Создаем типы устройств:

  1. абстрактный тип Access+Accounting, являющийся верхушкой иерархии всех типов устройств, объединяя их все (в нем прописываются настройки общие для всех типов устройств)
  2. тип ASR ISG, описывающий BRAS'ы
  3. тип SW-1, описывающий свичи уровня аггрегации (они же dhcp релеи)
  4. тип Switch, описывающий свичи уровня доступа (те, которые вставляют option82), привязываем к нему сущность коммутатор.
Типы устройств
Типы устройств: Access+Accounting (абстрактный тип, верхушка иерархии типов)
Типы устройств: ASR ISG (BRAS)
Типы устройств: SW-1 (уровень аггрегации)
Типы устройств: Switch (уровень доступа)

Для полной интеграции DHCP и ISG сессий, необходимо установить в тип устройства ASR ISG вместо стандартного ru.bitel.bgbilling.modules.inet.dyn.device.cisco.ISGServiceActivator его измененный вариант (на скриншоте 'Типы устройств: ASR ISG (BRAS)' он указан как ru.bitel.bgbilling.modules.inet.dyn.device.cisco.ISGIPServiceActivator):

import java.util.List;
 
import javax.annotation.Resource;
 
import org.apache.log4j.Logger;
 
import ru.bitel.bgbilling.modules.inet.access.Access;
import ru.bitel.bgbilling.modules.inet.access.InetConnectionRuntime;
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivator;
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivatorEvent;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetConnection;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDevice;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDeviceType;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetServ;
import ru.bitel.bgbilling.modules.inet.dyn.device.cisco.ISGServiceActivator;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.ParameterMap;
import ru.bitel.common.inet.IpAddress;
 
public class ISGServiceActivatorDhcp
    extends ISGServiceActivator
    implements ServiceActivator
{
	private static final Logger logger = Logger.getLogger( ISGServiceActivatorDhcp.class );
 
	@Resource(name = "access")
	private Access access;
 
	public ISGServiceActivatorDhcp()
	{
		super();
	}
 
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object init( Setup setup, int moduleId, InetDevice device, InetDeviceType deviceType, ParameterMap deviceConfig )
	    throws Exception
	{
		super.init( setup, moduleId, device, deviceType, deviceConfig );
 
		// по умолчанию закрытие - logoff
		this.closeMode = deviceConfig.getInt( "sa.radius.connection.close.mode", CLOSE_MODE_SUBSCR_COMMAND );
		// по умолчанию, при переключении состояния из отлючен во включен и withoutBreak=false делаем тоже самое, что и при обычном закрытии сессии
		this.closeEnableMode = deviceConfig.getInt( "sa.radius.connection.close.enableMode", this.closeMode );
 
		// никакой работы с вторичной авторизацией (InetDhcpHelperProcessor/InetRadiusHelperProcessor) нет
		this.closeRemoveFromKeyMap = deviceConfig.getInt( "sa.radius.connection.close.removeFromKeyMap", 0 ) > 0;
 
		// при закрытии соединения не отправляем дополнительно запросы на отключение сервисов
		this.disableServicesOnClose = deviceConfig.getInt( "sa.radius.connection.close.disableServices", 0 ) > 0;
 
		logger.debug( this.closeMode );
 
		return null;
	}
 
	@Override
	public Object connectionModify( ServiceActivatorEvent e )
	    throws Exception
	{
		logger.debug( "connectionModify" );
 
		if( e.getConnection().getDeviceId() != this.deviceId )
		{
			logger.debug( "Skip " + e.getConnection() + " " + this.deviceId );
			return null;
		}
 
		return super.connectionModify( e );
	}
 
	@Override
	public Object connectionClose( ServiceActivatorEvent e )
	    throws Exception
	{
		logger.debug( "connectionClose" );
 
		if( e.getConnection().getDeviceId() != this.deviceId )
		{
			logger.debug( "Skip " + e.getConnection() + " " + this.deviceId );
			return null;
		}
 
		return super.connectionClose( e );
	}
 
	@Override
	public Object onAccountingStart( ServiceActivatorEvent e )
	    throws Exception
	{
		return super.onAccountingStart( e );
	}
 
	@Override
	public Object onAccountingStop( ServiceActivatorEvent e )
	    throws Exception
	{
		logger.info( "onAccountingStop" );
 
		final InetConnection dhcpConnection = e.getConnection();
		// ISG соединение - не обрабатываем 
		if( dhcpConnection.getDeviceId() == deviceId )
		{
			return super.onAccountingStop( e );
		}
 
		if( connectionClose( dhcpConnection, dhcpConnection.getServId() ) )
		{
			return super.onAccountingStop( e );
		}
 
		List<InetServ> childrenServs = e.getNewInetServ().getChildren();
		if( childrenServs != null )
		{
			for( InetServ serv : childrenServs )
			{
				if( connectionClose( dhcpConnection, serv.getId() ) )
				{
					break;
				}
			}
		}
 
		return super.onAccountingStop( e );
	}
 
	private boolean connectionClose( InetConnection dhcpConnection, int servId )
	    throws Exception
	{
		List<InetConnectionRuntime> connectionRuntimeList = access.connectionManager.getByServId( servId );
		if( connectionRuntimeList == null )
		{
			return false;
		}
 
		for( InetConnectionRuntime connectionRuntime : connectionRuntimeList )
		{
			final InetConnection isgConnection = connectionRuntime.connection;
			if( isgConnection.getId() != dhcpConnection.getId() && isgConnection.getDeviceId() == deviceId &&
			    IpAddress.equals( isgConnection.getInetAddressBytes(), dhcpConnection.getInetAddressBytes() ) )
			{
				super.connectionClose( isgConnection, closeMode, null );
				return true;
			}
		}
 
		return false;
	}
}

Создаем тип сервиса INTERNET:

Сервис INTERNET, типы устройств

Указываем в конфигурации типа сервиса:

# не выдавать IP-адрес в Framed-IP-Address в Access-Accept-пакете
serv.radius.noAddress=1

Создаем сами устройства (соответствующих типов):

Устройства
Устройства: Access+Accounting (абстрактное устройство, верхушка иерархии устройств)
Устройства: R31_ASR1002 (BRAS)
Устройства: (каталист уровня аггрегации)
Устройства: (каталист уровня доступа)

Для свичей доступа указываем местоположение (используя сущность и атрибут адрес):

Устройства: (каталист уровня доступа, атрибуты)

Теперь осталось привязать сервис INTERNET (выбрав нужный свич уровня доступа и указав правильный номер порта) к договору:

Договор, сервисы (постоянный IP)
Договор, сервисы (случайный IP)

И не забыть про тариф, так как именно через него (помимо определения стоимостей) назначаются ISG сессии (Опции):

Договор, тарифный план (назначение Опций, т.е. ISG сервисов)

Теперь ставим BGInetAccess сервер для модуля Inet (выполняет функции DHCP и RADIUS серверов). Конфиг (файл inet-access.xml):

<?xml version="1.0" encoding="UTF-8"?>
<application context="access">
	<!-- Уникальное имя приложения -->
	<param name="app.name" value="BGInetAccess"/>
	<!-- Уникальный числовой id приложения -->
	<param name="app.id" value="10101"/>
 
	<!-- Параметры подключения к БД -->
	<param name="db.driver" value="com.mysql.jdbc.Driver"/>
	<param name="db.url" value="jdbc:mysql://127.0.0.1/bgbilling?useUnicode=true&amp;characterEncoding=Cp1251&amp;allowUrlInLocalInfile=true&amp;zeroDateTimeBehavior=convertToNull&amp;jdbcCompliantTruncation=false&amp;queryTimeoutKillsConnection=true&amp;connectTimeout=1000"/>
	<param name="db.user" value="bill"/>
	<param name="db.pswd" value="***"/>
	<param name="db.validationTimeout" value="10"/>
 
	<!-- Параметры подключения к MQ -->
	<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
	<param name="mq.user" value="bill"/>
	<param name="mq.pswd" value="***"/>
 
	<!-- id модуля -->
	<param name="moduleId" value="2"/>
	<!-- id корневого устройства -->
	<param name="rootDeviceId" value="1"/>
	<!-- Типы фейковых устройств, являющихся аккаунтинг серверами -->
	<param name="accounting.deviceTypeIds" value="1"/>
 
	<!-- Внутренняя переменная приложения, не изменять -->
	<param name="commonIdentifierName" value="rootDeviceId"/>
 
	<!-- Параметры сохранения логов данных -->
	<!-- Директория, в которую сохранять radius логи -->
	<param name="datalog.radius.dir" value="data/radius" />
	<!-- Размер блока данных в файле лога, также размер буфера на лог файл -->
	<param name="datalog.radius.chunk.size" value="262144" />
	<!-- Сжимать radius логи: 0 - не сжимать, 1 - zlib -->
	<param name="datalog.radius.compression.type" value="1" />
	<!-- Директория, в которую сохранять flow логи -->
	<param name="datalog.dhcp.dir" value="data/dhcp" />
	<!-- Размер блока данных в файле лога, также размер буфера на лог файл -->
	<param name="datalog.dhcp.chunk.size" value="131072" />
	<!-- Сжимать flow логи: 0 - не сжимать, 1 - zlib -->
	<param name="datalog.dhcp.compression.type" value="1" />
 
 
	<!-- Создание Access -->
	<bean name="access" class="ru.bitel.bgbilling.modules.inet.access.Access" />
 
	<context name="radius">
		<!-- Cоздание процессора radius-пакетов -->
		<bean name="radiusProcessor" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusHelperProcessor"/>
 
		<!-- Служебный ScheduledExecutorService, необходимый для dataLogger -->
		<scheduledExecutorService name="hrlydtlggr" corePoolSize="1" />
 
		<!-- Cоздание dataLogger, сохраняющего radius-пакеты на диск (только один экземпляр) -->
		<bean name="radiusDataLogger" class="ru.bitel.bgbilling.modules.inet.radius.RadiusHourlyDataLogger">
			<param name="scheduledExecutor">hrlydtlggr</param>
		</bean>
 
		<!-- Cоздание слушателя radius-пакетов на порту с передачей ему процессора и dataLogger -->
		<bean name="radiusListener" class="ru.bitel.bgbilling.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>
 
	<context name="dhcp">
		<!-- Cоздание процессора dhcp-пакетов -->
		<bean name="dhcpProcessor" class="ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpProcessor"/>
 
		<scheduledExecutorService name="hrlydtlggr" corePoolSize="1" />
 
		<!-- Cоздание dataLogger, сохраняющего dhcp-пакеты на диск  -->
		<bean name="dhcpDataLogger" class="ru.bitel.bgbilling.modules.inet.dhcp.DhcpHourlyDataLogger">
			<param name="scheduledExecutor">hrlydtlggr</param>
		</bean>
 
		<!-- Cоздание слушателя dhcp-пакетов на порту с передачей ему процессора и dataLogger -->
		<bean name="dhcpListener" class="ru.bitel.bgbilling.kernel.network.dhcp.DhcpListener">
			<constructor>
				<!-- Хост (интерфейс), на котором будет открыт сокет. Если пусто - на всех -->
				<param name="host" value=""/>
				<!-- Порт, на котором будет открыт сокет -->
				<param name="port" value="67"/>
				<!-- Размер буфера приема слушателя -->
				<param name="recvBufferSize">512 * 1024</param>
				<!-- Количество потоков-обработчиков -->
				<param name="threadCount">10</param>
				<!-- Максимальное количество пакетов в очереди на обработку -->
				<param name="maxQueueSize">200</param>
				<!-- Передача процессора -->
				<param name="processor">dhcpProcessor</param>
				<!-- Передача dataLogger -->
				<param name="dataLogger">dhcpDataLogger</param>
			</constructor>
		</bean>
	</context>
</application>

Здесь, в <param name="moduleId" value="2"/> цифра 2 - это ID модуля Inet, а
в <param name="rootDeviceId" value="1"/> цифра 1 - это ID устройства Access+Accounting.

Далее ставим BGInetAccounting сервер для модуля Inet (выполняет функции RADIUS-аккаунтинга). Конфиг (файл inet-accounting.xml):

<?xml version="1.0" encoding="UTF-8"?>
<application context="accounting">
	<!-- Уникальное имя приложения -->
	<param name="app.name" value="BGInetAccounting"/>
	<!-- Уникальный числовой id приложения -->
	<param name="app.id" value="10102"/>
 
	<!-- Параметры подключения к БД -->
	<param name="db.driver" value="com.mysql.jdbc.Driver"/>
	<param name="db.url" value="jdbc:mysql://127.0.0.1/bgbilling?useUnicode=true&amp;characterEncoding=Cp1251&amp;allowUrlInLocalInfile=true&amp;zeroDateTimeBehavior=convertToNull&amp;jdbcCompliantTruncation=false&amp;queryTimeoutKillsConnection=true&amp;connectTimeout=1000"/>
	<param name="db.user" value="bill"/>
	<param name="db.pswd" value="***"/>
	<param name="db.validationTimeout" value="10"/>
 
	<!-- Параметры подключения к MQ -->
	<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
	<param name="mq.user" value="bill"/>
	<param name="mq.pswd" value="***"/>
 
	<!-- id модуля -->
	<param name="moduleId" value="2"/>
	<!-- id корневого устройства -->
	<param name="rootDeviceId" value="1"/>
 
	<!-- Внутренняя переменная приложения, не изменять -->
	<param name="commonIdentifierName" value="rootDeviceId"/>
 
	<!-- Параметры сохранения radius-пакетов в файлы логов -->
	<!-- Директория, в которую сохранять radius логи -->
	<param name="datalog.radius.dir" value="data/radius" />
	<!-- Размер блока данных в файле лога, также размер буфера на лог файл -->
	<param name="datalog.radius.chunk.size" value="524288" />
	<!-- Сжимать radius логи: 0 - не сжимать, 1 - zlib -->
	<param name="datalog.radius.compression.type" value="1" />
 
	<!-- Создание Accounting -->
	<bean name="accounting" class="ru.bitel.bgbilling.modules.inet.accounting.Accounting"/>
 
	<context name="radius">
		<!-- Cоздание процессора radius-пакетов -->
		<bean name="radiusProcessor" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusHelperProcessor"/>
 
		<!-- Служебный ScheduledExecutorService, необходимый для dataLogger -->
		<scheduledExecutorService name="hrlydtlggr" corePoolSize="1"/>
 
		<!-- Cоздание dataLogger, сохраняющего radius-пакеты на диск (только один экземпляр) -->
		<bean name="radiusDataLogger" class="ru.bitel.bgbilling.modules.inet.radius.RadiusHourlyDataLogger">
			<param name="scheduledExecutor">hrlydtlggr</param>
		</bean>
 
		<!-- Cоздание слушателя radius-пакетов на порту с передачей ему процессора и dataLogger -->
		<bean name="radiusListener" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusListener">
			<constructor>
				<!-- Хост (интерфейс), на котором будет открыт сокет. Если пусто - на всех -->
				<param name="host" value=""/>
				<!-- Порт, на котором будет открыт сокет -->
				<param name="port" value="1813"/>
				<!-- Размер буфера приема слушателя -->
				<param name="recvBufferSize">1 * 1024 * 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.accounting -->
				<param name="mode">RadiusListener.Mode.accounting</param>
				<!-- Передача setup -->
				<param name="setup">setup</param>
				<!-- Передача dataLogger -->
				<param name="dataLogger">radiusDataLogger</param>
			</constructor>
		</bean>
	</context>
</application>

Запускаем BGInetAccess и BGInetAccounting, подключаем клиента и вот результат:

Монитор (активные сессии договора)
Отчет (по-сервисный аккаунтинг)


Полный конфиг типа устройств Access+Acounting:

access.group=1
 
# Типы устройств - NAS-ов
#radius.deviceTypeIds=3,4
# Типы устройств, являющиеся dhcp relay (нужно указывать все типы устройств-коммутаторы, через которые передается DHCP-пакет или же оставить значение пустым)
#dhcp.relay.deviceTypeIds=
# Привязка DHCP и ISG сессий по IP-адресу - здесь указывается тип устройства ASR ISG
radius.key.deviceTypeIds=3
 
# Количество потоков на worker'а
accounting.worker.1.thread.count=1
# тарификатор:
# минимальная сумма трафика, при которой тарифицировать соединение
accounting.worker.1.tariffication.1.minDeltaAmount=0
# пауза между заданиями тарификации
accounting.worker.1.tariffication.1.delay=1
# максимальное количество тарифицируемых соединений за задание
accounting.worker.1.tariffication.1.batchSize=100
# трекер (обработка сессий без наработки):
# пауза между заданиями трекинга
accounting.worker.1.tracking.1.delay=2
# максимальное количество проверенных соединений за задание
accounting.worker.1.tracking.1.batchSize=100
 
# Количество потоков на worker'а
accounting.worker.2.thread.count=1
# сброс в базу трафиков и наработки
# минимальная наработка, при которой сбрасывать соединения в базу
accounting.worker.2.flushing.1.minDeltaAccount=0
# пауза между заданиями сброса в базу
accounting.worker.2.flushing.1.delay=2
# максимальное количество сброшенных соединений в базу за задание
accounting.worker.2.flushing.1.batchSize=500
 
# Количество потоков на worker'а
accounting.worker.3.thread.count=1
# завершатель соединений
# пауза между заданиями
accounting.worker.3.finishing.1.delay=2
# максимальное количество сброшенных соединений в базу за задание
accounting.worker.3.finishing.1.batchSize=500
 
connection.start.fromAccept=1
# таймаут перевода соединения в статус suspended при остутствии радиус пакетов
connection.suspend.timeout=900
# таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout)
connection.close.timeout=1300
# таймаут перевода соединения в статус suspended при остутствии радиус пакетов (для сессий с ограниченным доступом)
connection.disable.suspend.timeout=900
# таймаут закрытия соединения при остутствии радиус пакетов (не складывается с connection.suspend.timeout, для сессий с ограниченным доступом)
connection.disable.close.timeout=1300
# таймаут завершения соединения после стоп-пакета (обычно используется для ожидания запоздавших Netflow-пакетов)
connection.finish.timeout=5
 
session.split.onTariffOption=1
session.split.onDeviceState=1

Полный конфиг типа устройств ASR ISG:

# Версия SNMP (по умолчанию 1)
snmp.version=2
# SNMP OID, из которого ивлекается значение uptime (1.3.6.1.2.1.1.3.0)
snmp.uptimeOid=1.3.6.1.2.1.1.3.0
 
# По умолчанию для Inet каждое устройство является netflow-агентом, 
# для оптимизации указываем, что у нас только один netflow-агент
flow.agent.type=netflow
flow.agent.link={@deviceId}:-1
 
# Поиск устройства по giaddr и remoteId - 1,
# поиск устройства только по giaddr, агентское устройство ищется отдельно, после preprocessDhcpRequest - 2,
dhcp.deviceSearchMode=1
 
# убираем заголовок-длину
dhcp.option82.removeHeader=2
# позиция agentRemoteId
dhcp.option82.agentRemoteId.position=0
 
# Поиск сервиса Inet по устройству и интерфейсу
dhcp.servSearchMode=1
 
# выдавать тот же IP адрес, что при открытом доступе
dhcp.disable.mode=1
 
# при появлении нового DISCOVER закрываем предыдущую сессию в биллинге
#dhcp.connection.closeOnNew=1
 
# Отключаем проверку пароля
radius.password.verification=0
 
# Берем адрес из Access-Request
radius.address.fromRequest=1
 
# Код атрибута, из которого извлекать acctSessionId родительской сессии (по умолчанию - из cisco-avpair)
#radius.parentAcctSessionId.type=1
# префикс в значении атрибута перед acctSessionId родительской сессии
#radius.parentAcctSessionId.prefix=parent-session-id=
# код атрибута, из которого извлекать имя сервиса ISG (по умолчанию cisco-SSG-Service-Info)
#radius.serviceName.type=251
# префикс в значении атрибута перед именем сервиса ISG (если есть)
#radius.serviceName.prefix=
 
# Атрибуты, выдаваемые в Access-Accept
radius.realm.default.attributes=Acct-Interim-Interval=60;Idle-Timeout=1300;cisco-avpair=subscriber:accounting-list=ipoe-isg-aaa
 
# Радиус атрибуты, выдаваемые при авторизации для сервисов
radius.inetOption.2.attributes=cisco-SSG-Account-Info=AISG-5MBPS
radius.inetOption.3.attributes=cisco-SSG-Account-Info=AISG-10MBPS
radius.inetOption.4.attributes=cisco-SSG-Account-Info=AISG-LOCAL
 
# Категории ip адресов из ресурсов, из которых будут выдаваться адреса ("пул", указывается во вкладке "IP ресурсы")
radius.realm.default.ipCategories=1
 
# Коды ошибок, при которых вместо reject выдавать accept с заданными атрибутами
# (пользователю выдается серый адрес и устанавливается HTTP-редирект)
#radius.disable.accessCodes=1,2,3,4,10,11,12,46
# атрибуты, выдаваемые при rejectToAccept
radius.disable.attributes=Acct-Interim-Interval=60;cisco-avpair=subscriber:accounting-list=ipoe-isg-aaa;cisco-SSG-Account-Info=AL4REDIRECT;cisco-SSG-Account-Info=AOPENGARDEN
#radius.realm.reject.attributes=Acct-Interim-Interval=60;IP-Interface-Name=IP-Interface-Name=ISG-IP-UNAUTH;cisco-SSG-Account-Info=ALOCAL_L4R
#категории ip адресов из ресурсов, из которых будут выдаваться адреса для отключенных ("пул", указывается во вкладке "IP ресурсы")
radius.disable.ipCategories=2
 
# Параметры активации сервисов
# длина паузы, если возникла ошибка
#sa.error.pause=60
# количество заданий за раз
#sa.batch.size=20
# время (сек) ожидания завершения всех заданий (при асинхронной работе)
#sa.batch.wait=5
# пауза (сек) после обработки заданий
#sa.batch.pause=0
# время (сек) ожидания новой задачи перед вызовом disconnect.
#sa.batch.waitNext=5
#режим отправки CoA. 1 - команды 0xc и 0xb в одном пакете для каждого сервиса, 2 - атрибуты subscriber:command= в раздельных пакетах для каждого сервиса
sa.radius.connection.coa.mode=2
# при отключении посылать команду account-logoff
sa.radius.connection.close.mode=3
# не посылать команды на отключение сервисов
#sa.radius.connection.close.disableServices=1 
# чтобы, если деньги закончились, не закрывал сервисы, а закрывал сразу сессию ISG целиком - 0, иначе - 1
sa.radius.connection.withoutBreak=0
# если dhcp lease time большой, а при положительном балансе доступ нужно дать (даже если адрес сейчас выдан серый), нужно установить 1
#sa.radius.connection.coa.onEnable=0
# откуда при отправке CoA брать атрибуты опций (по умолчанию - те же атрибуты, что выдаются при удачной авторизации)
#sa.radius.option.attributesPrefix=
sa.radius.connection.attributes=Acct-Session-Id,User-Name,Framed-IP-Address
radius.connection.attributes=Acct-Session-Id,User-Name,Framed-IP-Address
# атрибуты CoA запроса для прекращения доступа (используется при sa.radius.connection.withoutBreak=1)
#sa.radius.disable.attributes=
# фиксированные атрибуты, добавляемые в запрос перед отправкой CoA
#sa.radius.coa.attributes=
# добавлять ли при отправке CoA атрибуты реалма (для default - из radius.realm.default.attributes)
#sa.radius.realm.addAttributes=0
# фиксированные атрибуты, добавляемые в запрос перед отправкой PoD
#sa.radius.pod.attributes=
sa.radius.connection.close.removeFromKeyMap=0
 
# Лог CoA запросов
sa.radius.log=1
 
#radius.disable.attributes=cisco-avpair=subscriber:accounting-list=ISG-AUTH-1;cisco-SSG-Account-Info=ALOCAL_L4R
 
#radius.serviceName.disable=L4REDIRECT,OPENGARDEN
#sa.radius.service.disable=L4REDIRECT,OPENGARDEN
 
#Для автоматического привязывания MAC-адреса к сервису в конфигурации модуля/типа сервиса/устройства/типа устройства можно прописать
#serv.macAddress.auto=1
 
# Пауза между выполнениями команды после ошибки
manage.error.pause=5
# Пауза между получением uptime
manage.uptime.pause=360
# Пауза после ошибки, возникшей при получении uptime
manage.uptime.error.pause=360
 
# Синхронизировать ли сервисы при обнаружении перезагрузки, 0 - не синхронизировать (по умолчанию), 1 - синхронизировать
# (для обнаружения перезагрузки в типе устройства должен быть установлен обработчик управления устройством)
#sa.device.sync.onReboot=0
# Вызывать ли при синхронизации для каждого сервиса, 0 - только serviceCreate или 1 (по умолчанию)  
# сначала serviceCancel, а затем serviceCreate
#sa.device.sync.cancelBeforeCreate=1

Здесь нужно обратить внимание на:

# Поиск устройства по giaddr и remoteId - 1,
# поиск устройства только по giaddr, агентское устройство ищется отдельно, после preprocessDhcpRequest - 2,
dhcp.deviceSearchMode=1
 
# Поиск сервиса Inet по 
dhcp.servSearchMode=1
 
# выдавать тот же IP адрес, что при открытом доступе
dhcp.disable.mode=1
 
# при появлении нового DISCOVER закрываем предыдущую сессию в биллинге
#dhcp.connection.closeOnNew=1
 
# Берем адрес из Access-Request
radius.address.fromRequest=1
 
# Радиус атрибуты, выдаваемые при авторизации для сервисов
radius.inetOption.2.attributes=cisco-SSG-Account-Info=AISG-5MBPS
radius.inetOption.3.attributes=cisco-SSG-Account-Info=AISG-10MBPS
radius.inetOption.4.attributes=cisco-SSG-Account-Info=AISG-LOCAL
 
# чтобы, если деньги закончились, не закрывал сервисы, а закрывал сразу сессию ISG целиком - 0, иначе - 1
sa.radius.connection.withoutBreak=0

В radius.inetOption.2.attributes=cisco-SSG-Account-Info=AISG-5MBPS цифра 2 - это ID соответствующей Опции (ISG-5MBPS).
А это должно быть закомментировано:

# Коды ошибок, при которых вместо reject выдавать accept с заданными атрибутами
#(пользователю выдается серый адрес и устанавливается HTTP-редирект)
#radius.disable.accessCodes=1,2,3,4,10,11,12,46
 
# не посылать команды на отключение сервисов
#sa.radius.connection.close.disableServices=1 
 
#radius.disable.attributes=cisco-avpair=subscriber:accounting-list=ISG-AUTH-1;cisco-SSG-Account-Info=ALOCAL_L4R
#radius.serviceName.disable=L4REDIRECT,OPENGARDEN
#sa.radius.service.disable=L4REDIRECT,OPENGARDEN

Полный конфиг типа устройств SW-1:

# Код субопции 82, содержащей VLAN, позиция и длина в субопции
dhcp.option82.vlanId.code=1
dhcp.option82.vlanId.position=0
dhcp.option82.vlanId.length=2
 
dhcp.option82.interfaceId.code=1
dhcp.option82.interfaceId.position=2
dhcp.option82.interfaceId.length=2
 
dhcp.option.leaseTime=600
 
# параметры DHCP к сети не привязанные
dhcp.option.serverIdentifier=0.0.0.0
#dhcp.option.leaseTime=600
#dhcp.option.timeServer=ntp.bgbilling.ru
# параметр DHCP "основной шлюз" для сети
#dhcp.net.option.188.191.0.0:255.255.255.0.gate=
#dhcp.net.option.188.191.1.0:255.255.255.0.gate=
#dhcp.net.option.188.191.2.0:255.255.255.0.gate=
#dhcp.net.option.188.191.3.0:255.255.255.0.gate=
 
#dhcp.option.timeOffset=43200
#dhcp.option.domainName=bgbilling.ru

Полный конфиг устройства Access+Acounting:

ip.resource.categoryId=1

Полный конфиг устройства R31_ASR1002:

# Хост для отправки PoD и CoA запросов (по умолчанию - хост, заданный в параметрах устройства Хост/порт)
#radius.host=<хост устройства>
# порт для отправки PoD и CoA запросов (по умолчанию - порт, заданный в параметрах устройства Хост/порт)
radius.port=1700
# идентификатор - Nas-Identifier (по умолчанию - значение из поля Идентификатор параметров устройства)
#radius.identifier=<идентификатор устройства>
# используемый secret для общения по radius-протоколу (по умолчанию - значение из поля Community/secret параметров устройства)
#radius.secret=<community/sercret устройства>
sa.radius.secret=***
# Сommunity (по умолчанию из параметра устройства Сommunity/Secret)
snmp.community=***

Полный конфиг устройства SW-1:

ip.resource.categoryId=1
vlan.resource.category=1
dhcp.ipCategories=1

Полный конфиг модуля Inet:

# Активные и приостановленные статусы договора
contract.status.active.codes=0
contract.status.suspend.codes=3,4
 
# Проверка цены в тарифе: 0 - проверка отсутсвует, 1 - ошибка только? если у сессии есть трафик определенного типа,
# но для него нет цены, 2 - ошибка? если хотя бы для одного типа трафика в привязке типа сервиса нет цены (по умолчанию - 1)
#accounting.tariffication.checkPrice=1
 
# Режим активации учетного периода, если не используется скрипт на событие активации,
# 0 (по умолчанию) - активация со дня подключения (старта сессии), 1 - активация с начала месяца.
# Следует учитывать, что учетный период является второй величиной при вычислении пропорциональности
# в тарифной ветке "Диапазон трафика"
#accounting.period.activation.mode=0
 
# Нужно ли отключать сервис с типом инициации "по трафику", если тариф не найден
#serv.disableOnTariffError=0
 
#Пункты Web - меню
web.menuItem1=Отчет по сессиям Inet
web.menuItem2=Смена пароля на логины Inet
web.menuItem3=none
#web.menuItem3=Отчет по трафикам Inet
 
# Параметры автоматической генерации логина для сервиса.
# Минимальное значение логина при генерации логина
#serv.login.min=1
# Максимальное значение логина при генерации логина (т.е. если в базе присутствуют логины 1,2,3 и 10000000,
# то при генерации создастся логин 4, а не 10000001)
#serv.login.max=9999999
 
# Парамерты автоматической генерации пароля для сервиса. Можно указать в конфигурации модуля, конфигурации устройства, конфигурации типа сервиса
# (в последнем случае значения будут главнее):
# Минимальная длина пароля
serv.password.length.min=5
# Максимальная длина пароля
serv.password.length.max=16
# Разрешенные символы (используются также при генерации пароля)
serv.password.chars=1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
# Описание разрешенных символов, если пользователь ввел другие
serv.password.chars.description=В пароле допустимы только цифры и латинские буквы.
# Длина для автоматически генерируемого пароля
serv.password.length.auto=6
# Используемые символы для автоматически генерируемого пароля (по умолчанию значение берется из параметра serv.password.chars)
#serv.password.chars.auto=
 
# Параметры активации карточек модуля card при использовании InetRadiusProcessor,
# данные параметры можно указать как в конфигурации модуля, так и в конфигурации устройства.
# Код модуля card
#card.moduleId=
# id услуг активации
#card.activate.serviceIds=
# Минимальное значение карточного логина используется, чтобы указать, какие числовые логины нужно искать в карточках;
# если 0, то ограничение не действует.
#card.login.min=0
# Максимальное значение карточного логина используется, чтобы указать, какие числовые логины нужно искать в карточках;
# если 0, то ограничение не действует.
#card.login.max=0




Вся вышеприведенная конфигурация будет работать только если ISG сервисы будут описаны локально (на BRAS'е). Чтобы загружать сервисы из биллинга (как изначально предполагалось), создаем еще один тип устройств ASR ISG Service Auth (это будет уже второй тип для одного и того же BRAS'а, первый тип был - ASR ISG):

Типы устройств: ASR ISG Service Auth (BRAS)

Затем создаем и вторую иерархию устройств:

  • еще одно абстрактное устройство типа Access+Accounting: Service Auth
  • и второе устройство R31_ASR1002 (BRAS), но уже типа ASR ISG Service Auth
Устройства: R31_ASR1002 (типа ASR ISG Service Auth)
Устройства: R31_ASR1002 (типа ASR ISG Service Auth), конфиг

Для чего все это нужно?
Во первых - в новом типе устройств ASR ISG Service Auth описываем ISG сервисы (Опции):

#Опция ISG-5MBPS
radius.inetOption.2.attributes=cisco-avpair=ip:traffic-class=in access-group 101 priority 201;cisco-avpair=ip:traffic-class=out access-group 102 priority 201;cisco-SSG-Service-Info=QU;;5120000;;384000;;768000;;D;;5120000;;960000;;1920000

Во вторых - на сервер устанавливаем еще одну копию BGInetAccess сервер для модуля Inet (переименовав его из BGInetAccess, к примеру, в BGInetServiceAccess) и в нем указываем в качестве root-устройства вершину второй иерархии: Service Auth (типа Access+Accounting):

<param name="rootDeviceId" value="3"/>

Полный конфиг (inet-access.xml):

<?xml version="1.0" encoding="UTF-8"?>
<application context="access">
	<!-- Уникальное имя приложения -->
	<param name="app.name" value="BGInetServiceAccess"/>
	<!-- Уникальный числовой id приложения -->
	<param name="app.id" value="10103"/>
 
	<!-- Параметры подключения к БД -->
	<param name="db.driver" value="com.mysql.jdbc.Driver"/>
	<param name="db.url" value="jdbc:mysql://127.0.0.1/bgbilling?useUnicode=true&amp;characterEncoding=Cp1251&amp;allowUrlInLocalInfile=true&amp;zeroDateTimeBehavior=convertToNull&amp;jdbcCompliantTruncation=false&amp;queryTimeoutKillsConnection=true&amp;connectTimeout=1000"/>
	<param name="db.user" value="bill"/>
	<param name="db.pswd" value="***"/>
	<param name="db.validationTimeout" value="10"/>
 
	<!-- Параметры подключения к MQ -->
	<param name="mq.url" value="failover:(tcp://localhost:61616)"/>
	<param name="mq.user" value="bill"/>
	<param name="mq.pswd" value="***"/>
 
	<!-- id модуля -->
	<param name="moduleId" value="2"/>
	<!-- id корневого устройства -->
	<param name="rootDeviceId" value="3"/>
	<!-- Типы фейковых устройств, являющихся аккаунтинг серверами -->
	<param name="accounting.deviceTypeIds" value="1"/>
 
	<!-- Внутренняя переменная приложения, не изменять -->
	<param name="commonIdentifierName" value="rootDeviceId"/>
 
	<!-- Параметры сохранения логов данных -->
	<!-- Директория, в которую сохранять radius логи -->
	<param name="datalog.radius.dir" value="data/radius" />
	<!-- Размер блока данных в файле лога, также размер буфера на лог файл -->
	<param name="datalog.radius.chunk.size" value="262144" />
	<!-- Сжимать radius логи: 0 - не сжимать, 1 - zlib -->
	<param name="datalog.radius.compression.type" value="1" />
	<!-- Директория, в которую сохранять flow логи -->
	<param name="datalog.dhcp.dir" value="data/dhcp" />
	<!-- Размер блока данных в файле лога, также размер буфера на лог файл -->
	<param name="datalog.dhcp.chunk.size" value="131072" />
	<!-- Сжимать flow логи: 0 - не сжимать, 1 - zlib -->
	<param name="datalog.dhcp.compression.type" value="1" />
 
 
	<!-- Создание Access -->
	<bean name="access" class="ru.bitel.bgbilling.modules.inet.access.Access" />
 
	<context name="radius">
		<!-- Cоздание процессора radius-пакетов -->
		<bean name="radiusProcessor" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusProcessor"/>
 
		<!-- Служебный ScheduledExecutorService, необходимый для dataLogger -->
		<scheduledExecutorService name="hrlydtlggr" corePoolSize="1" />
 
		<!-- Cоздание dataLogger, сохраняющего radius-пакеты на диск (только один экземпляр) -->
		<bean name="radiusDataLogger" class="ru.bitel.bgbilling.modules.inet.radius.RadiusHourlyDataLogger">
			<param name="scheduledExecutor">hrlydtlggr</param>
		</bean>
 
		<!-- Cоздание слушателя radius-пакетов на порту с передачей ему процессора и dataLogger -->
		<bean name="radiusListener" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusListener">
			<constructor>
				<!-- Хост (интерфейс), на котором будет открыт сокет. Если пусто - на всех -->
				<param name="host" value=""/>
				<!-- Порт, на котором будет открыт сокет -->
				<param name="port" value="1811"/>
				<!-- Размер буфера приема слушателя -->
				<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>
 
</application>

Запускаем и получаем второй radius-сервер (на порту 1811).

Создаем новый тип сервиса (не путать с ISG сервисами, те - назначаются на ISG сессию на циске, а эти - нечто вроде аккаунтов для доступа к услугам в BGBilling'е), который и будет описывать как биллингу авторизовывать радиус запросы с логинами равными именам ISG сервисов:

Типы сервисов: ISG Service (конфигурация)
Типы сервисов: ISG Service (типы устройств)

Теперь нужно завести отдельный договор, в котором для устройства Access+Accounting: Service Auth (вершина второй иерархии устройств, к которой и привязан второй радиус) будут созданы сервисы (типа ISG Service) с логинами равными именами ISG сервисов:

Договор ISG_SERVICE, сервисы
Договор ISG_SERVICE, сервис ISG-5MBPS

В результате, второй радиус сервер будет отвечать ACCESS-ACCEPT для запросов от BRAS'а, в которых логин=имя ISG сервиса.

Теперь осталось только привязать к этому сервису (не к ISG сервису, а к сервису договора, с логином сервиса равным имени ISG сервиса) соответствующую опцию:

Договор ISG_SERVICE, сервис ISG-5MBPS, опции

Описание этой опции (тело ISG сервиса) радиус найдет у дочернего к Access+Accounting: Service Auth устройства R31_ASR1002 в конфигурации его типа (ASR ISG Service Auth), и ответит BRAS'у:

Packet type: Access-Accept
Identifier: 98
Authenticator: {FB C8 D2 33 9D EC CF 10 04 0A 78 70 21 9A 69 04}
Attributes:
  Acct-Interim-Interval=60
  cisco-avpair=subscriber:accounting-list=ipoe-isg-aaa
  cisco-avpair=ip:traffic-class=in access-group 101 priority 201
  cisco-avpair=ip:traffic-class=out access-group 102 priority 201
  cisco-SSG-Service-Info=QU;5120000;384000;768000;D;5120000;960000;1920000


Вот и все!

Личные инструменты