Модифицированный скриптовый шлюз для DES-3526 и подобных
Материал из BiTel WiKi
Данный скрипт написан на основе скрипта Реалиазация_скриптовго_шлюза_для_коммутаторов_DES-3526,_DES-3550,_DES-3828,_DES-3852,_DGS-3200-10_и_им_подобных.
Содержание |
Задача
При разработке данного скрита решались следующие задачи:
- уменьшение объема скрипта за счет унификации кода, выполняемого при разных командах (открытие, закрытие, удаление);
- разделение кода скрипта и правил для коммутатора;
- возможность добавления нескольких IP-адресов на один порт.
Недостатки и недоделки
- правила для коммутатора вводятся все-таки в текст скрипта, а не в конфигурацию шлюза
- нельзя прописать один порт для разных договоров
- все манипуляции с IP-адресами договора надо проводить при состоянии его шлюза в положении удален (иначе некоторые записи в коммутаторе останутся до его перезагрузки)
- подключение к свитчу занимает 5 секунд (наверное это уже проблема в в биллинге - возможно он лезет к DNS)
- скрипт не проверяет текущее состояние коммутатора, а каждый раз загружает в него нужные команды
- в боевом режиме оно еще не проверялось
- не проверялось работа с ipn_dhcp (option82) - предполагается что при одном адресе на порт клиент будет автоматически получать IP, а при нескольких адресах (а это не является массовой услугой) прописывать адреса вручную
Предварительная настройка коммутатора
# этим правилом мы будем разрешать arp_reply c адресом абонента # это правила нужно тк абоненты (или вирусы на их компах) частенько присваивают себе адрес шлюза create access_profile packet_content_mask offset_0-15 0x0 0x0 0x0 0x0 offset_16-31 0xFFFF0000 0x0 0xFFFF0000 0x0 offset_32-47 0xFFFFFFFF 0x0 0x0 0x0 profile_id 20 #блокировка dhcp ответов и разрешение dhcp запросов (они могут отправляться не с IP-адреса пользователя) create access_profile ip udp dst_port_mask 0xFFFF profile_id 30 config access_profile profile_id 30 add access_id 1 ip udp dst_port 68 port 1 deny ... config access_profile profile_id 30 add access_id 24 ip udp dst_port 68 port 24 deny config access_profile profile_id 30 add access_id 101 ip udp dst_port 67 port 1 permit ... config access_profile profile_id 30 add access_id 124 ip udp dst_port 67 port 24 permit #правило для разрешения доступа пользователя к сети create access_profile ip source_ip_mask 255.255.255.255 profile_id 40 #правило для разрешения доступа пользователя к статистике create access_profile ip source_ip_mask 255.255.255.255 destination_ip_mask 255.255.255.0 profile_id 50 #разрешение arp-запросов create access_profile packet_content_mask offset_0-15 0x0 0x0 0x0 0x0 offset_16-31 0xFFFF0000 0x0 0xFFFF0000 0x0 profile_id 60 config access_profile profile_id 60 add access_id 1 packet_content_mask offset_0-15 0x0 0x0 0x0 0x0 offset_16-31 0x8060000 0x0 0x10000 0x0 port 1 permit .... config access_profile profile_id 60 add access_id 24 packet_content_mask offset_0-15 0x0 0x0 0x0 0x0 offset_16-31 0x8060000 0x0 0x10000 0x0 port 24 permit #блокируем всю остальную активность пользователя create access_profile ethernet source_mac 00-00-00-00-00-00 profile_id 200 config access_profile profile_id 200 add access_id 1 ethernet source_mac 00-00-00-00-00-00 port 1 deny config access_profile profile_id 200 add access_id 24 ethernet source_mac 00-00-00-00-00-00 port 24 deny
коммутатор будет работать с профилями с номерами 20, 40, 50:
при открытии шлюза добавляются правила 20, 40 и удаляется правило 50
при закрытии шлюза добавляются правила 20, 50 и удаляется правило 40
при удалении шлюза удаляются правила 20, 40, 50
Текст скрипта
import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import bitel.billing.common.IPUtils; import bitel.billing.common.module.ipn.IPNContractStatus; import bitel.billing.server.ipn.UserStatus; import bitel.billing.server.ipn.bean.ManadUtils; import bitel.billing.server.ipn.bean.VlanManager; import bitel.billing.server.ipn.dlink.UserPortStatus; import bitel.billing.server.util.DefaultServerSetup; import bitel.billing.server.util.Utils; import bitel.billing.server.util.telnet.OperationTimedoutException; import bitel.billing.server.util.telnet.TelnetSession; /* protected void doSync(){ log.info( "script started" ); }; */ protected void doSync(){ log.info( "script started" ); try { log.info( "script started 1" ); host = gate.getHost(); port = gate.getPort(); DefaultServerSetup gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" ); pswd = gate.getKeyword(); login = gateSetup.getStringValue( "login"); result = new StringBuffer(); if( log.isDebugEnabled() ) { log.info( gate.getId() + " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); } TelnetSession session = new TelnetSession( host, port); session.setLoginPromptSequence( ":" ); log.info( "before connect" ); session.connect(); log.info( "after connect" ); result.append( session.doCommand( login ) ); log.info( "after command" ); session.setLoginPromptSequence( "#" ); result.append( session.doCommand( pswd ) ); log.info( "before pswd" ); log.info( "execute commands" ); doCommands( session, result, gateSetup); //TODO commands here session.setLoginPromptSequence( "****" ); result.append( session.doCommand( "logout" ) ); log.info( result.toString() ); log.info( "ok" ); } catch (Exception e) { throw new RuntimeException ( e ); } }; private void doCommands( TelnetSession session, StringBuffer result, DefaultServerSetup gateSetup) throws IOException, OperationTimedoutException { openAddress = gateSetup.getStringValue( "open.address", "255.255.255.255" ) ; log.info( "openAddress = " + openAddress ); uplinks = Utils.stringToIntegerList( gateSetup.getStringValue( "uplink" ) ); ports = getUserList( statusList ); //-----настройки, вообще надо перенести ихв конфиг------------------------------------------------------------------- OpenRules = new String []{ "config access_profile profile_id 20 add access_id ${aid} packet_content_mask offset_0-15 0x0 0x0 0x0 0x0 offset_16-31 0x8060000 0x0 0x20000 0x0 offset_32-47 0x${ip_hex} 0x0 0x0 0x0 port ${port} permit", //доступ к сети "config access_profile profile_id 40 add access_id ${aid} ip source_ip ${ip} port ${port} permit", //удаляем правило доступа только к биллингу "config access_profile profile_id 50 delete access_id ${aid}" }; CloseRules = new String []{ //arp reply "config access_profile profile_id 20 add access_id ${aid} packet_content_mask offset_0-15 0x0 0x0 0x0 0x0 offset_16-31 0x8060000 0x0 0x20000 0x0 offset_32-47 0x${ip_hex} 0x0 0x0 0x0 port ${port} permit", //доступ к биллингу "config access_profile profile_id 50 add access_id ${aid} ip source_ip ${ip} destination_ip ${openAdress} port ${port} permit", //удаляем правило доступа только к сети "config access_profile profile_id 40 delete access_id ${aid}" }; RemoveRules = new String []{ //arp reply "config access_profile profile_id 20 delete access_id ${aid}", //удаляем правило доступа биллингу "config access_profile profile_id 50 delete access_id ${aid}", //удаляем правило доступа только к сети "config access_profile profile_id 40 delete access_id ${aid}" }; //--------------------------------------------------------------------------------------------------------------------- int j=1; for( UserPortStatus port : ports ) { log.info("port.ipAddr=" + port.ipAddr); switch (port.status.status) { case IPNContractStatus.STATUS_OPEN: ApplyRules = OpenRules; log.info("open_user"); break; case IPNContractStatus.STATUS_REMOVED: ApplyRules = RemoveRules; log.info("remove_user"); break; default: ApplyRules = CloseRules; log.info("close_user"); break; }; for (i = 0; i < ApplyRules.length; i++){ // for (String proto_rule : ApplyRules){ ip_hex=Convert2hex(port.ipAddr); rule=setValues(ApplyRules[i], port.port, port.ipAddr, openAddress, ip_hex , j); log.info("rule=" + rule); result.append( session.doCommand( rule ) ); } j=j+1; } }; private String setValues( String rule, int port, String ip, String openAddress, String ip_hex , int mod) { aid=26*mod+port; rule = rule.replaceAll( "\\$\\{port\\}", String.valueOf( port ) ); rule = rule.replaceAll( "\\$\\{ip\\}" , ip ); rule = rule.replaceAll( "\\$\\{openAdress\\}", openAddress ); rule = rule.replaceAll( "\\$\\{ip_hex\\}", ip_hex ); rule = rule.replaceAll( "\\$\\{aid\\}", String.valueOf(aid) ); return rule; } private String Convert2hex( String ip ){ addr=InetAddress.getByName(ip); bytes=addr.getAddress(); str=""; for(b : bytes){ str=str+b2h(b & 0xff); } return str; } private String b2h( b ){ hexChars = new String []{ "0", "1", "2", "3", "4", "5", "6", "7", "8","9", "A", "B", "C", "D", "E", "F" }; return (hexChars[b/16]+hexChars[b%16]); } protected void doParentSync() { } public List getUserList( List statusList ) { List userList = new ArrayList(); for( UserStatus status : statusList ) { String rule = status.rule.getRuleText(); StringTokenizer st = new StringTokenizer( rule, ";" ); while( st.hasMoreTokens() ) { String token = st.nextToken().trim(); data = token.split( ":" ); if( data.length == 2 ) { UserPortStatus portStatus = new UserPortStatus(); portStatus.port = Utils.parseIntString( data[0] ); portStatus.ipAddr = data[1]; portStatus.status = status; userList.add( portStatus ); } else if ( data.length == 3 ) { UserPortStatus portStatus = new UserPortStatus(); portStatus.port = Utils.parseIntString( data[0] ); portStatus.macAddr = data[1].toUpperCase().replaceAll( "\\-", " " ); portStatus.ipAddr = data[2]; portStatus.status = status; userList.add( portStatus ); } } } return userList; }