Автоматическое сохранение конфигурации маршрутизаторов cisco

В данной заметке рассказывается о том, как настроить автоматическое сохранение конфигурации сетевого оборудования, работающего под управлением Cisco IOS и отслеживание изменений с помощью RCS.

Пару слов, зачем это нужно. Конфигурация маршрутизатора относится к числу критически важных данных, поэтому обязательно должно осуществятся её регулярное резервное копирование. Тогда при выходе из строя марщрутизатора можно будет быстро восстановить работу, заменив его и скопировав сохраненный конфиг. Причем сохранять нужно не только последнюю версию, но и несколько предыдущих - если из-за ошибки при настройке возникнут проблемы, это позволит легко вернутся к предыдущей версии. Изменения в конфигурации высылаются администратору по почте. Это особенно удобно, когда одним маршрутизатором управляет несколько человек, поскольку позволяет быть в курсе изменений, сделанных другими.

Для решения этой задачи существует как минимум три программы (помимо скриптов, написанных мной) - ciscoconf (порт FreeBSD /usr/ports/net-mgmt/ciscoconf) и rancid. Первая (ciscoconf) копирует конфигурации конфигурацию по RSH и сохраняет в RCS. Её преимущество - она это может делать сразу после завершения конфигурации отслеживая появление в логе строчки содержащей %SYS-5-CONFIG_I. Вторая (rancid) более универсальная и позволяет работать не только с оборудованием Cisco. Для своей работы она требует сохранения в конфиге пароля на доступ по telnet и пароль enable. Я считаю, что это делать нежелательно из соображений безопасности (но это субъективное мнение, snmp не безопасноее). Уже после написания этого скрипта я наткнулся еще на один проект - Pancho. Там так же конфиги копируются используюя snmp+tftp.

Если вам не хочется читать все, что написано ниже то рекомендую поставить ciscoconf - её настроить проще, чем то, что описано далее.

Тем не менее я решил сделать подобную систему самому, поскольку мне не хотелось только ради ciscoconf открывать на маршрутизаторах rsh. Сохранять в открытом виде пароли для доступа к Циске я тем более не стал. Кроме просмотра конфигурации через telnet или по rsh есть еще один способ - дать по snmp команду скопировать конфигурацию на tftp-сервер. Им я и воспользовался. Еще одна причина написания этих скриптов - я думал, что при копировании конфига с помощью snmp+tftp процессор маршрутизатора нагружается меньше, чем при использовании RSH, но проведенные тесты показали, что в обоих случаях нагрузка на процессор примерно одинаковая (загрузка процессора на 3550 при копировании конфига 9,3K 30 раз в минуту в среднем 28%). В двух словах как работает предлагаемся схема: циске по snmp дается команда скопировать конфиг по tftp. Далее этот файл помещается в RCS-архив, а diff высылается администратору. Скрипт написан на perl, с использованием модуля Cisco-CopyConfig и запускается из крона.

Настройка tftp-сервера

Здесь и далее рассматривается настройка на примере FreeBSD. Если у вас еще не настроен tftp-сервер то сейчас самое время это сделать. Сначала добавим в систему пользователя netmgr под которым будет работать наша система (запускать под рутом софт, для работы которого не нужны права рута плохая идея). Добавьте в /etc/inetd.conf строчку
tftp dgram udp wait root /usr/libexec/tftpd tftpd -s /var/tftproot -u netmgr -l
(на всякий случай напомню, что после изменения этого файла нужно перезапустить inetd, а если до этого он не был запущен, то добавить в /etc/rc.conf строчку inetd_enable="YES" и запустить его). Далее нужно обязательно ограничить доступ к tftp-серверу только для адресов используемых вашими маршрутизаторами. Ни в коем случае нельзя открывать открытым доступ к tftp для всех т. к. если злоумышленник получит ваш конфиг он легко сможет восстановить все пароли закодированые с помощью service password-encryption (он предназнаен только для того, чтобы скрыть в конфиге пароли от случайного подглядывания). Для этого в файле /etc/hosts.allow прописываем адреса наших марщрутизаторов или подсети в которых они находятся (если доступ к этим подсетям полностью контролируются).
Например:
tftpd: 192.168.1.64/255.255.255.248 : allow
tftpd: 192.168.2.0/255.255.255.240 : allow
tftpd: ALL : deny
Не забывайте, что эти строчки должны быть расположены выше строчки ALL : ALL : allow которая по умолчанию стоит в начале /etc/hosts.allow.

Далее создаем каталог /var/tftproot и в нем подкаталог /var/tftproot/config для хранения конфигов. Владельцем папки tftproot делаем netmgr и ставим права 700 чтобы ограничить доступ к конфигам, который в числе прочего содержат пароли. tftp-сервер дает возможность записывать только в ранее созданный файл, в который имеет доступ на запись пользователь, под которым запускается tftpd:
touch /var/tftproot/config/router1 touch /var/tftproot/config/router2 chown netmgr /var/tftproot/config/*

Теперь заходим на циску и пробуем скопировать конфиг вручную (192.168.1.1 это адрес нашего сервера, на котором поднят tftp):


router1#
router1#copy running-config tftp://192.168.1.1/config/router1
Address or name of remote host [192.168.1.1]?
Destination filename [config/router1]?
!!!
10230 bytes copied in 0.676 secs (15133 bytes/sec)
router1#
Если копирование прошло успешно, то можно переходить к следующему шагу. Если копирование не удалось то можно проверить:

Настройка snmp

Настроим доступ на маршрутизатор с сервера по snmp. Создаем ACL которыми будет защищен доступ к snmp на запись и ACL для ограничения серверов, на которые можно копировать конфиг по tftp. В данном случае можно вместо двух сделать один, но в общем случае они могут и различаться:


access-list 10 remark -- hosts permitted to write snmp MIBs on the router
access-list 10 permit 192.168.1.1
access-list 10 deny   any log
access-list 11 remark -- tftp servers to/from which config download/upload is permitted
access-list 11 permit 192.168.1.1
access-list 11 deny   any log
Указываем snmp-community (которое играет роль пароля) и ACL для доступа на запись:

snmp-server community E9bJFckD RW 10
Указываем куда можно копировать конфиг по tftp:

snmp-server tftp-server-list 11

Установка модуля Cisco-CopyConfig

Для работы этого модуля необходим модуль Net::SNMP который можно установить из портов. Самого CopyConfig в портах нету, поэтому его нужно будет скачать с CPAN и установить вручную.

Для тестирования работы модуля и ранее сделанных настроек напишем простейший скрипт:

#!/usr/bin/perl -w

use strict;
use Cisco::CopyConfig ();

my $tftp_ip    = '192.168.1.1';
my $tftp_file  = 'config/router1';
my $cisco_ip   = '192.168.2.1';
my $comm_s     = 'E9bJFckD';
my $config     = Cisco::CopyConfig->new(
                     Host => $cisco_ip,
                     Comm => $comm_s
        );
print "$config->{err}\n" unless $config->copy($tftp_ip, $tftp_file);
Конфиг должен скопироваться в /var/tftproot/config/router1.

Скрипт для копирования и помещения конфигов в RCS

fetchconf.pl:

#!/usr/bin/perl

use strict;
use warnings;
use Cisco::CopyConfig ();

#####################################################

# ip адрес tftp-сервера на который заливаются конфиги
# на этой же машине и должен запускаться скрипт
my $tftp_host = '192.168.1.1';

# директория на tftp-сервере куда кладутся конфиги
my $dir = 'config';

# директория где лежат RCS-файлы
my $home = '/home/netmgr/ciscocong';

# snmp RW community для кошек
my %community = (
        '192.168.2.1' => 'E9bJFckD',
        '192.168.2.2' => 'J0uSsO6Yt'
        );

# имена хостов для кошек, на основе этого именуются файлы
my %hosts = (
        '192.168.2.1' => 'router1',
        '192.168.2.2' => 'router2'
        );

# e-mail на который будут высылаться изменения
my $to = 'noc@localhost';

my $path = '/usr/bin';

#####################################################

my $message = "";

foreach my $ip (keys %community ){
  my $config     = Cisco::CopyConfig->new (
    Host => $ip,
    Comm => $community{$ip}
  );

  my $name = $hosts{$ip};

  # если конфигурационного файла в tftproot еще нет, то создаем его
  if ( ! -r "/var/tftproot/$dir/$name" ) {
    system "$path/touch /var/tftproot/$dir/$name";
  }

  # даем команду скопировать конфиг с циски по tftp
  warn "Error while copy conf from $ip to tftp://$tftp_host/$dir/$name: $config->{err}\n"
                unless $config->copy($tftp_host, "$dir/$name");

  # Создаем и инициализируем  RCS файл, если его еще нет
  if ( ! -r "$home/$name,v" ) {
    system "$path/rcs -q -t-$name -i $home/$name,v /var/tftproot/$dir/$name";
  }

  # удаляем из кофига ntp clock-period, потому что это значение часто меняется
  system "$path/fgrep -v 'ntp clock-period' /var/tftproot/$dir/$name > $home/$name";

  # RCS diff
  my $msg = `$path/rcsdiff -qu $home/$name`;
  if ($msg ne '') {
    $message .= "===  $name =============================================================\n";
    $message .= "$msg\n\n";
  }
  # store config in RCS
  system "$path/ci -q -m'-' -l $home/$name";
}

# Отправляем изменения по почте
my $now = localtime;

open (MAIL, "| $path/mail -E -s \"cisco config diff ($now)\" $to") || die "$!\n";
print MAIL $message;
close MAIL;

Т. к. скрипт содержит RW snmp-community, назначаем ему права 700, чтоб другие пользователи не могли его прочитать. Все настройки прописываются в начале скрипта. При добавлении новой циски достаточно прописать её в хэшах %community и %hosts. Для проверки работы запускаем скрипт, что ни будь меняем на циске и запускаем снова. Должно прийти письмо. Скрипт нужно прописать в cron пользователя netmgr. Для небольшой сети, с редкими изменениями достаточно запускать раз в несколько часов:

# fetch config from cisco, store in RCS and mail diff
3       */3     *       *       *       /home/netmgr/fetchconf.pl

Пример письма, высылаемого скриптом:

===  sr1 =============================================================
--- /home/netmgr/ciscocong/sr1  2004/09/02 11:03:03     1.33
+++ /home/netmgr/ciscocong/sr1  2004/09/10 14:03:03
@@ -1,7 +1,7 @@

 !
-! Last configuration change at 14:48:07 MSD Thu Sep 2 2004 by ivanov
-! NVRAM config last updated at 10:57:31 MSD Wed Sep 1 2004 by ivanov
+! Last configuration change at 16:13:56 MSD Fri Sep 10 2004 by petrov
+! NVRAM config last updated at 16:18:32 MSD Fri Sep 10 2004 by petrov
 !
 version 12.1
 service nagle
@@ -98,9 +98,15 @@
  spanning-tree portfast
 !
 interface FastEthernet0/6
- switchport access vlan 1001
+ description -- server 75.02
+ switchport access vlan 1000
  switchport mode access
+ switchport nonegotiate
+ switchport port-security
+ switchport port-security violation restrict
  no cdp enable
+ spanning-tree portfast
+ spanning-tree bpdufilter enable
 !
 interface FastEthernet0/7
  switchport access vlan 1001

Небольшое замечание по безопасности - защите сервера на котором работает этот скрипт нужно уделить повышенное внимание, поскольку если злоумышленник получит полный доступ к этому хосту, то он сможет по tftp скопировать на маршрутизаторы измененный конфиг и получит таким образом полный конторль над всеми маршрутизаторами. Желательно размещать подобную систему на сервере, который не имеет открытых во внешний мир сервисов (web, mail, ftp и т. д.)


Сcылки по теме:
How To Copy Configurations To and From Cisco Devices Using SNMP
Getting RANCID on FreeBSD
Южанинов Антон <citrin@citrin.ru>, октябрь 2004 г.