Реалиазация шлюза на Cisco
Материал из BiTel WiKi
Blib  (Обсуждение | вклад)  (Новая: этот тип шлюза смотрит к какому источнику привязан ип адрес клиента после чего идет на этот роутер и д...)  | 
		Blib  (Обсуждение | вклад)   | 
		||
| Строка 58: | Строка 58: | ||
public class RouterGateWorker extends GateWorker {  | public class RouterGateWorker extends GateWorker {  | ||
| - | + |   private static SetupData setup = new SetupData("data.data");  | |
| - | + |   static final long maxSize = 64;  | |
| - | + |   @Override  | |
| - | + |   protected void doSync() {  | |
| - | + |     Long exclude[];  | |
| - | + |     DefaultServerSetup gateSetup = new DefaultServerSetup(gate.getConfig(), "\r\n");  | |
| - | + |     HashMap<String, ArrayList<String>> cmds = new HashMap<String, ArrayList<String>>();  | |
| - | + |     String login = gateSetup.getStringValue("login", "root");  | |
| - | + |     String pswd = gateSetup.getStringValue("password", "passwd");  | |
| - | + |     int debug = gateSetup.getIntValue("debug", gate.getGateType().getConfigSetup().getIntValue("debug", 0));  | |
| - | + |     int mid = gateSetup.getIntValue("mid", gate.getGateType().getConfigSetup().getIntValue("mid", -1));  | |
| - | + |     ArrayList<Long> ex = new ArrayList<Long>();  | |
| - | + |     for (Iterator it = gateSetup.getOrderedValues("exclude.").iterator(); it.hasNext();) {  | |
| - | + |       String s = (String) it.next();  | |
| - | + |       s = s.trim();  | |
| - | + |       StringTokenizer st = new StringTokenizer(s, "/");  | |
| - | + |       if (st.countTokens() != 2) {  | |
| - | + |         log.error("Cant parse gate config: " + s);  | |
| - | + |         gateErrors.append("Ошибка конфига\n");  | |
| - | + |         continue;  | |
| - | + |       }  | |
| - | + |       ex.add(aton(st.nextToken()));  | |
| - | + |       ex.add(aton(st.nextToken()));  | |
| - | + |     }  | |
| - | + |     exclude = ex.toArray(new Long[ex.size()]);  | |
| - | + |     Connection con = null;  | |
| - | + |     PreparedStatement ps = null;  | |
| - | + |     try {  | |
| - | + |       con = setup.getDBConnection();  | |
| - | + |       for (Iterator<UserStatus> it = statusList.iterator(); it.hasNext();) {  | |
| - | + |         UserStatus us = it.next();  | |
| - | + |         int cid = us.contractId;  | |
| - | + |         log.debug("CID:" + cid + " status:" + us.status);  | |
| - | + |         ps = con.prepareStatement("select * from ipn_user_range_" + mid + " where cid=? and "  | |
| - | + |             + " ( date1 is null or date1<=now() ) and ( date2 is null or date2>=now() )");  | |
| - | + |         ps.setInt(1, cid);  | |
| - | + |         ResultSet rs = ps.executeQuery();  | |
| - | + |         while (rs.next()) {  | |
| - | + |           int aid = rs.getInt("id");  | |
| - | + |           long a1 = rs.getBigDecimal("addr1").longValue();  | |
| - | + |           long a2 = rs.getBigDecimal("addr2").longValue();  | |
| - | + |           assert a1 < a2;  | |
| - | + |           PreparedStatement psSrc = con  | |
| - | + |               .prepareStatement("select s.title,s.host_or_dir,i.number,i.title from ipn_user_source_"  | |
| - | + |                   + mid + " us join source s on us.source_id=s.id left outer join ipn_iface_" + mid  | |
| - | + |                   + " i on us.source_id=i.source_id and us.iface=i.number where aid=?");  | |
| - | + |           psSrc.setInt(1, aid);  | |
| - | + |           ResultSet rs2 = psSrc.executeQuery();  | |
| - | + |           while (rs2.next()) {  | |
| - | + |             int n = rs2.getInt(3);  | |
| - | + |             String rtr = rs2.getString(2);  | |
| - | + |             if (n < 0 && a1!=0 ) {  | |
| - | + |               // ANY и addr1==0.0.0.0    | |
| - | + |               addcmd: {  | |
| - | + |                 // проверяем размер  | |
| - | + |                 if (Math.abs(a2 - a1) > maxSize) {  | |
| - | + |                   log.error("Exceed max network size, " + ntoa(a1) + "-" + ntoa(a2) + " cid:" + cid);  | |
| - | + |                   gateErrors.append("Превышен максимальный размер сети " + ntoa(a1) + "-" + ntoa(a2) + "\n");  | |
| - | + |                   break addcmd;  | |
| - | + |                 }  | |
| - | + |                 // проверяем попадают ли адреса в защищенный  | |
| - | + |                 // диапазон  | |
| - | + |                 for (int i = 0; i < exclude.length; i += 2)  | |
| - | + |                   if ((exclude[i] == (a1 & exclude[i + 1])) || (exclude[i] == (a2 & exclude[i + 1]))) {  | |
| - | + |                     log.error("Network excluded, " + ntoa(a1) + "-" + ntoa(a2) + " cid:" + cid);  | |
| - | + |                     gateErrors.append("Сеть защищена конфигом " + ntoa(a1) + "-" + ntoa(a2) + "\n");  | |
| - | + |                     break addcmd;  | |
| - | + |                   }  | |
| - | + |                 // все хорошо  | |
| - | + |                 for (long i = a1; i <= a2; i++)  | |
| - | + |                   addToCmdList(cmds, rtr, (us.status == 0 ? "no " : "") + "ip route " + ntoa(i)  | |
| - | + |                       + " 255.255.255.255 null0 tag 1901");  | |
| - | + |               }  | |
| - | + |             } else {  | |
| - | + |               // определенный интерфейс и addr1 == 0.0.0.0 (точно VPN)  | |
| - | + |               addToCmdList(cmds, rtr, "interface " + rs2.getString(4));  | |
| - | + |               addToCmdList(cmds, rtr, (us.status == 0 ? "no " : "") + "shutdown");  | |
| - | + |             }  | |
| - | + |           }  | |
| - | + |         }  | |
| - | + |       }  | |
| - | + |     } catch (SQLException e) {  | |
| - | + |       log.error(e.getLocalizedMessage(), e);  | |
| - | + |       gateErrors.append("Ошибка запроса в БД " + e.getLocalizedMessage() + "\n");  | |
| - | + |     } finally {  | |
| - | + |       if (ps != null)  | |
| - | + |         try {  | |
| - | + |           ps.close();  | |
| - | + |         } catch (SQLException e) {  | |
| - | + |           log.error(e.getLocalizedMessage(), e);  | |
| - | + |           gateErrors.append("Ошибка запроса в БД " + e.getLocalizedMessage() + "\n");  | |
| - | + |         }  | |
| - | + |     }  | |
| - | + |     if (debug > 0) {  | |
| - | + |       for (String host : cmds.keySet()) {  | |
| - | + |         log.debug("Debug mode telnet " + login + "@" + host);  | |
| - | + |         for (String c : cmds.get(host))  | |
| - | + |           log.debug(host+"  "+c);  | |
| - | + |         //gateErrors.append("режим отладки\n");  | |
| - | + |       }  | |
| - | + |     } else  | |
| - | + |       for (String host : cmds.keySet()) {  | |
| - | + |         try {  | |
| - | + |           log.debug("telnet " + login + "@" + host);  | |
| - | + |           Expect4j exp = ExpectUtils.telnet(host, 23);  | |
| - | + |           if (exp.expect("ogin:") < 0)  | |
| - | + |             throw new RuntimeException("failed match login prompt");  | |
| - | + |           exp.send(login + "\n");  | |
| - | + |           if (exp.expect("assword:") < 0)  | |
| - | + |             throw new RuntimeException("failed match password prompt");  | |
| - | + |           exp.send(pswd + "\n");  | |
| - | + |           if (exp.expect("#") < 0)  | |
| - | + |             throw new RuntimeException("failed match prompt 0");  | |
| - | + |           exp.send("conf term\n");  | |
| - | + |           for (String c : cmds.get(host)) {  | |
| - | + |             log.debug(c);  | |
| - | + |             if (exp.expect("#") < 0)  | |
| - | + |               throw new RuntimeException("failed match prompt 1");  | |
| - | + |             exp.send(c + "\n");  | |
| - | + |           }  | |
| - | + |           if (exp.expect("#") < 0)  | |
| - | + |             throw new RuntimeException("failed match prompt 2");  | |
| - | + |           exp.send("end\n");  | |
| - | + |           if (exp.expect("#") < 0)  | |
| - | + |             throw new RuntimeException("failed match prompt 3");  | |
| - | + |           exp.send("exit\n");  | |
| - | + |           exp.close();  | |
| - | + |         } catch (Exception e) {  | |
| - | + |           log.error("telnet " + login + "@" + host);  | |
| - | + |           for (String c : cmds.get(host))  | |
| - | + |             log.error(c);  | |
| - | + |           log.error(e.getLocalizedMessage(), e);  | |
| - | + |           gateErrors.append("Ошибка " + e.getLocalizedMessage() + "\n");  | |
| - | + |         }  | |
| - | + |       }  | |
| - | + |   }  | |
| - | + |   public final static String ntoa(long n) {  | |
| - | + |     return (n >> 24 & 0xff) + "." + (n >> 16 & 0xff) + "." + (n >> 8 & 0xff) + "." + (n & 0xff);  | |
| - | + |   }  | |
| - | + |   public final static long aton(String a) {  | |
| - | + |     long n = 0;  | |
| - | + |     StringTokenizer st = new StringTokenizer(a, ".");  | |
| - | + |     try {  | |
| - | + |       while (st.hasMoreTokens()) {  | |
| - | + |         n |= n << 8 | (Integer.parseInt(st.nextToken()) & 0xff);  | |
| - | + |       }  | |
| - | + |     } catch (NumberFormatException e) {  | |
| - | + |       return 0;  | |
| - | + |     }  | |
| - | + |     return n;  | |
| - | + |   }  | |
| - | + |   private final void addToCmdList(HashMap<String, ArrayList<String>> cmds, String rtr, String c) {  | |
| - | + |     ArrayList<String> l = cmds.get(rtr);  | |
| - | + |     if (l == null) {  | |
| - | + |       l = new ArrayList<String>();  | |
| - | + |       cmds.put(rtr, l);  | |
| - | + |     }  | |
| - | + |     l.add(c);  | |
| - | + |   }  | |
}  | }  | ||
</source >  | </source >  | ||
| - | 12:  | + | --[[Участник:Blib|Blib]] 12:08, 8 июня 2008 (UTC)  | 
Версия 12:08, 8 июня 2008
этот тип шлюза смотрит к какому источнику привязан ип адрес клиента после чего идет на этот роутер и делает
ip route адрес клиента Null0
т.е. все пакеты клиента отправляются в /dev/null (если разрешен RPF то и входящие пакеты отправляются в null)
если адреса привязаны к индивидуальному интерфейсу то скрипт делает shutdown этого интерфейса
Настройка типа шлюза в бгбиллинге.
Клиент БГБиллинга -> Модули -> IPN модуль -> Типы шлюзов
Добавляем новый шлюз.
Название:  xxx
Комментарий: Универсальный шлюз Cisco
Конфигурация:
gate_manager.class=ru.dsi.bg.server.RouterGateWorker
настройка индивидуального шлюза
login=xxx password=xxx exclude.1=10.10.0.0/255.255.255.0 debug=1
login/password - логин на роутеры
exclude - исключает на всякий случай наши адреса что бы случайно не отключить самого себя
debug - 1- значит что ничего не делать а только писать в лог что бы было бы сделано
после этого
нужно скомпилировать класс сделать jar и положить в директорию lib на сервере
package ru.dsi.bg.server; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.StringTokenizer; import bitel.billing.server.ipn.GateWorker; import bitel.billing.server.ipn.UserStatus; import bitel.billing.server.util.DefaultServerSetup; import bitel.billing.server.util.SetupData; import expect4j.Expect4j; import expect4j.ExpectUtils; public class RouterGateWorker extends GateWorker { private static SetupData setup = new SetupData("data.data"); static final long maxSize = 64; @Override protected void doSync() { Long exclude[]; DefaultServerSetup gateSetup = new DefaultServerSetup(gate.getConfig(), "\r\n"); HashMap<String, ArrayList<String>> cmds = new HashMap<String, ArrayList<String>>(); String login = gateSetup.getStringValue("login", "root"); String pswd = gateSetup.getStringValue("password", "passwd"); int debug = gateSetup.getIntValue("debug", gate.getGateType().getConfigSetup().getIntValue("debug", 0)); int mid = gateSetup.getIntValue("mid", gate.getGateType().getConfigSetup().getIntValue("mid", -1)); ArrayList<Long> ex = new ArrayList<Long>(); for (Iterator it = gateSetup.getOrderedValues("exclude.").iterator(); it.hasNext();) { String s = (String) it.next(); s = s.trim(); StringTokenizer st = new StringTokenizer(s, "/"); if (st.countTokens() != 2) { log.error("Cant parse gate config: " + s); gateErrors.append("Ошибка конфига\n"); continue; } ex.add(aton(st.nextToken())); ex.add(aton(st.nextToken())); } exclude = ex.toArray(new Long[ex.size()]); Connection con = null; PreparedStatement ps = null; try { con = setup.getDBConnection(); for (Iterator<UserStatus> it = statusList.iterator(); it.hasNext();) { UserStatus us = it.next(); int cid = us.contractId; log.debug("CID:" + cid + " status:" + us.status); ps = con.prepareStatement("select * from ipn_user_range_" + mid + " where cid=? and " + " ( date1 is null or date1<=now() ) and ( date2 is null or date2>=now() )"); ps.setInt(1, cid); ResultSet rs = ps.executeQuery(); while (rs.next()) { int aid = rs.getInt("id"); long a1 = rs.getBigDecimal("addr1").longValue(); long a2 = rs.getBigDecimal("addr2").longValue(); assert a1 < a2; PreparedStatement psSrc = con .prepareStatement("select s.title,s.host_or_dir,i.number,i.title from ipn_user_source_" + mid + " us join source s on us.source_id=s.id left outer join ipn_iface_" + mid + " i on us.source_id=i.source_id and us.iface=i.number where aid=?"); psSrc.setInt(1, aid); ResultSet rs2 = psSrc.executeQuery(); while (rs2.next()) { int n = rs2.getInt(3); String rtr = rs2.getString(2); if (n < 0 && a1!=0 ) { // ANY и addr1==0.0.0.0 addcmd: { // проверяем размер if (Math.abs(a2 - a1) > maxSize) { log.error("Exceed max network size, " + ntoa(a1) + "-" + ntoa(a2) + " cid:" + cid); gateErrors.append("Превышен максимальный размер сети " + ntoa(a1) + "-" + ntoa(a2) + "\n"); break addcmd; } // проверяем попадают ли адреса в защищенный // диапазон for (int i = 0; i < exclude.length; i += 2) if ((exclude[i] == (a1 & exclude[i + 1])) || (exclude[i] == (a2 & exclude[i + 1]))) { log.error("Network excluded, " + ntoa(a1) + "-" + ntoa(a2) + " cid:" + cid); gateErrors.append("Сеть защищена конфигом " + ntoa(a1) + "-" + ntoa(a2) + "\n"); break addcmd; } // все хорошо for (long i = a1; i <= a2; i++) addToCmdList(cmds, rtr, (us.status == 0 ? "no " : "") + "ip route " + ntoa(i) + " 255.255.255.255 null0 tag 1901"); } } else { // определенный интерфейс и addr1 == 0.0.0.0 (точно VPN) addToCmdList(cmds, rtr, "interface " + rs2.getString(4)); addToCmdList(cmds, rtr, (us.status == 0 ? "no " : "") + "shutdown"); } } } } } catch (SQLException e) { log.error(e.getLocalizedMessage(), e); gateErrors.append("Ошибка запроса в БД " + e.getLocalizedMessage() + "\n"); } finally { if (ps != null) try { ps.close(); } catch (SQLException e) { log.error(e.getLocalizedMessage(), e); gateErrors.append("Ошибка запроса в БД " + e.getLocalizedMessage() + "\n"); } } if (debug > 0) { for (String host : cmds.keySet()) { log.debug("Debug mode telnet " + login + "@" + host); for (String c : cmds.get(host)) log.debug(host+" "+c); //gateErrors.append("режим отладки\n"); } } else for (String host : cmds.keySet()) { try { log.debug("telnet " + login + "@" + host); Expect4j exp = ExpectUtils.telnet(host, 23); if (exp.expect("ogin:") < 0) throw new RuntimeException("failed match login prompt"); exp.send(login + "\n"); if (exp.expect("assword:") < 0) throw new RuntimeException("failed match password prompt"); exp.send(pswd + "\n"); if (exp.expect("#") < 0) throw new RuntimeException("failed match prompt 0"); exp.send("conf term\n"); for (String c : cmds.get(host)) { log.debug(c); if (exp.expect("#") < 0) throw new RuntimeException("failed match prompt 1"); exp.send(c + "\n"); } if (exp.expect("#") < 0) throw new RuntimeException("failed match prompt 2"); exp.send("end\n"); if (exp.expect("#") < 0) throw new RuntimeException("failed match prompt 3"); exp.send("exit\n"); exp.close(); } catch (Exception e) { log.error("telnet " + login + "@" + host); for (String c : cmds.get(host)) log.error(c); log.error(e.getLocalizedMessage(), e); gateErrors.append("Ошибка " + e.getLocalizedMessage() + "\n"); } } } public final static String ntoa(long n) { return (n >> 24 & 0xff) + "." + (n >> 16 & 0xff) + "." + (n >> 8 & 0xff) + "." + (n & 0xff); } public final static long aton(String a) { long n = 0; StringTokenizer st = new StringTokenizer(a, "."); try { while (st.hasMoreTokens()) { n |= n << 8 | (Integer.parseInt(st.nextToken()) & 0xff); } } catch (NumberFormatException e) { return 0; } return n; } private final void addToCmdList(HashMap<String, ArrayList<String>> cmds, String rtr, String c) { ArrayList<String> l = cmds.get(rtr); if (l == null) { l = new ArrayList<String>(); cmds.put(rtr, l); } l.add(c); } }
--Blib 12:08, 8 июня 2008 (UTC)
