Пример реализации скриптового универсального шлюза
Материал из BiTel WiKi
Max (Обсуждение | вклад) |
Max (Обсуждение | вклад) |
||
| Строка 1: | Строка 1: | ||
Стоит задача привязки CISCO 6509 SUP-2/MSFC-2/PFC2 IOS (c6sup2_rp-JK2O3SV-M), Version 12.1(26)E9, RELEASE SOFTWARE (fc1) к БГ-биллингу версии 4.5<br> | Стоит задача привязки CISCO 6509 SUP-2/MSFC-2/PFC2 IOS (c6sup2_rp-JK2O3SV-M), Version 12.1(26)E9, RELEASE SOFTWARE (fc1) к БГ-биллингу версии 4.5<br> | ||
| - | Так как весия IOS 12.1 поддерживает нумерацию правил акцесс-листа то из за этого шлюзы типа CISCO и CISCO2 не могут быть использованы для привязки данного железа к биллингу.<br> | + | Так как весия IOS 12.1 для коммутаторов не поддерживает нумерацию правил акцесс-листа то из за этого шлюзы типа CISCO и CISCO2 которые описаны в стандартной инструкции не могут быть использованы для привязки данного железа к биллингу.<br> |
| - | В версии 4.5 разработчиком по моей просьбе был написан интерфейс и скрипт вызова файла с логикой шлюза который позволяет использовать внешние скрипты, куда собственно я и вынес логику общения биллинга с моей цыской. | + | В версии 4.5 разработчиком по моей просьбе был написан интерфейс и скрипт (JAVA) вызова файла с логикой шлюза (ACC) который позволяет использовать внешние скрипты, куда собственно я и вынес логику общения биллинга с моей цыской.<br> |
| + | Рекомендую перед началом действий сначала всё прочитать, а только потом что то делать, так как структура файлов очень мудрённая. | ||
---- | ---- | ||
| - | И так, заходим в | + | И так, заходим в настройки модуля IPN<br> |
1. Создаём тип шлюза - Script-perl | 1. Создаём тип шлюза - Script-perl | ||
Закладка "Конфигурация" типа шлюза: | Закладка "Конфигурация" типа шлюза: | ||
| Строка 14: | Строка 15: | ||
script=/usr/local/BGBillingServer/ACC | script=/usr/local/BGBillingServer/ACC | ||
</pre> | </pre> | ||
| - | АСС - есть скрипт на перле с логикой связи | + | АСС - есть мой скрипт на перле с логикой связи, спасибо Мне! |
Закладка "Комманды" - оставляем пустой.<br> | Закладка "Комманды" - оставляем пустой.<br> | ||
| Строка 128: | Строка 129: | ||
} | } | ||
</pre> | </pre> | ||
| - | За данный код спасибо разработчикам. | + | За данный код спасибо разработчикам.<br> |
Нажимаем ОК.<br> | Нажимаем ОК.<br> | ||
Тип шлюза создан!<br> | Тип шлюза создан!<br> | ||
| Строка 143: | Строка 144: | ||
--- | --- | ||
| - | 3. Мой скрипт ACC написан на PERL использует телнет для управления | + | 3. Мой скрипт ACC написан на PERL и использует телнет для управления железом.<br> |
Для его работы необходим модуль NET:TELNET который можно взять из CPAN.<br> | Для его работы необходим модуль NET:TELNET который можно взять из CPAN.<br> | ||
| - | На цыске должен быть создан пользователь LOGIN с паролем PASS (крупные буквы заменить | + | На цыске должен быть создан пользователь LOGIN с паролем PASS (крупные буквы заменить своими значениями).<br> |
Для уменьшения проблем вот конфиг цыски оптимизированной под данную связку: | Для уменьшения проблем вот конфиг цыски оптимизированной под данную связку: | ||
<pre> | <pre> | ||
| - | username LOGIN privilege 15 secret | + | username LOGIN privilege 15 secret 0 PASS |
| + | ! | ||
interface Vlan11 | interface Vlan11 | ||
description "Kurchatova str." | description "Kurchatova str." | ||
| Строка 157: | Строка 159: | ||
ip policy route-map ACCESS-CLIENTS | ip policy route-map ACCESS-CLIENTS | ||
load-interval 30 | load-interval 30 | ||
| + | ! | ||
route-map ACCESS-CLIENTS permit 1 | route-map ACCESS-CLIENTS permit 1 | ||
match ip address 100 | match ip address 100 | ||
set interface Loopback0 Null0 | set interface Loopback0 Null0 | ||
| + | ! | ||
access-list 100 deny ip 123.123.123.4 0.0.0.3 any | access-list 100 deny ip 123.123.123.4 0.0.0.3 any | ||
access-list 100 permit ip any any | access-list 100 permit ip any any | ||
| + | ! | ||
line vty 0 15 | line vty 0 15 | ||
exec-timeout 0 0 | exec-timeout 0 0 | ||
| Строка 170: | Строка 175: | ||
</pre> | </pre> | ||
Небольшие пояснения к логике работы цыски:<br> | Небольшие пояснения к логике работы цыски:<br> | ||
| - | Существует роут-мап ACCESS-CLIENTS который вешается на IP интерфейс клиента (в примере vlan11), в данном роут-мапе сказано что любой трафик который попадает в акцесс-лист 100 стоит уничтожать (кстати тут можно прописать редирект на страницу, где сказано что доступ отсутствует из-за блокировки).<br> | + | Существует роут-мап ACCESS-CLIENTS который вешается на IP интерфейс клиента (в примере vlan11), в данном роут-мапе сказано что любой трафик который попадает в акцесс-лист 100 стоит уничтожать (кстати тут можно прописать редирект на страницу, где сказано что доступ отсутствует из-за блокировки - пока не реализовано).<br> |
| - | В акцесс-листе 100 мы прописываем всех кому нужен инет как DENY (этим как раз и занимается мой скрипт), тем самым их трафик не попадёт в роут-мап ACCESS-CLIENTS | + | В акцесс-листе 100 мы прописываем всех кому нужен инет как DENY (этим как раз и занимается мой скрипт), тем самым их трафик не попадёт в роут-мап ACCESS-CLIENTS.<br> |
| + | Так как последним правилом в данном листе стоит permit ip any any, то любой тарфик который не DENY будет уничтожен.<br> | ||
| + | Необходимо обязательно в ручную прописать все ваши сервера ДНС и хосты которые должны быть доступны клиентам до подключения как DENY!!!<br> | ||
| - | Код скрипта логики ACC | + | Код скрипта логики ACC: |
<pre> | <pre> | ||
#!/usr/bin/perl | #!/usr/bin/perl | ||
| Строка 299: | Строка 306: | ||
</pre> | </pre> | ||
| + | Скрипт может быть написан на чём угодно, хоть на шеле.<br> | ||
Для новичков и тех кто не знаком с перлом поясню:<br> | Для новичков и тех кто не знаком с перлом поясню:<br> | ||
| - | |||
Логика такая: скрипту АСС от биллинга передаютя параметры вида IP МАСКА НАС СТАТУС например (123.123.123.0 255.255.255.252 10.10.0.1 0)<br> | Логика такая: скрипту АСС от биллинга передаютя параметры вида IP МАСКА НАС СТАТУС например (123.123.123.0 255.255.255.252 10.10.0.1 0)<br> | ||
| - | Данная строка означает что клиент с сетью 123.123.123.0/30 пытается авторизоваться.<br> | + | Данная строка означает что клиент с сетью 123.123.123.0/30 и шлюзом 10.10.0.1 пытается авторизоваться.<br> |
Мой скрипт решает следующие проблемы:<br> | Мой скрипт решает следующие проблемы:<br> | ||
| - | 1. Опеределяет подключается или отключается клиент по флагу СТАТУС.<br> | + | 1. Опеределяет подключается или отключается клиент по флагу СТАТУС, флаг статус может меняться с 0 на 1.<br> |
2. Все цыски при заведнии записи в акцесс листах требуют ввода вайлкардовой маски, а биллинг передаёт её в десятичном виде.<br> | 2. Все цыски при заведнии записи в акцесс листах требуют ввода вайлкардовой маски, а биллинг передаёт её в десятичном виде.<br> | ||
3. Позволяет выбирать нас и профайл шлюза.<br> | 3. Позволяет выбирать нас и профайл шлюза.<br> | ||
| - | |||
В моём примере описано два типа шлюза 6509 - cisco и 2620 - cisco_2600 суть их видна в реализации.<br> | В моём примере описано два типа шлюза 6509 - cisco и 2620 - cisco_2600 суть их видна в реализации.<br> | ||
У 6509 задействован роут-мап, так как его использование снижает нагрузку по сравнению с методом навешивания на каждый интерфейс акцесс-листа и даёт очень широкое поле для манёвра с клиентским трафиком.<br> | У 6509 задействован роут-мап, так как его использование снижает нагрузку по сравнению с методом навешивания на каждый интерфейс акцесс-листа и даёт очень широкое поле для манёвра с клиентским трафиком.<br> | ||
Версия 20:51, 3 января 2009
Стоит задача привязки CISCO 6509 SUP-2/MSFC-2/PFC2 IOS (c6sup2_rp-JK2O3SV-M), Version 12.1(26)E9, RELEASE SOFTWARE (fc1) к БГ-биллингу версии 4.5
Так как весия IOS 12.1 для коммутаторов не поддерживает нумерацию правил акцесс-листа то из за этого шлюзы типа CISCO и CISCO2 которые описаны в стандартной инструкции не могут быть использованы для привязки данного железа к биллингу.
В версии 4.5 разработчиком по моей просьбе был написан интерфейс и скрипт (JAVA) вызова файла с логикой шлюза (ACC) который позволяет использовать внешние скрипты, куда собственно я и вынес логику общения биллинга с моей цыской.
Рекомендую перед началом действий сначала всё прочитать, а только потом что то делать, так как структура файлов очень мудрённая.
И так, заходим в настройки модуля IPN
1. Создаём тип шлюза - Script-perl
Закладка "Конфигурация" типа шлюза:
user_rule.editor.class=bitel.billing.module.services.ipn.editor.ManadContractRuleEditor gate_manager.class=bitel.billing.server.ipn.ManadGateWorker use.script=1 script=/usr/local/BGBillingServer/ACC
АСС - есть мой скрипт на перле с логикой связи, спасибо Мне!
Закладка "Комманды" - оставляем пустой.
Закладка "Типы правил" - оставляем пустой.
В закладке "Скрипт" пишем следующее:
import bitel.billing.server.ipn.bean.AddressRange;
import bitel.billing.server.ipn.UserStatus;
import bitel.billing.server.ipn.bean.AddressRangeManager;
import bitel.billing.server.util.DefaultServerSetup;
import bitel.billing.server.util.Utils;
import bitel.billing.common.IPUtils;
protected void doSync()
{
date = new GregorianCalendar();
gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n"
);
script = gateSetup.getStringValue( "script");
//цикл по всем договорам на этом шлюзе
for( UserStatus status : statusList )
{
cid = status.contractId;
//
AddressRangeManager man = new AddressRangeManager( con, mid );
addressList = man.getContractAddressRange( cid, date, -1 );
for ( AddressRange range : addressList)
{
ip = getIP( range);
mask = getMask ( range) ;
String host = gate.getHost();
if ( mask == null )
{
log.info( "Incorrect range for cid = " + cid );
continue;
}
log.info( "script = " + script );
log.info( "ip = " + ip );
log.info( "mask = " + mask );
log.info( "host = " + host );
String [] arguments = { script, ip, mask, host, String.valueOf( status.status ) };
//выполняем команду
Process process = Runtime.getRuntime().exec( arguments );
//ждем окончания работы процесса ..Это не обязательно
process.waitFor();
log.info( "exitCode=" + process.exitValue() );
}
}
}
getIP ( range )
{
return IPUtils.convertIpToString( range.getAddr1() );
}
getMask ( range )
{
result = null;
delta = range.getAddr2() - range.getAddr1() + 1;
int pow = getPow( delta );
log.info( "pow = " + pow );
//махинация для того чтоб получить 0xFFFFFFFF -в beanshell не
//получилось задать такое большое число и модификатор l в конце не работает
ffMask = (0xFFFFFFF);
ffMask = (ffMask << 8 ) | 0xFF;
if ( pow >= 0 )
{
mask = ffMask;
mask = (mask << pow) & ffMask;
result = IPUtils.convertIpToString( mask );
}
return result;
}
//находим разницу между двумя ip(она должна быть степеью двойки) и
//возращаем эту степень
int getPow( long delta )
{
int idx = 0;
int count = 0;
int pow = -1;
while ( delta > 0 )
{
if ( (delta & 1 ) == 1 )
{
count ++;
pow = idx;
if ( count > 1)
{
break;
}
}
delta = (delta >> 1);
idx++;
}
//если не одна единица в числе, значит это не степень двойки и
//диапазон задан неверно
if ( count != 1 )
{
pow = -1;
}
return pow;
}
За данный код спасибо разработчикам.
Нажимаем ОК.
Тип шлюза создан!
---
2. Идём в закладку Шлюзы.
Создаём шлюз:
В параметры Хост и порт шлюза, а так же Ключевое слово можно написать что угодно, оно для нас не имеет значения.
В "Тип шлюза" - указываем созданный нами тип шлюза - Script-perl
Комментарий и конфигурацию оставляем пустыми.
Шлюз создан!
---
3. Мой скрипт ACC написан на PERL и использует телнет для управления железом.
Для его работы необходим модуль NET:TELNET который можно взять из CPAN.
На цыске должен быть создан пользователь LOGIN с паролем PASS (крупные буквы заменить своими значениями).
Для уменьшения проблем вот конфиг цыски оптимизированной под данную связку:
username LOGIN privilege 15 secret 0 PASS ! interface Vlan11 description "Kurchatova str." ip address 123.123.123.1 255.255.255.0 no ip redirects ip route-cache policy ip route-cache flow ip policy route-map ACCESS-CLIENTS load-interval 30 ! route-map ACCESS-CLIENTS permit 1 match ip address 100 set interface Loopback0 Null0 ! access-list 100 deny ip 123.123.123.4 0.0.0.3 any access-list 100 permit ip any any ! line vty 0 15 exec-timeout 0 0 privilege level 15 logging synchronous transport input telnet ssh transport output telnet ssh
Небольшие пояснения к логике работы цыски:
Существует роут-мап ACCESS-CLIENTS который вешается на IP интерфейс клиента (в примере vlan11), в данном роут-мапе сказано что любой трафик который попадает в акцесс-лист 100 стоит уничтожать (кстати тут можно прописать редирект на страницу, где сказано что доступ отсутствует из-за блокировки - пока не реализовано).
В акцесс-листе 100 мы прописываем всех кому нужен инет как DENY (этим как раз и занимается мой скрипт), тем самым их трафик не попадёт в роут-мап ACCESS-CLIENTS.
Так как последним правилом в данном листе стоит permit ip any any, то любой тарфик который не DENY будет уничтожен.
Необходимо обязательно в ручную прописать все ваши сервера ДНС и хосты которые должны быть доступны клиентам до подключения как DENY!!!
Код скрипта логики ACC:
#!/usr/bin/perl
#edit 03.01.2009 23:21 Max
$ip=@ARGV[0];
$netmask=@ARGV[1];
$nas=@ARGV[2];
$status=@ARGV[3];
#Wailcard netmask
if($netmask eq '255.255.255.255'){$wnetmask='0.0.0.0';}
elsif($netmask eq '255.255.255.252'){$wnetmask='0.0.0.3';}
elsif($netmask eq '255.255.255.248'){$wnetmask='0.0.0.7';}
elsif($netmask eq '255.255.255.240'){$wnetmask='0.0.0.15';}
elsif($netmask eq '255.255.255.224'){$wnetmask='0.0.0.31';}
elsif($netmask eq '255.255.255.192'){$wnetmask='0.0.0.63';}
elsif($netmask eq '255.255.255.128'){$wnetmask='0.0.0.127';}
elsif($netmask eq '255.255.255.0'){$wnetmask='0.0.0.255';}
elsif($netmask eq '255.255.254.0'){$wnetmask='0.0.1.255';}
elsif($netmask eq '255.255.252.0'){$wnetmask='0.0.3.255';}
elsif($netmask eq '255.255.248.0'){$wnetmask='0.0.7.255';}
elsif($netmask eq '255.255.240.0'){$wnetmask='0.0.15.255';}
elsif($netmask eq '255.255.224.0'){$wnetmask='0.0.31.255';}
else{&error;}
if($status eq 0)
{&auth;}
else
{&no_auth;}
###########################################################
#AUTHORIZED################################################
###########################################################
sub auth{
#NAS
if($nas eq '10.11.0.6'){&cisco_2600;}
if($nas eq '10.11.0.10'){&cisco_2600;}
if($nas eq '10.11.0.14'){&cisco_2600;}
if($nas eq '10.11.0.1'){&cisco;}
&error;
}
sub cisco{
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 30, Prompt => '/#/');
$t->open("$nas") || die("False\n");
$t->login("LOGIN", "PASS");
$t->cmd(String => 'conf t', Cmd_remove_mode => 0);
$t->cmd("ip access-list extended 100");
$t->cmd("deny ip $ip $wnetmask any");
$t->cmd("no permit ip any any");
$t->cmd("permit ip any any");
$t->cmd("$cmd");
$t->cmd("exit");
exit 0;
}
sub cisco_2600{
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 30, Prompt => '/#/');
$t->open("$nas") || die("False\n");
$t->login("LOGIN", "PASS");
$t->cmd(String => 'conf t', Cmd_remove_mode => 0);
$t->cmd("ip access-list extended 100");
$t->cmd("permit ip $ip $wnetmask any");
$t->cmd("no deny ip any any");
$t->cmd("deny ip any any");
$t->cmd("$cmd");
$t->cmd("exit");
exit 0;
}
###########################################################
#NOAUTH####################################################
###########################################################
sub no_auth{
#NAS
if($nas eq '10.11.0.6'){&no_cisco_2600;}
if($nas eq '10.11.0.10'){&no_cisco_2600;}
if($nas eq '10.11.0.14'){&no_cisco_2600;}
if($nas eq '10.11.0.1'){&no_cisco;}
&error;
}
sub no_cisco{
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 30, Prompt => '/#/');
$t->open("$nas") || die("False\n");
$t->login("LOGIN", "PASS");
$t->cmd(String => 'conf t', Cmd_remove_mode => 0);
$t->cmd("ip access-list extended 100");
$t->cmd("no deny ip $ip $wnetmask any");
$t->cmd("$cmd");
$t->cmd("exit");
exit 0;
}
sub no_cisco_2600{
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 30, Prompt => '/#/');
$t->open("$nas") || die("False\n");
$t->login("LOGIN", "PASS");
$t->cmd(String => 'conf t', Cmd_remove_mode => 0);
$t->cmd("ip access-list extended 100");
$t->cmd("no permit ip $ip $wnetmask any");
$t->cmd("$cmd");
$t->cmd("exit");
exit 0;
}
#НЕ ОПРЕДЕЛЁН NAS#########################################################################
sub error{
open(ERR,">>/usr/local/BGBillingServer/log/err.connect.log");
print ERR "ERROR: CONNECT ip=$ip, netmask=$netmask|$wnetmask, nas=$nas, status=$status\n";
close ERR;
exit 1;
}
##########################################################################################
Скрипт может быть написан на чём угодно, хоть на шеле.
Для новичков и тех кто не знаком с перлом поясню:
Логика такая: скрипту АСС от биллинга передаютя параметры вида IP МАСКА НАС СТАТУС например (123.123.123.0 255.255.255.252 10.10.0.1 0)
Данная строка означает что клиент с сетью 123.123.123.0/30 и шлюзом 10.10.0.1 пытается авторизоваться.
Мой скрипт решает следующие проблемы:
1. Опеределяет подключается или отключается клиент по флагу СТАТУС, флаг статус может меняться с 0 на 1.
2. Все цыски при заведнии записи в акцесс листах требуют ввода вайлкардовой маски, а биллинг передаёт её в десятичном виде.
3. Позволяет выбирать нас и профайл шлюза.
В моём примере описано два типа шлюза 6509 - cisco и 2620 - cisco_2600 суть их видна в реализации.
У 6509 задействован роут-мап, так как его использование снижает нагрузку по сравнению с методом навешивания на каждый интерфейс акцесс-листа и даёт очень широкое поле для манёвра с клиентским трафиком.
У 2620 задействован только акцесс-лист ввиду малого количества абонентов за данным железом, и простотой использования.
Для тех кому есть что обсудить или спросить велкам в http://bgbilling.ru/forum/viewtopic.php?p=10713#10713
