RedBack CLIPS
Материал из BiTel WiKi
Rush (Обсуждение | вклад) |
Rush (Обсуждение | вклад) (→Настройка биллинга) |
||
Строка 384: | Строка 384: | ||
== Настройка биллинга == | == Настройка биллинга == | ||
+ | |||
+ | Устанавливаем модуль Inet стандартным способом. | ||
+ | |||
+ | Скачиваем и устанавливаем приложения BGInetAccess и BGInetAccounting. | ||
+ | |||
+ | Конфигурация BGInetAccess (inet-access.xml): | ||
+ | <source lang='xml'> | ||
+ | <?xml version="1.0" encoding="UTF-8"?> | ||
+ | <application context="access"> | ||
+ | <param name="app.name" value="BGInetAccess"/> | ||
+ | <param name="app.id" value="1"/> | ||
+ | |||
+ | <param name="moduleId" value="15"/> | ||
+ | |||
+ | <param name="db.driver" value="com.mysql.jdbc.Driver"/> | ||
+ | <param name="db.url" value="jdbc:mysql://db.clink.ru/bgbilling?useUnicode=true&characterEncoding=Cp1251&allowUrlInLocalInfile=true&zeroDateTimeBehavior=convertToNull&jdbcCompliantTruncation=false&queryTimeoutKillsConnection=true"/> | ||
+ | <param name="db.user" value="bgbilling"/> | ||
+ | <param name="db.pswd" value="9muDwtZIBye8"/> | ||
+ | |||
+ | <param name="mq.url" value="failover:(tcp://localhost:61616)"/> | ||
+ | <param name="mq.user" value="bill"/> | ||
+ | <param name="mq.pswd" value="y4LtRThdoIko"/> | ||
+ | |||
+ | <param name="rootDeviceId" value="3"/> | ||
+ | <!-- типы фейковых устройств, являющихся аккаунтинг серверами --> | ||
+ | <param name="accounting.deviceTypeIds" value="3"/> | ||
+ | |||
+ | <param name="commonIdentifierName" value="rootDeviceId" /> | ||
+ | |||
+ | <bean name="access" class="ru.bitel.bgbilling.modules.inet.access.Access" /> | ||
+ | |||
+ | <param name="datalog.radius.dir" value="data/radius"/> | ||
+ | <param name="datalog.dhcp.dir" value="data/dhcp" /> | ||
+ | |||
+ | |||
+ | <context name="radius"> | ||
+ | <bean name="radiusProcessor" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusProcessor"/> | ||
+ | |||
+ | <scheduledExecutorService name="hrlydtlggr" corePoolSize="1" /> | ||
+ | |||
+ | <bean name="radiusDataLogger" class="ru.bitel.bgbilling.modules.inet.radius.RadiusHourlyDataLogger"> | ||
+ | <param name="scheduledExecutor">hrlydtlggr</param> | ||
+ | </bean> | ||
+ | |||
+ | <bean name="radiusListener" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusListener"> | ||
+ | <constructor> | ||
+ | <param name="host" value="194.165.18.10"/> | ||
+ | <param name="port" value="11812"/> | ||
+ | <param name="byteBufferCapacity">512 * 1024</param> | ||
+ | <param name="processor">radiusProcessor</param> | ||
+ | <param name="mode">RadiusListener.Mode.authentication</param> | ||
+ | <param name="dataLogger">radiusDataLogger</param> | ||
+ | <param name="threadCount">10</param> | ||
+ | <param name="maxQueueSize">200</param> | ||
+ | </constructor> | ||
+ | </bean> | ||
+ | </context> | ||
+ | |||
+ | <context name="dhcp"> | ||
+ | <bean name="dhcpProcessor" class="ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpHelperProcessor"/> | ||
+ | |||
+ | <bean name="dhcpListener" class="ru.bitel.bgbilling.kernel.network.dhcp.DhcpListener"> | ||
+ | <constructor> | ||
+ | <param name="host" value="194.165.18.10"/> | ||
+ | <param name="port" value="67"/> | ||
+ | <param name="byteBufferCapacity">512 * 1024</param> | ||
+ | <param name="processor">dhcpProcessor</param> | ||
+ | <param name="dataLogger"></param> | ||
+ | <param name="threadCount">10</param> | ||
+ | <param name="maxQueueSize">200</param> | ||
+ | </constructor> | ||
+ | </bean> | ||
+ | </context> | ||
+ | |||
+ | </application> | ||
+ | </source> | ||
== Ссылки == | == Ссылки == | ||
#[http://forum.bgbilling.ru/viewtopic.php?f=44&t=5361&start=15 Обсуждение на форуме] | #[http://forum.bgbilling.ru/viewtopic.php?f=44&t=5361&start=15 Обсуждение на форуме] |
Версия 03:08, 23 сентября 2011
CLIPS - это технология, используемая в оборудовании фирмы Ericsson для аутентификации, авторизации и аккаунтинга абонентов IPOE. Принципы CLIPS подробно описаны в документе "Clips HOWTO" ( http://shop.nag.ru/article/clips ).
В данной статье будет описана интеграция маршрутизатора SE100 с АСР BGBilling для работы с абонентами CLIPS.
Аутентификации абонентов происходит по порту коммутатора с использованием DHCP опции 82. В нашем случае SE100 является основным шлюзом и релеем для абонентов. Используется посервисный аккаунтинг, причем учитывается только внешний трафик.
Содержание |
Схема сети
Клиент - Коммутатор с Options.82 - SE100 - Мир | Сервер биллинга
Коммутатор проставляет Options.82 свой идентификатор, порт клиента и пересылает запрос на SE100 широковещательно. Из сети 172.16.23.0/24 выдаётся IP адрес авторизованным клиентам, из 172.16.25.0/24 - блокированным с установкой редиректа на страницу HTTP с ошибкой.
При необходимости блокировки сессии клиента устанавливается редирект на текущую сессию посредством CoA, делается пометка в DHCP сервере о истечении аренды. По следующему DHCP запросу отправляется NaK, после чего редбек завершает сессию и начинает новую. В новой сессии выдаётся уже адрес из пула фейковых адресов 172.16.25.0/24.
Сессия поднимается по Update пакету, т.к. в старт пакете отсутствует IP адрес. IP адрес перекладывается из атрибута Assigned-IP-Address в стандартный Framed-Ip-Address скриптов предобработки.
Из ответа авторизации Framed-Ip-Address удаляется, т.к. иначе редбек не шлёт DHCP запрос.
Трафики считаются суммарные по данным атрибутов Acct-Input/Output-Octets, Acct-Input/Output-Gigawords.
Процесс аутентификации
Когда клиент инициирует получение адреса, коммутатор вставляет в запрос опцию 82 и запрос попадает на интерфейс SE100.
Конфиг коммутатора (для примера возьмем D-link 3526):
# dhcp_local_relay позволяет вставлять в приходящие от абонентов DHCP-запросы опцию 82. enable dhcp_local_relay config dhcp_local_relay vlanid 2000 state enable # 2000 - вилан, настроенный на абонентских портах
Конфиг SE100:
context IPOE ! no ip domain-lookup ! # Интерфейс, к которому будут "биндиться" абоненты после авторизации interface CLIENTS multibind ip address 193.x.x.1/24 dhcp proxy 65535 ip arp secured-arp ! # Интерфейс, к которому будут "биндиться" абоненты, не прошедшие авторизацию (аналог Reject-To-Accept) interface NOAUTH multibind ip address 172.16.24.1/24 dhcp proxy 65535 ! # Интерфейс для общения с Radius-сервером interface loop0 loopback ip address 172.16.19.1/32 ip source-address radius dhcp-server no logging console logging syslog 194.xx.xx.2 facility local7 ! # Акцесс-лист для абонентов, не прошедших авторизацию. Разрешает работу DNS и DHCP, а также позволяет выйти на страницу управления и сайт провайдера. policy access-list HTTP-REDIRECT seq 10 permit tcp any host 194.xx.xx.10 eq www class CLS-NORMAL seq 19 permit udp any host 194.xx.xx.6 eq domain class CLS-NORMAL seq 20 permit tcp any host 194.xx.xx.3 eq www class CLS-NORMAL seq 21 permit udp any eq bootpc host 193.xx.xx.1 eq bootps class CLS-NORMAL seq 22 permit udp any eq bootpc host 172.16.24.1 eq bootps class CLS-NORMAL seq 30 permit tcp any any eq www class CLS-REDIRECT seq 40 permit ip any any class CLS-DROP ! # Классы для разделения трафика по зонам (локальный и внешний) policy access-list SUB-IN seq 10 permit ip any 194.xx.xx.0 0.0.1.255 class INTERNAL seq 20 permit ip any 193.xx.xx.0 0.0.3.255 class INTERNAL seq 30 permit ip any any class EXTERNAL ! policy access-list SUB-OUT seq 10 permit ip 194.xx.xx.0 0.0.1.255 any class INTERNAL seq 20 permit ip 193.xx.xx.0 0.0.3.255 any class INTERNAL seq 30 permit ip any any class EXTERNAL ! # Профиль http-редиректа (всех не прошедних авторизацию перенаправлять на страницу с ошибкой) http-redirect profile NOAUTH url "http://noauth.provider.ru/" # Настройки Radius aaa authentication administrator local aaa authentication administrator maximum sessions 1 aaa authentication subscriber radius aaa accounting subscriber radius aaa update subscriber 10 aaa accounting event dhcp aaa hint ip-address radius accounting server 194.xx.xx.10 encrypted-key 5FD62606082DAF92 port 11813 radius coa server 194.xx.xx.10 encrypted-key 5FD62606082DAF92 port 3799 ! radius server 194.xx.xx.10 encrypted-key 5FD62606082DAF92 port 11812 radius attribute nas-ip-address interface loop0 radius attribute nas-port format session-info radius attribute nas-identifier Redback-IPOE ! # Полиси по умолчанию для абонента (переопределяется через Radius-атрибуты) subscriber default qos policy policing DEF-IPOE-IN qos policy metering DEF-IPOE-OUT ! # Профиль сервиса. В нем задаются параметры подключения (скорость), а также указывается на то, что учет трафика необходимо вести по qos классу EXTERNAL radius service profile RSE-SVC-EXT parameter value Rate 100000 parameter value Burst 12500000 accounting in qos EXTERNAL accounting out qos EXTERNAL seq 10 attribute Dynamic-Policy-Filter "ip in forward class EXTERNAL qos" seq 20 attribute Dynamic-Policy-Filter "ip out forward class EXTERNAL qos" seq 30 attribute Dynamic-Qos-Parameter "meter-class-rate EXTERNAL rate-absolute $Rate" seq 40 attribute Dynamic-Qos-Parameter "meter-class-burst EXTERNAL $Burst" seq 50 attribute Dynamic-Qos-Parameter "police-class-rate EXTERNAL rate-absolute $Rate" seq 60 attribute Dynamic-Qos-Parameter "police-class-burst EXTERNAL $Burst" seq 70 attribute Service-Interim-Accounting 900 ! ip route 0.0.0.0/0 context local ! ! # Адрес DHCP-сервера dhcp relay server 194.165.18.17
После получения DHCP DISCOVER запроса, RedBack преобразует параметры запроса в Radius-атрибуты и отправляет Access-Request на указанный Radius-сервер. Запрос выглядит примерно следующим образом:
User-Name=f0:7d:68:82:59:27 NAS-Port-Id=2/1 vlan-id 2217 clips 169782 NAS-Identifier=Redback-IPOE User-Password=Redback NAS-IP-Address=172.16.19.1 NAS-Port=553650345 Service-Type=5 NAS-Port-Type=5 Platform-Type=4 Medium-Type=11 Agent-Remote-Id={01 06 1C BD B9 E6 48 78} DHCP-Option={3D 3D 07 01 F0 7D 68 82 59 27} DHCP-Option={0C 0C 07 44 49 52 2D 33 30 30} Agent-Circuit-Id={00 04 08 A9 00 01} OS-Version=6.5.1.3 Mac-Addr=f0-7d-68-82-59-27 NAS-Real-Port=553650345 UNKNOWN[3561--1]={02 0A 01 06 1C BD B9 E6 48 78} UNKNOWN[3561--1]={01 08 00 04 08 A9 00 01}
В качестве Radius-сервера используется приложение BGInetAccess. В качестве логина, SE подставляет MAC-адрес абонента. Параметры DHCP-опции 82 хранятся в атрибутах Agent-Remote-Id и Agent-Circuit-Id. Для того, чтобы авторизовать абонента по MAC-адресу коммутатора и порту, необходимо сгенерировать User-Name из этих параметров. Для этого используется динамический класс-обработчик процессора протокола (в биллинге задается в разделе "Типы устройств"), а именно метод preprocessAccessRequest:
public void preprocessAccessRequest( RadiusPacket request, RadiusPacket response, ConnectionSet connectionSet ) throws Exception { String macAddr = request.getStringAttribute( 2352, 145, null ); byte[] remoteId = request.getByteAttribute( 2352, 96, null ); byte[] circuitId = request.getByteAttribute( 2352, 97, null ); if( macAddr != null && remoteId != null && circuitId != null ) { String callingStation = macAddr.replaceAll( "\\-", "" ); String userName = ""; // Формируем User-Name формата <mac коммутатора>:<порт коммутатора> userName = Utils.bytesToHexString( remoteId ).substring(4, 16) + ":" + Utils.bytesToHexString( circuitId ).substring(10, 12); userName = userName.toLowerCase(); request.setStringAttribute( -1, 1, userName ); request.setStringAttribute( -1, 31, callingStation ); } }
При успешной аутентификации, BGInetAccess отправляет Access-Accept следующего вида:
Acct-Interim-Interval=900 Framed-IP-Address=193.106.88.119 # Атрибут, необходимый для получения абонентом IP-адреса DHCP-Max-Leases=1 # Атрибуты для включения сервиса для абонента. Устанавливают скорость соединения и включают посервисный аккаунтинг. Service-Name:1=RSE-SVC-EXT Service-Options:1=1 Service-Parameter:1=Rate=6000 Burst=750000 # Обязательный атрибут, указывает, к какому IP-интерфейсу "привязать" абонента IP-Interface-Name=CLIENTS
Для получения адреса по DHCP, в Radius ответе не должно быть атрибута Framed-IP-Address. Поэтому используется следующий метод для обработки ответа:
public void postprocessAccessRequest( RadiusPacket request, RadiusPacket response, ConnectionSet connectionSet ) throws Exception { response.removeAttributes( -1, 8 ); }
После успешной авторизации, SE посылает запрос на DHCP сервер. В качестве сервера DHCP используется то же самое приложение BGInetAccess. Для успешной привязки DHCP-запроса к сессии, необходимо предобработать его в соответствии с выбранным алгоритмом:
@Override public void preprocessDhcpRequest( DhcpPacket request, DhcpPacket response ) throws Exception { try { byte[] circuitId = request.getSubOption( (byte)1 ).value; byte[] remoteId = request.getSubOption( (byte)2 ).value; byte[] mac = new byte[6]; byte[] port = new byte[1]; System.arraycopy(circuitId, 5, port, 0, 1); System.arraycopy(remoteId, 2, mac, 0, 6); request.setSubOption( (byte)1, port); request.setSubOption( (byte)2, mac); } catch (java.lang.NullPointerException e) { return; } }
После этого абонент получает адрес и начинает работать.
Процесс аккаунтинга
После установления сессии, RedBack отправляет на Accounting-сервер сначала Start-пакет, и следом сразу же Update-пакет с Acct-Session-Time=0. Поскольку в Start-пакете отсутствует IP-адрес абонента, игнорируем его, в результате чего сессия стартует по первому Update-пакету.
IP адрес абонента приходит в VSA 132 ( Assigned-Ip-Address), поэтому для корректной работы биллинга необходимо скопировать его значение в параметр Framed-Ip-Address.
Поскольку при авторизации мы устанавливаем абоненту сервис RSE-SVC-EXT и включаем на нем посервисный аккаунтинг, SmartEdge помимо Accounting-пакетов для всей сессии, будет посылать пакеты для этого сервиса. Эти пакеты отличаются тем, что параметр Acct-Status-Type для Start, Stop и Update-пакетов равен 101, 102 и 103 соответственно. Параметр Acct-Session-Id формируется из Acct-Session-Id родительской сессии плюс строки вида RSE-SVC-EXT-1278BAF8. Идентификатор родительской сессии передается в параметре Acct-Multi-Session-Id.
Таким образом, для того чтобы учитывать у абонентов только внешний трафик, мы обнуляем значения параметров Acct-Input-Octets и Acct-Output-Octets для пакетов с Acct-Status-Type=3 и Acct-Status-Type=3.
У пакетов с Acct-Status-Type=102 и Acct-Status-Type=103 копируем параметр Acct-Multi-Session-Id в параметр Acct-Session-Id и устанавливаем Acct-Status-Type в 3. Таким образом посервисные пакеты выглядят для биллинга как обычные Update'ы.
Сессия останавливается по общему Stop-пакету с Acct-Session-Type=2.
Указанная логика реализуется в методе preprocessAccountingRequest класса SmartEdgeProtocolHandler:
@Override public void preprocessAccountingRequest( RadiusPacket request, RadiusPacket response, ConnectionSet connectionSet ) throws Exception { int acctStatusType = request.getIntAttribute( -1, 40, 0 ); // старты получается не обрабатываем, сессия стартует по апдейту if( acctStatusType != 1 && acctStatusType != 101 ) { preprocessAccessRequest( request, response, connectionSet ); Integer ipaddr = request.getIntAttribute( 2352, 132, null ); if( ipaddr != null ) { request.setIntAttribute( -1, 8, ipaddr ); } } if ( acctStatusType == 3 || acctStatusType == 2) { // обнуляем общие счетчики трафика (нас интересуют только посервисные) request.setIntAttribute(-1, 42, 0); request.setIntAttribute(-1, 43, 0); } if ( acctStatusType == 103 || acctStatusType == 102) { String sessionID = request.getStringAttribute(-1, 50, null); request.setStringAttribute(-1, 44, sessionID); } if ( acctStatusType == 103 || acctStatusType == 102) { request.setIntAttribute(-1, 40, 3); } }
Управление сессиями
Для смены параметров подключения абонента, используются запросы CoA. В нашем случае осуществляется либо изменение скорости соединения, либо отключение абонента.
В случае изменения скорости, необходимо отправить на Smart Edge два запроса: сначала отключить сервис, а затем тут же включить с новыми параметрами.
Acct-Session-Id=0100FFFF7800285F-4E7308EE Deactivate-Service-Name:1=RSE-SVC-EXT
Acct-Session-Id=0100FFFF7800285F-4E7308EE Service-Name:1=RSE-SVC-EXT Service-Options:1=1 Service-Parameter:1=Rate=48000 Burst=6000000
При отключении абонента по балансу, через CoA абонентской сессии устанавливаются параметры редиректа на страницу с ошибкой. Запрос выглядит следующим образом:
Acct-Interim-Interval=900 Acct-Session-Id=0100FFFF78002877-4E7308EE Forward-Policy=in:NOAUTH-IPOE HTTP-Redirect-Profile-Name=NOAUTH
Для того, чтобы пользователь получил адрес из "серой" сети, ему выдается DHCP NAK.
При включении абонента, ему также выдается DHCP NAK чтобы инициализировать получение нового адреса.
Это реализуется в методах connectionModify и connectionClose класса SmartEdgeServiceActivator:
public Object connectionModify( ServiceActivatorEvent event ) throws Exception { log.info( "Connection modify!" ); log.info( "oldState: " + event.getOldState() + "; newState: " + event.getNewState() + "; oldOptionSet: " + event.getOldOptions() + "; newOptionSet: " + event.getNewOptions() ); InetConnection connection = event.getConnection(); // это Reject-To-Accept коннект, нужно сбросить для инициации нормального коннекта if( event.getOldState() == InetServ.STATE_DISABLE && event.getNewState() == InetServ.STATE_ENABLE ) { // убрать из DHCP, чтобы выдало NaK EventProcessor.getInstance().request( new InetConnectionManager.ConnectionRemoveEvent( connection ) ); return null; } else { RadiusPacket packet = pod.createModifyRequest(); packet.addAttributes( serviceCloseAttributes ); preparePacket( packet, connection ); log.info( "Send CoA: \n" + packet ); pod.send( packet ); packet = pod.createModifyRequest(); preparePacket( packet, connection ); for( Integer optionId : event.getNewOptions() ) { RadiusAttributeSet attrs = optionSets.get( optionId ); if( attrs != null ) { packet.addAttributes( attrs ); } } log.info( "Send CoA: \n" + packet ); return pod.sendAsync( packet ); } }
public Object connectionClose( ServiceActivatorEvent event ) throws Exception { log.info( "Connection close!" ); InetConnection connection = event.getConnection(); RadiusPacket packet = pod.createModifyRequest(); preparePacket( packet, connection ); packet.addAttributes( lockAttributes ); // убрать из DHCP, чтобы выдало NaK EventProcessor.getInstance().request( new InetConnectionManager.ConnectionRemoveEvent( connection ) ); log.info( "Send CoA lock: \n" + packet ); return pod.sendAsync( packet ); }
Настройка биллинга
Устанавливаем модуль Inet стандартным способом.
Скачиваем и устанавливаем приложения BGInetAccess и BGInetAccounting.
Конфигурация BGInetAccess (inet-access.xml):
<?xml version="1.0" encoding="UTF-8"?> <application context="access"> <param name="app.name" value="BGInetAccess"/> <param name="app.id" value="1"/> <param name="moduleId" value="15"/> <param name="db.driver" value="com.mysql.jdbc.Driver"/> <param name="db.url" value="jdbc:mysql://db.clink.ru/bgbilling?useUnicode=true&characterEncoding=Cp1251&allowUrlInLocalInfile=true&zeroDateTimeBehavior=convertToNull&jdbcCompliantTruncation=false&queryTimeoutKillsConnection=true"/> <param name="db.user" value="bgbilling"/> <param name="db.pswd" value="9muDwtZIBye8"/> <param name="mq.url" value="failover:(tcp://localhost:61616)"/> <param name="mq.user" value="bill"/> <param name="mq.pswd" value="y4LtRThdoIko"/> <param name="rootDeviceId" value="3"/> <!-- типы фейковых устройств, являющихся аккаунтинг серверами --> <param name="accounting.deviceTypeIds" value="3"/> <param name="commonIdentifierName" value="rootDeviceId" /> <bean name="access" class="ru.bitel.bgbilling.modules.inet.access.Access" /> <param name="datalog.radius.dir" value="data/radius"/> <param name="datalog.dhcp.dir" value="data/dhcp" /> <context name="radius"> <bean name="radiusProcessor" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusProcessor"/> <scheduledExecutorService name="hrlydtlggr" corePoolSize="1" /> <bean name="radiusDataLogger" class="ru.bitel.bgbilling.modules.inet.radius.RadiusHourlyDataLogger"> <param name="scheduledExecutor">hrlydtlggr</param> </bean> <bean name="radiusListener" class="ru.bitel.bgbilling.modules.inet.radius.InetRadiusListener"> <constructor> <param name="host" value="194.165.18.10"/> <param name="port" value="11812"/> <param name="byteBufferCapacity">512 * 1024</param> <param name="processor">radiusProcessor</param> <param name="mode">RadiusListener.Mode.authentication</param> <param name="dataLogger">radiusDataLogger</param> <param name="threadCount">10</param> <param name="maxQueueSize">200</param> </constructor> </bean> </context> <context name="dhcp"> <bean name="dhcpProcessor" class="ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpHelperProcessor"/> <bean name="dhcpListener" class="ru.bitel.bgbilling.kernel.network.dhcp.DhcpListener"> <constructor> <param name="host" value="194.165.18.10"/> <param name="port" value="67"/> <param name="byteBufferCapacity">512 * 1024</param> <param name="processor">dhcpProcessor</param> <param name="dataLogger"></param> <param name="threadCount">10</param> <param name="maxQueueSize">200</param> </constructor> </bean> </context> </application>