Реалиазация шлюза на Cisco
Материал из BiTel WiKi
этот тип шлюза смотрит к какому источнику привязан ип адрес клиента, после чего телнетом идет на этот роутер и делает
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); } }
скрипту нужны 2 внешние библиотеки expect4j и common-net
--Blib 12:08, 8 июня 2008 (UTC)