понедельник, 26 сентября 2011 г.

Костылинг dhcp, или как заставить работать UTM5 c isc-dhcp

В данной статье я расскажу как все же заставить работать isc-dhcpd с биллинговой системой UTM5 от компании NetUP (Российская Федерация).

Данный костыль не рассчитывает быть полноценным, но его можно использовать на первое время, если у вас не особо то и сегментированная сеть. Если же вы используете в своей сети opt82 (выдача ip-адреса по порту коммутатора), то придется писать немного другой скриптик, но об этом в другой раз

Приступим.
На сервере dhcp должны быть установлены следующие программы и модули:
1. isc-dhcp30-relay-3.0.7
2. isc-dhcp30-server-3.0.7_5
3. p5-DBD-mysql50-4.013
4. p5-DBI-1.60.9
5. p5-Storable-2.21
6. perl-5.10.1 

Далее создаем каталог dhcp в /usr/local/etc/. Мне было удобно именно в этой папке, там же лежит и dhcpd.conf.

В /usr/local/etc/dhcp/ кладем вот такой файл на перле:
#!/usr/bin/perl
use DBI;
use DBD::mysql;
#use lib '/cktv/perl';
#use cktv::logger;

# Инициализация
#loginfo "Обновление DHCPD";
$dbh = DBI->connect("DBI:mysql:UTM5;192.168.1.1", "login", "password", {'RaiseError' => 1}) or die crit msg "Can't connect to DB!";

open F, ">", "/tmp/dhcpd.hosts.new";

# Получаем данные (192.168.xx.xx)
my $items = $dbh->selectall_arrayref( "SELECT inet_ntoa(ip & 0xFFFFFFFF) as ip, ip_groups.mac, accounts.is_blocked FROM ip_groups,iptraffic_service_links, service_links, users, accounts WHERE ip_groups.mac!='' AND accounts.id=users.basic_account AND service_links.user_id=users.id AND service_links.is_deleted='0' AND ip_groups.is_deleted='0' AND iptraffic_service_links.ip_group_id=ip_groups.ip_group_id AND service_links.id=iptraffic_service_links.id GROUP BY ip_groups.ip ORDER BY ip_groups.ip" );

# Таблица для поиска дублей
my ( %MAC, %IP ) = ();

for my $item ( @$items ) {
    my ( $ip, $mac ) = @$item;

    $mac =~ s/^\s+//;
    $mac =~ s/\s+$//;
    $mac = uc $mac;

    # Проверяем мак
    unless ( $mac ) {
        # DHCP не нужен
        next;
    } elsif ( $mac =~ /^[0-9A-F]{2}(?::[0-9A-F]{2}){5}$/ ) {
        # Мак правильный
    } elsif ( $mac =~ /([0-9A-F]{2})([0-9A-F]{2})\.?
                ([0-9A-F]{2})([0-9A-F]{2})\.?
                ([0-9A-F]{2})([0-9A-F]{2})/x ) {
        # Цисковский или просто числа
        $mac = "$1:$2:$3:$4:$5:$6";
        #crit msg "Fixed: $ip $mac";
         print "Fixed: $ip $mac";
    } else {
        #msg "Wrong: $ip $mac";
        print "Wrong: $ip $mac";
        next;
    }

    # Проверка на дубликаты
    if ( $MAC{$mac} ) {
        #crit msg "Duplicate MAC: $ip $mac";
 #       print 12;
        print "Duplicate MAC: $ip $mac";
        next;
    }

    if ( $IP{$ip} ) {
        #crit msg "Duplicate IP: $ip $mac";
        print "Duplicate IP: $ip $mac";
        next;
    }

    $IP{$ip} = 1;
    $MAC{$mac} = 1;

    # Сохраняем в конфиг
    $ip =~ /^(\d+\.\d+)\.(\d+)\.(\d+)$/;
        my $opt = '';

#    if ( $ip =~ /^123\.123\.123\./ ) {
#        # Внешний адрес нашего C-класса
#        $opt .= sprintf "option host-name pc_%03s_%03s; ", $2, $3;
#    }

     if ( $ip =~ /^123\.123\.123\./ ) {
        # Внешний адрес нашего C-класса
        $opt .= sprintf "option host-name host-%0s-%0s.broadband.domain.ru; ", $2, $3;
     }

#    printf F "host pc_%03s_%03s { hardware ethernet %s; fixed-address %s; option routers %s; }\n",
#        $2, $3, $mac, $ip, "$1.$2.1",$opt;

#    printf F "host $ip { hardware ethernet %s; fixed-address %s; option routers %s; }\n",
#        $mac, $ip, "$1.$2.1",$opt;

printf F "host $ip { hardware ethernet %s; fixed-address %s; }\n",
        $mac, $ip;
}

# Отключаемся
$dbh->disconnect;
close F;

Далее создаем в этой же папке /usr/local/etc/dhcp/ файл dhcp.sh следующего содержания:
#!/bin/sh

/usr/local/etc/dhcp/dhcp.pl

diff /etc/dhcpd.hosts /tmp/dhcpd.hosts.new > /dev/null >> /var/log/dhcpd_updater ||
(/usr/local/sbin/dhcpd -t -cf /usr/local/etc/dhcpd.conf 2>&1 &&
cp /tmp/dhcpd.hosts.new /etc/dhcpd.hosts &&
/usr/local/etc/rc.d/isc-dhcpd forcerestart 2>&1 &&
echo Reboot: \`date\` >> /var/log/dhcpd_updater); 

И ставим этот файл на запуск в крон. Как вашей душе угодно я выставил каждые 10 минут.

Все данные пишутся в файл /etc/dhcpd.hosts в виде:
host 192.168.10.2 { hardware ethernet 00:00:00:00:00:00; fixed-address 192.168.10.2; }

Дальше нам остается добавить в /usr/local/etc/dhcpd.conf в конец конфига строчку: include "/etc/dhcpd.hosts".

В общем то и все

Конфиг dhcpd.conf:
# /usr/local/etc/dhcpd.conf
#
# Конфигурация для isc-dhcp сервера
#
# Глобальные параметры
#========================================================
# Доменый суффикс, который будет присвоен клиентам
option domain-name "domain.ru";

# Список DNS серверов, которые должен использовать клиент
option domain-name-servers 192.168.1.1;
server-name "domain";

# На какое время выдавать клиентам настройки (в секундах) 86400сек=1день
default-lease-time 86400;

# На какое максимальное время выдавать клиентам настройки (в секундах)
max-lease-time 172800;

# Минимально на сколько выдается IP-адрес
min-lease-time 86400;
#========================================================

#Параметр определяет, будет ли DHCP-сервер пытаться обновить DNS при выдаче конфигурационной информации
ddns-update-style none;
#ddns-update-style interim;

# Данный параметр говорит, что мы будем обновлять DNS зону (т.к. мы уже выбрали, что не будем ее обновлять, то комментируем эту строчку)
#ddns-update-style ad-hoc;

# Включаем IP-Forwarding
option ip-forwarding on;
#ddns-fwd-name ns.domain.ru;

# Объявляем, что наш DHCP-сервер самый авторитетный (т.е. главный в сети)
authoritative;
# Логи которые отправляет DHCP-сервер
log-facility local7;
ignore client-updates;
deny bootp;
deny client-updates;
deny duplicates;
ignore declines;

# Локальные параметры сети (настройка сети)
#==========================================
shared-network domain {

subnet 192.168.10.0 netmask 255.255.255.0 { # Сеть которую объявляем и маска данной сети
        option subnet-mask 255.255.255.0;
        option routers 192.168.10.1;
        option broadcast-address 192.168.10.255;
        option domain-name-servers 192.168.1.1;
pool {
        range 192.168.10.2 192.168.10.254;
        deny unknown-clients; # Запретить выдачу IP-адресов не известным клиентам
#       deny client-updates;
#       deny bootp;
#       deny duplicates;
#       ignore declines;
}
option netbios-node-type 8;
option ntp-servers 192.168.1.1; # Сервер синхронизации времени

default-lease-time 86400; # Поумолчанию на сколько выдается IP-адрес
max-lease-time 172800; # Максимально на сколько выдается IP-адрес, после чего мы его сами забираем
}
subnet 192.168.11.0 netmask 255.255.255.0 { # Сеть которую объявляем и маска данной сети
        option subnet-mask 255.255.255.0;
        option routers 192.168.11.1;
        option broadcast-address 192.168.11.255;
        option domain-name-servers 192.168.1.1;
pool {
        range 192.168.11.2 192.168.11.254;
        deny unknown-clients; # Запретить выдачу IP-адресов не известным клиентам
#       deny client-updates;
#       not authoritative;
#       deny bootp;
#       deny duplicates;
#       ignore declines;
}
option netbios-node-type 8;
option ntp-servers 192.168.1.1; # Сервер синхронизации времени

default-lease-time 86400; # Поумолчанию на сколько выдается IP-адрес
max-lease-time 172800; # Максимально на сколько выдается IP-адрес, после чего мы его сами забираем
}
include "/etc/dhcpd.hosts";


Естественно все ip-адреса и mac-адреса вымышленные Удачи!

Еще добавлю, для защиты от dhcp-snooping, на порту коммутатора (у меня cisco) нужно указать следующие опции:
 switchport access vlan xx #VLAN в котором сидит dhcp
 switchport mode access
 no cdp enable
 ip dhcp snooping limit rate 500 #Лимит запросов
 ip dhcp snooping trust #Объявляем, что наш dhcp самый главный в сети (так называемая защита от подмены запросов) 


понедельник, 19 сентября 2011 г.

Для чего я создал блог?

Хотелось бы отметить, что все мы люди и всем свойственно забывать некоторые вещи в своей жизни. Так устроен наш разум, так устроен наш мозг. Блог для меня - это прежде всего записная книжка, как для себя так и для рабочих моментов. Ведь не всегда я помню как настроить те или иные моменты.