Реалиазация шлюза на Cisco

Материал из BiTel WiKi

(Различия между версиями)
Перейти к: навигация, поиск
Blib (Обсуждение | вклад)
(Новая: этот тип шлюза смотрит к какому источнику привязан ип адрес клиента после чего идет на этот роутер и д...)
Следующая правка →

Версия 12:05, 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);
	}
}

12:05, 8 июня 2008 (UTC)~

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