Реалиазация шлюза на 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)

Личные инструменты