ISG

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску

Cisco ISG

Постановка задачи

В небольшом интернет-провайдере отказаться от использования VPN (pptp) для контроля сессий.
Траффик контролировать непосредсвенно на уровне IP. Контроль валидность src-IP осуществляется на уровне сети доступа (DHCP-snooping + ACL), любой клиент который попадает на роутер с ISG имеет верефицированный src-IP.

Требуется поддреживать следующие тарифы:

  1. Volume-Based Prepaid (помегабайтный тариф)
  2. Безлимитные тарифы (ограничение по скорости)
  3. (опционально) Тарифы с ограничением по скорости и времени. (Lagacy-тарифы, которые были предназначены для создания альтернативы диал-ап, пока не реализовано.)

Restrictions for ISG Prepaid Billing Support

Внимание: Volume-monitor работает только с суммарным траффиком. Возможно, это ограничение можно обойти созданием 2-х сервисов на входящий и исходящий траффик, однако я не вижу в этом смысла для себя на данный момент.

Вот цитата с cisco.com

  • ISG volume-based prepaid billing is not supported on the Cisco 10000-PRE2. не важно для меня
  • ISG prepaid billing support can only be applied to traffic flows that have been defined by an ISG traffic class.
  • Quotas are measured in seconds for time and in bytes for volume. There is no way to change the unit of measure. не важно для меня, непонятно кому может быть нужно что то другое
  • The volume quota is for combined upstream and downstream traffic.

Общяя схема работы

Общяя схема работы такова: Биллинг (оригинальная разработка) управляет RADIUS-сервером (FreeRadius), который в свою очередь хранит информацию о пользователях и сервисах в "понятном" для ISG виде. При необходимости что-либо изменить непосредсвенно на маршрутизаторе с ISG (например, изменить текущий тариф, если пользователь поменял себе тариф и хочет наблюдать изменение скорости) биллинг посылает CoA-пакет который вызывает деавторизацию пользователя и потом - повторную авторизацию с новыми параметрами.

Пользователи Volume-Based тарифов перенаправляются на "портал" при исчерпании лимита траффика.

Конфигурация маршрутизатора

Аппаратная платформа

#sh ver
Cisco IOS Software, 7200 Software (C7200P-ADVIPSERVICESK9-M), Version 12.2(33)SRD, RELEASE SOFTWARE (fc2)
...

ROM: System Bootstrap, Version 12.4(12.2r)T, RELEASE SOFTWARE (fc1)
BOOTLDR: Cisco IOS Software, 7200 Software (C7200P-BOOT-M), Version 12.4(4)XD10, RELEASE SOFTWARE (fc2)
...
System image file is "disk0:c7200p-advipservicesk9-mz.122-33.SRD.bin"
...
Cisco 7201 (c7201) processor (revision B) with 917504K/65536K bytes of memory.
Processor board ID 78002300
MPC7448 CPU at 1666Mhz, Implementation 0, Rev 2.2
1 slot midplane, Version 2.0

Last reset from power-on
1 FastEthernet interface
4 Gigabit Ethernet interfaces
2045K bytes of NVRAM.

250880K bytes of ATA PCMCIA card at slot 0 (Sector size 512 bytes).
65536K bytes of Flash internal SIMM (Sector size 512K).
Configuration register is 0x2102

Policy-Map

Для управления пользователями используются полиси-мап (policy-map) которые применяются на интерфейсы маршрутизатора.

policy-map type control ISG-CUSTOMERS-POLICY
 class type control ISG-IP-UNAUTH event timed-policy-expiry
  1 service disconnect
 !
 class type control always event quota-depleted
  1 set-param drop-traffic FALSE
 !
 class type control always event credit-exhausted
  1 service-policy type service name LOCAL_L4R
 !
 class type control always event session-start
  10 authorize aaa list ISG-AUTH-1 password ISG identifier source-ip-address
  20 set-timer UNAUTH-TIMER 1
  30 service-policy type service name SERVICE_L4R
 !
!

Этот policy-map означает

  1. Для сессий (или пакетов?) удовлетворяющих условию ISG-IP-UNAUTH выполнить действие 1 service disconnect.
  2. Для ВСЕХ (control always) событий quota-depleted установить параметр drop-traffic FALSE.
    Это значит что между событиями quota-depleted (исчерпан лимит сессии - траффика или времени) и credit-exhausted (ответ от "препейд-сервера" со значением квоты равной 0) траффик будет продолжать форвардиться.
    Отмечу, что теоретически возможна ситуация когда счет будет поплнен после события quota-depleted и до того как будет произведен перезапрос, событие credit-exhausted никогда не наступит.
  3. При инициации сесии (control always event session-start) будет произведена попытка авторизации (authorize aaa list ISG-AUTH-1 password ISG identifier source-ip-address) и в случае неуспеха (unauth) будет установлен сервис перенаправления (service-policy type service name SERVICE_L4R)

Class-Map

Траффик классифицируется с помощью конструкций class-map

Например: CLASS-TO-REDIRECT - определяет какой траффик следует редиректить (см. L4 REDIRECT)
Траффик будет классифицирован как соответвующий CLASS-TO-REDIRECT если ИЛИ входящий ИЛИ исхлодящий траффик попадет под ACL 197

class-map type traffic match-any CLASS-TO-REDIRECT
 match access-group output 197
 match access-group input 197
sh access-lists 197
Extended IP access list 197 (Compiled)
    10 permit tcp any any eq www (17990 matches)
    20 permit tcp any eq www any (4584 matches)
    100 deny ip any any (792518 matches)

class-map которому соответвуют unauth-клиенты (назначение таймера мне не ясно на 100%, но он присутвует во всех примерах.) (?)

class-map type control match-all ISG-IP-UNAUTH
 match timer UNAUTH-TIMER
 match authen-status unauthenticated

Конфигурация инерфейса

Далее policy-map применяется на интерфейс

sh run int gigabitEthernet 0/1.613

!
interface GigabitEthernet0/1.613
 encapsulation dot1Q 613
 ip address 123.123.244.193 255.255.255.248
 service-policy type control ISG-CUSTOMERS-POLICY
 ip subscriber routed
  initiator unclassified ip-address
end

ip subscriber routed означает что пользователи не подключены непосредсвенно к интерфейсу (т.е. их МАК-адреса использовать нельзя). initiator unclassified ip-address означает что сессия инициируется при появлении пакета с src- или dst-ip который не может быть отнесен ни к одной из существующих сессий.


На каждого пользователя в процессе работы применяется один или несколько сервисов. Траффик, который не принадлежит ни одному сервису будет dropped. Изменить эту политику нельзя. (?)

конфигурация AAA

Далее, для работы следует определить RADIUS-server который будет хранить информацию о пользователях и (опционально) сервисах.
Делается это следующим образом:

!
aaa group server radius ISG-RADIUS
 server 172.16.30.144 auth-port 1812 acct-port 1813
!

Собственно, более-менее "классическое" описание AAA

aaa authentication login ISG-AUTH-1 group ISG-RADIUS
aaa authorization network ISG-AUTH-1 group ISG-RADIUS
aaa accounting network ISG-AUTH-1 start-stop group ISG-RADIUS
radius-server attribute 44 include-in-access-req
radius-server attribute 44 extend-with-addr
radius-server attribute 8 include-in-access-req
radius-server attribute 32 include-in-accounting-req
radius-server attribute 55 include-in-acct-req
radius-server attribute 31 mac format unformatted
radius-server host 172.16.30.144 auth-port 1812 acct-port 1813 key 7 0100110D4F080E
radius-server vsa send cisco-nas-port
radius-server vsa send accounting
radius-server vsa send authentication
!

Настройка порядка просмотра источников сервисов - локальные или downloaded

Ключевой момент - указать default local, в противном случае нельзя будет использовать локально созданные сервисы.

aaa authorization subscriber-service default local group ISG-RADIUS



Конфигурация RADIUS-сервера

базовая настройка FreeRadius

В качестве радиус-сервера традиционно предпочитаю FreeRadius.

  1. Прописываем роутер с ISG как клиента с верным secret
  2. Создаем сервисы
  3. Создаем пользователей

Я решил пойти по комбинированому пути - сервисы, которых немного я решил хранить в конфигурационных файлах (что повышает наглядность). Кроме того, один сервис создан непосредсвенно на роутере (с целью демонстрации и такой возможности) Пользователей хранить в БД (mySQL по той причине что биллинг работает с этой БД)

Описание сервисов

Сервисы - суть, те же пользователи, описание их помещаю в файл /etc/raddb/users (местоположение зависит от ситсемы)

Предоплаченный тариф:

PREPAID_INTERNET  Password == "cisco"
                Cisco-AVPair += "ip:traffic-class=in access-group 196 priority 6",
                Cisco-AVPair += "ip:traffic-class=out access-group 196 priority 6",
                Cisco-AVPair += "ip:traffic-class=out default drop",
                Cisco-AVPair += "ip:traffic-class=in default drop",
                Cisco-AVPair += "prepaid-config=TRAFFIC_PREPAID"

Обратить внимание - сеть 99.99.99.0/24 исключена из сервиса PREPAID_INTERNET. Это сделано для того что бы траффик на сервер биллинга ("портал") не учитвался и не обрабатывался этим сервисом

access-list 196 deny   ip 99.99.99.0 0.0.0.255 any
access-list 196 deny   ip any 99.99.99.0 0.0.0.255
access-list 196 permit ip any any


Тариф "доступ только на сервер биллинга" ("портал")

BILLING_ACCESS  Password == "cisco"
                Cisco-AVPair += "ip:traffic-class=in access-group 195 priority 4",
                Cisco-AVPair += "ip:traffic-class=out access-group 195 priority 4",
                Cisco-Account-Info += "QU;512000;256000;D;512000;256000",

Обратно предыдущему - в ACL сервиса включены только сеть сервера биллинга ("портала")

access-list 195 permit ip 99.99.99.0 0.0.0.255 any
access-list 195 permit ip any 99.99.99.0 0.0.0.255
access-list 195 deny   ip any any


Сервис редиректа (осуществляет редирект на "портал" для всего траффика попавшего под ACL 197

SERVICE_L4R     Password == "cisco"
                Cisco-AVPair += "ip:l4redirect=redirect list 197 to group REDIRECT_NOPAY",
                Cisco-AVpair += "traffic-class=input access-group 197",
                Cisco-AVpair += "traffic-class=output access-group 197",
                Cisco-AVPair += "ip:traffic-class=out default drop",
                Cisco-AVPair += "ip:traffic-class=in default drop"
                Idle-Timeout =  "600"

Под редирект должен попадать только www (80 порт), что и отражено в ACL

access-list 197 permit tcp any any eq www
access-list 197 permit tcp any eq www any
access-list 197 deny   ip any any

Хотя можно использовать и именованые ACL я встречал упоминания о том, что они не всегда работают корректно, в отличии от нумерованых.


MySQL

Некоторые таблицы в БД radius немного модифицированы, некоторые - добавены.

radacct

В таблицу radacct добавлено поле AcctUpdateTime.

mysql> describe radacct;
+----------------------+-------------+------+-----+---------------------+----------------+
| Field                | Type        | Null | Key | Default             | Extra          |
+----------------------+-------------+------+-----+---------------------+----------------+
| RadAcctId            | bigint(21)  | NO   | PRI | NULL                | auto_increment |
| AcctSessionId        | varchar(32) | NO   | MUL |                     |                |
| AcctUniqueId         | varchar(32) | NO   | MUL |                     |                |
| UserName             | varchar(64) | NO   | MUL |                     |                |
| Realm                | varchar(64) | YES  |     |                     |                |
| NASIPAddress         | varchar(15) | NO   | MUL |                     |                |
| NASPortId            | varchar(15) | YES  |     | NULL                |                |
| NASPortType          | varchar(32) | YES  |     | NULL                |                |
| AcctStartTime        | datetime    | NO   | MUL | 0000-00-00 00:00:00 |                |
| AcctStopTime         | datetime    | NO   | MUL | 0000-00-00 00:00:00 |                |
| AcctUpdateTime       | timestamp   | NO   |     | CURRENT_TIMESTAMP   |                |
| AcctSessionTime      | int(12)     | YES  |     | NULL                |                |
| AcctAuthentic        | varchar(32) | YES  |     | NULL                |                |
| ConnectInfo_start    | varchar(50) | YES  |     | NULL                |                |
| ConnectInfo_stop     | varchar(50) | YES  |     | NULL                |                |
| AcctInputOctets      | bigint(20)  | YES  |     | NULL                |                |
| AcctOutputOctets     | bigint(20)  | YES  |     | NULL                |                |
| CalledStationId      | varchar(50) | NO   |     |                     |                |
| CallingStationId     | varchar(50) | NO   |     |                     |                |
| AcctTerminateCause   | varchar(32) | NO   |     |                     |                |
| ServiceType          | varchar(32) | YES  |     | NULL                |                |
| FramedProtocol       | varchar(32) | YES  |     | NULL                |                |
| FramedIPAddress      | varchar(15) | NO   | MUL |                     |                |
| AcctStartDelay       | int(12)     | YES  |     | NULL                |                |
| AcctStopDelay        | int(12)     | YES  |     | NULL                |                |
| XAscendSessionSvrKey | varchar(10) | YES  |     | NULL                |                |
+----------------------+-------------+------+-----+---------------------+----------------+

Дополнительны таблицы

Для базового взаимодействия с биллингом добавлена таблица billing_info куда биллинг записывает информацию о лимитах.

CREATE TABLE `billing_info` (
  `ip` varchar(255) default NULL,
  `traffic` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


Для тестов внесу лимит в таблицу для определенного IP

mysql> select * from billing_info;
+----------------+---------+
| ip             | traffic |
+----------------+---------+
| 123.123.244.194 | 1000000 |
+----------------+---------+
1 rows in set (0.00 sec)

radcheck

Далее добавляю пользователя в таблицу radcheck

mysql> select * from radcheck;
+----+----------------+---------------+----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | UserName       | Attribute     | op | Value                                                                                                                                                                                                                            |
+----+----------------+---------------+----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|  3 | 123.123.244.194 | Auth-Type     | := | `%{sql:SELECT IF((IF(traffic-(SUM(AcctInputOctets)+SUM(AcctOutputOctets))<=0,0,1)=0)And '%{Cisco-Account-Info}'='S%{User-Name}','Reject','Accept') FROM radacct right join billing_info on ip=username where ip='%{User-Name}'}` |
|  2 | 123.123.244.194 | User-Password | == | ISG                                                                                                                                                                                                                              |
+----+----------------+---------------+----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Radius xlat

На этом моменте стоит остановиться немного подробнее - во freeradius есть интересная возможность которая позволяет делать вычисляемые поля (модуль xlat).
Это реализуется с помощью конструкции

`%{sql:SELECT ....}`

В этой конструкции можно использовать переменные вид %{Attribute} - т.е. ссылаться на атрибуты содержащиеся в полученном пакете.


Соответвенно, запрос

SELECT IF((IF(traffic-(SUM(AcctInputOctets)+SUM(AcctOutputOctets))<=0,0,1)=0)And '%{Cisco-Account-Info}'='S%{User-Name}','Reject','Accept') FROM radacct right join billing_info on ip=username where ip='%{User-Name}'}`

Проверяем баланс траффика, если баланс положительный то сразу Accept, если нет то проверяем есть ли в запросе '%{Cisco-Account-Info}'='S%{User-Name и Reject или Accept по этому признаку. Нужно для того, что б пользователь с балансом траффка меньше 0 не мог воспользоваться никакими сервисами, но при этом возвращать Accept + лимит равный 0 для запросов переавторизации (см. ниже) или сразу Reject для запросов авторизации. А эти запросы отличать по значению поля '%{Cisco-Account-Info}'
В случае отсутвия атрибута в запросе - его значение будет NULL.


В случае если этот запрос вернул Accept то в Auth-Accept из таблицы radreply возвращаем атрибуты пользователя.

mysql> select * from radreply;
+----+----------------+--------------------+----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | UserName       | Attribute          | op | Value                                                                                                                                                                                                                                                           |
+----+----------------+--------------------+----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|  1 | 123.123.244.194 | Cisco-Service-Info | =  | NPREPAID_INTERNET                                                                                                                                                                                                                                               |
|  2 | 123.123.244.194 | Cisco-Control-Info | += | `%{sql:SELECT  IFNULL(CONCAT("QV", GREATEST(0,billing_info.traffic-(IFNULL(SUM(radacct.AcctInputOctets),0)+IFNULL(SUM(radacct.AcctOutputOctets),0)))),"QV0") FROM radacct right join billing_info on billing_info.ip=radacct.username where ip='%{User-Name}'}` |
|  3 | 123.123.244.194 | Service-Type       | =  | Outbound-User                                                                                                                                                                                                                                                   |
|  4 | 123.123.244.194 | Cisco-Account-Info | += | APREPAID_INTERNET                                                                                                                                                                                                                                               |
|  5 | 123.123.244.194 | Cisco-Account-Info | += | NPREPAID_INTERNET                                                                                                                                                                                                                                               |
|  6 | 123.123.244.194 | Idle-Timeout       | =  | 120                                                                                                                                                                                                                                                             |
|  7 | 123.123.244.194 | Cisco-Account-Info | += | ABILLING_ACCESS                                                                                                                                                                                                                                                 |
+----+----------------+--------------------+----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Запрос в Cisco-Control-Info возвращает квоту клиента в виде QV:<Чисто в Байтах>. Запрос слега замысловатый для обработки ситуации когда radacct пустой. (Null в качестве результатат этого запроса не устраивае, лимит будет бесконечным)

Тестирование

Проверяем что бы у клиента была положительная квота по траффику.

mysql> select billing_info.traffic-(sum(AcctOutputOctets)+sum(AcctInputOctets)) from radacct,billing_info where billing_info.ip=radacct.username and radacct.username='123.123.244.194';
+-------------------------------------------------------------------+
| billing_info.traffic-(sum(AcctOutputOctets)+sum(AcctInputOctets)) |
+-------------------------------------------------------------------+
|                                                              NULL |
+-------------------------------------------------------------------+

Запрос выше такую ситуацию обрабатывает и вернет 0 а не Null

Проверяем что бы на роутере не было сессий (для чистоты эксперемента)

Router#cle sss session all
Clear all subscriber service sessions?[confirm]

Router#sh sss session
%No active Subscriber Sessions


Пробуем иницировать сессию (ping ...), смотрим в радиус

ping  local.com.ua
PING local.com.ua (194.0.88.26) 56(84) bytes of data.
64 bytes from zain.local.com.ua (194.0.88.26): icmp_seq=2 ttl=59 time=10.1 ms

Первый пакет теряется всегда - требуется время на инициализацию сесиии.


Дальше смотрим в дебаг радиуса (запускать radiusd -XXXX)

Запрос на вторизацию. Если на этот запрос вернуть Reject сессия перейдет в состояние unath. атрибут Cisco-Account-Info = "S123.123.244.194" используется для того что бы отличить этот запрос от запросов на получение квоты траффика (см. ниже).

Access-Request packet from host 172.16.32.117:1645, id=115, length=153
        User-Name = "123.123.244.194"
        User-Password = "ISG"
        Framed-IP-Address = 123.123.244.194
        Cisco-Account-Info = "S123.123.244.194"
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Dialout-Framed-User
        NAS-IP-Address = 172.16.32.117
        Acct-Session-Id = "C345F40100004D69"

Ответ - пользователь авторизован, Ему нужно применить сервисы PREPAID_INTERNET и BILLING_ACCESS Остальные поля не являются обязательными на данном этапе, и игнорируются(?) (уточнить!)

Access-Accept of id 115 to 172.16.32.117 port 1645
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Cisco-Control-Info += "QV1000000"
        Service-Type = Dialout-Framed-User
        Cisco-Account-Info += "APREPAID_INTERNET"
        Cisco-Account-Info += "NPREPAID_INTERNET"
        Idle-Timeout = 120
        Cisco-Account-Info += "ABILLING_ACCESS"

Запрос информации о сервисе BILLING_ACCESS

Access-Request packet from host 172.16.32.117:1645, id=116, length=124
        User-Name = "BILLING_ACCESS"
        User-Password = "cisco"
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Dialout-Framed-User
        NAS-IP-Address = 172.16.32.117
        Acct-Session-Id = "C345F40100004D69"

Отвеет - это сервис определяемый 195 access-list и лимит скорости у него 512кбит (такая скорость взята для тестов)

Access-Accept of id 116 to 172.16.32.117 port 1645
        Cisco-AVPair += "ip:traffic-class=in access-group 195 priority 4"
        Cisco-AVPair += "ip:traffic-class=out access-group 195 priority 4"
        Cisco-Account-Info += "QU;512000;256000;D;512000;256000"

Аналогично, запрос информации о сервисе PREPAID_INTERNET

Access-Request packet from host 172.16.32.117:1645, id=117, length=126
        User-Name = "PREPAID_INTERNET"
        User-Password = "cisco"
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Dialout-Framed-User
        NAS-IP-Address = 172.16.32.117
        Acct-Session-Id = "C345F40100004D69"

Ответ - сервис определяемый 196-м ACL и использовать prepaid-config=TRAFFIC_PREPAID

TRAFFIC_PREPAID - препейд-конфиг, предварительно настроеный на роутере.

Access-Accept of id 117 to 172.16.32.117 port 1645
        Cisco-AVPair += "ip:traffic-class=in access-group 196 priority 6"
        Cisco-AVPair += "ip:traffic-class=out access-group 196 priority 6"
        Cisco-AVPair += "ip:traffic-class=out default drop"
        Cisco-AVPair += "ip:traffic-class=in default drop"
        Cisco-AVPair += "prepaid-config=TRAFFIC_PREPAID"

Конфигурация "препейд" - определяет пороги срабатывания квот и методы авторизации и аккаунтинга.

subscriber feature prepaid TRAFFIC_PREPAID
 threshold time 1 seconds
 threshold volume 1 bytes
 interim-interval 1 minutes
 method-list author ISG-AUTH-1
 method-list accounting ISG-AUTH-1
 password ISG
!

Prepaid-Server (краткое отступление)

Небольшое отступление:насколько я понимаю, предпологается что для сервисов используется отдельный радиус-сервер (prepaid-server) , соответвенно, в конфигурации этого сервиса будет пользователь с таким-же User-Name (в моем случае - IP адрес) но другим паролем.
Я для упрощения системы, сделал один серер авторизации совпадающий с "препейд-сервером", отсюда совпадение паролей
password ISG и   10 authorize aaa list ISG-AUTH-1 password ISG identifier source-ip-address.
Насколько я могу судить, в такой конфигурации все работает нормально, т.к. роутер игнорирует те атрибуты в ответах, которые не ожидает получить на свой запрос. Однако не исключено что в боле сложных конфигурациях с этим могут быть сложности.
Я не нашел способа определить спиок атрибутов которые радиус возвращает на основе запроса (т.е. нельзя вернуть Reply-Attibute-A если в запросе присутвует Request-Attribute-A="Value". Однако, с помощью xlat можно писать запросы которые будут возвращать разные значения предопределенных атрибутов на основе атрибутов пришедьших в запросе.

Этот момент требует дополнительно уточнения, но насколько я могу судить, в моей конфигурации можно обойтись без отдельного "перейд-сервера"

Инициализация сессии (radius)

Это запрос к "препейд-серверу" за квотой траффика, от запроса авторизации он отличается отсутвием аттрибута Cisco-Account-Info = "S123.123.244.194"

Access-Request packet from host 172.16.32.117:1645, id=118, length=161
        User-Name = "123.123.244.194"
        User-Password = "ISG"
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Framed-Protocol = PPP
        Framed-IP-Address = 123.123.244.194
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Framed-User
        NAS-IP-Address = 172.16.32.117
        Acct-Session-Id = "C345F40100004D6A"

Ответ - ключевым моментом в нем является значение квоты: Cisco-Control-Info += "QV1000000"

Access-Accept of id 118 to 172.16.32.117 port 1645
        Framed-IP-Address = 255.255.255.254
        Framed-MTU = 576
        Service-Type = Framed-User
        Framed-Protocol = PPP
        Framed-Compression = Van-Jacobson-TCP-IP
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Cisco-Control-Info += "QV1000000"
        Cisco-Account-Info += "APREPAID_INTERNET"
        Cisco-Account-Info += "NPREPAID_INTERNET"
        Idle-Timeout = 120
        Cisco-Account-Info += "ABILLING_ACCESS"


B далее - старт аккаунтинга.

Accounting-Request packet from host 172.16.32.117:1646, id=51, length=219
        Acct-Session-Id = "C345F40100004D6A"
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Framed-Protocol = PPP
        Framed-IP-Address = 123.123.244.194
        Cisco-AVPair = "parent-session-id=C345F40100004D69"
        User-Name = "123.123.244.194"
        Acct-Status-Type = Start
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Framed-User
        NAS-IP-Address = 172.16.32.117
        Event-Timestamp = "Jan 10 2009 17:03:26 EET"
        NAS-Identifier = "router.ua"

Обновление аккаунтинга.

Accounting-Request packet from host 172.16.32.117:1646, id=61, length=281
        Acct-Session-Id = "C345F40100004D6A"
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Framed-Protocol = PPP
        Framed-IP-Address = 123.123.244.194
        Cisco-AVPair = "parent-session-id=C345F40100004D69"
        User-Name = "123.123.244.194"
        Cisco-Control-Info = "I0;49392"
        Cisco-Control-Info = "O0;49224"
        Acct-Input-Packets = 588
        Acct-Output-Packets = 586
        Acct-Input-Octets = 49392
        Acct-Output-Octets = 49224
        Acct-Session-Time = 601
        Acct-Status-Type = Interim-Update
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Framed-User
        NAS-IP-Address = 172.16.32.117
        Event-Timestamp = "Jan 10 2009 17:13:27 EET"
        NAS-Identifier = "router.ua"
        Acct-Delay-Time = 0

Отмечу, что аккаунтинг содержит достаточно много полей, которые не вносятся в классическую таблицу radacct.

Инициализация сессии (router)

Проверяю состояние сессии на роутере:

Router#sh sss session
Current Subscriber Information: Total sessions 1

Uniq ID Interface    State         Service      Identifier           Up-time
179     IP           authen        Local Term   123.123.244.194       00:16:27


Более детально информация о учитываемом траффике

#sh sss session detail

.... пропущено ....


Session inbound features:
 Feature: Prepaid Idle Timeout
   Timeout configuration: 120 (seconds)
 Feature: Prepaid Volume Monitor
   Threshold:999999 - Quota:1000000
   Usage(since last update):161828 - Total:161828
   Current states: Start
Session outbound features:
 Feature: Prepaid Idle Timeout
   Timeout configuration: 120 (seconds)
 Feature: Prepaid Volume Monitor
   Threshold:999999 - Quota:1000000
   Usage(since last update):161828 - Total:161828
   Current states: Start
Configuration sources associated with this session:
Service: PREPAID_INTERNET, Active Time = 00:16:39

Исчерпание кредита

Далее пробуем израсходовать траффик и наблюдать за ситуацией...

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

 class type control always event quota-depleted
  1 set-param drop-traffic FALSE

Этим поведением можно управлять.

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

Sending Access-Accept of id 126 to 172.16.32.117 port 1645
        Framed-IP-Address = 255.255.255.254
        Framed-MTU = 576
        Service-Type = Framed-User
        Framed-Protocol = PPP
        Framed-Compression = Van-Jacobson-TCP-IP
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Cisco-Control-Info += "QV0"
        Cisco-Account-Info += "APREPAID_INTERNET"
        Cisco-Account-Info += "NPREPAID_INTERNET"
        Idle-Timeout = 120
        Cisco-Account-Info += "ABILLING_ACCESS"


Получив Cisco-Control-Info += "QV0" на роутере будет сгененрировано событие credit-exhausted и соответвенно применен сервис 1 service-policy type service name LOCAL_L4R описаный в моем случае локально на роутере.

!
policy-map type service LOCAL_L4R
 ip access-group 197 in
 ip access-group 197 out
 1 class type traffic CLASS-TO-REDIRECT
  redirect to group REDIRECT_NOPAY
 !
!

При этом траффик не проходит в мир, и при попытке открыть любую www-страницу будет осуществлен редирект на биллинг.

Поплнение счета пользователя

Далее - пробуем осуществить тестовое "пополнение счета" пользователя. Этого достаточно что б перекрыть тот небольшой минус который образовался из-за отстования аккаунтинга.

mysql> update billing_info set traffic=2000000;


Подождав примерно миуту, вижу в радиусе перезапрос траффика

Access-Request packet from host 172.16.32.117:1645, id=137, length=178
        User-Name = "123.123.244.194"
        User-Password = "ISG"
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Framed-Protocol = PPP
        Framed-IP-Address = 123.123.244.194
        Cisco-Control-Info = "QV1756357"
        NAS-Port-Type = Virtual
        Cisco-NAS-Port = "0/0/1/613"
        NAS-Port = 0
        NAS-Port-Id = "0/0/1/613"
        Service-Type = Framed-User
        NAS-IP-Address = 172.16.32.117
        Acct-Session-Id = "C345F40100004D6A"

Возвращаем новую квоту:

Access-Accept of id 137 to 172.16.32.117 port 1645
        Framed-IP-Address = 255.255.255.254
        Framed-MTU = 576
        Service-Type = Framed-User
        Framed-Protocol = PPP
        Framed-Compression = Van-Jacobson-TCP-IP
        Cisco-Service-Info = "NPREPAID_INTERNET"
        Cisco-Control-Info += "QV243643"
        Cisco-Account-Info += "APREPAID_INTERNET"
        Cisco-Account-Info += "NPREPAID_INTERNET"
        Idle-Timeout = 120
        Cisco-Account-Info += "ABILLING_ACCESS"

И траффик начинает ходить нормально, редирект отключается.

Изменение тарифов и установка новых квот

Однако, в случае если этого не произойдет, для "сброса с линии" можно использовать механизм CoA

Дальнейшие планы

  1. проверить работу с несколькими сервисами с разной скоростью доступа к сети (в моем случае сервисов будет 3 - локальный харьковский узел обмена траффиком (KH-IX), всеукраинский узел обмена траффиком (UA-IX) и "мировой" траффик.
  2. смена тарифов
  3. раздельный аккаунтинг по сервисам

Debug


Для дебага мне понадобилось:

#sh debugging
SSS:
  SSS Manager events debugging is on
  SSS Manager errors debugging is on
  SSS policy events debugging is on
  SSS policy state machine debugging is on
  SSS policy all debugs debugging is on
  SSS policy detailed events debugging is on
  SSS policy error debugging is on
Subscriber Service Switch/Policy condition map:
  Subscriber policy condition map events debugging is on
Subscriber Service Switch/Policy rules:
  Subscriber Service Switch policy rules events debugging is on
Subscriber Service Switch/Policy service:
  Subscriber service events debugging is on
SSF/Access-list:
  ACL feature packets debugging is on
  ACL feature events debugging is on
SSF/L4R:
  L4 Redirect feature events debugging is on
  L4 Redirect feature errors debugging is on
  L4 Redirect feature packets debugging is on
SSF/Volume-Monitor:
  Prepaid volume monitor feature errors debugging is on
  Prepaid volume monitor feature events debugging is on

Список использованной литературы

http://forum.nag.ru/forum/index.php?showtopic=45688
http://forum.nag.ru/forum/index.php?showtopic=41243
http://forum.nag.ru/forum/index.php?showtopic=42945
http://www.opennet.ru/openforum/vsluhforumID6/17551.html
http://www.opennet.ru/openforum/vsluhforumID6/15205.html
http://www.opennet.ru/openforum/vsluhforumID6/14964.html
http://www.ciscosystems.com/en/US/docs/ios/12_2sb/isg/coa/guide/isg_ig.html
http://www.cisco.com/en/US/docs/ios/12_2sb/isg/configuration/guide/isg_c.html
http://www.cisco.com/en/US/docs/ios/12_3t/12_3t11/feature/guide/gtssgdfq.html
http://www.cisco.com/en/US/docs/ios/isg/configuration/guide/isg_tshoot_sa_dcd.html
http://www.ciscosystems.cd/en/US/docs/ios/isg/configuration/guide/isg_subscriber_svcs.html
http://www.cisco.com/en/US/docs/ios/solutions_docs/edge_ios/ge_rls4.html

Очень интресная статья
http://www.cisco.com/en/US/docs/ios/solutions_docs/edge_ios_migration/migv2.html#wp1246871
http://www.cisco.com/univercd/cc/td/doc/product/software/ios122sb/cg/isg_lib/index.htm