
Настройка Oxidized
Из-за большого количества сетевого оборудования и отсутствия достаточного времени не получается бэкапить всё оборудование.Но надеюсь данная статья поможет вам автоматизировать рутинную работу. Все изменения конфигураций будут версионироваться, и бэкапиться, вы всегда сможете восстановить прошивку на необходимое состояние.
Выделяем ПК или VM, устанавливаем Linux, я предпочитаю Debian (сейчас актуальная версия 12). Устанавливаем Docker и Docker-Compose по оф. инструкции Добавление репозиториев
apt update apt upgrade apt get install mc ncdu htop sudo curl sudo apt -y install ca-certificates curl gnupg lsb-release apt-transport-https gnupg2 software-properties-common curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo “deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable” | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Установка Docker
sudo apt update sudo apt -y install docker-ce docker-ce-cli containerd.io sudo systemctl start docker sudo systemctl enable docker
Установка Docker-Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.28.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose echo PWD=${PWD} >> .env

Мне понравилась сборка Oxidized от Сергея Ершова
https://github.com/ErshovSergey/oxidized_docker-compose
mkdir /docker git clone https://github.com/ErshovSergey/oxidized\\_docker-compose.git cd oxidized_docker-compose docker-compose up
Внутри Docker-Compose уже есть Nginx в качестве Reverse Proxy.
Настройка
Скопировать файлы
cp .env-default .env cp router.db.csv-default router.db.csv
nano .env
Меняем имя нашего сервера и ip адрес

т.к. сервер бэкапов будет доступен только внутри локальной сети, указываем A запись внутри домена, через оснастку DNS на контроллере домена

Вернёмся к нашему Linux’у, локально на ПК (не в докере),переходим сd /path/to/data/folder/oxidized-docker редактируем наш router.db.csv
nano router.db.csv
Рассмотрим пример
Возможные модели model_map[routeros|ios|junos|procurve|comware|datacom|vrp|airos|edgeswitch] строка для конфига name:ipaddr:model:username:password:enable_password:group_devices:ssh_port:ssh_proxy:ssh_proxy_port:ssh_key:ssh_no_exec ssh_no_exec[true|false] прямой доступ name_host:ip_addr_host:routeros:ssh_user:ssh_user_pass:enable_pass:group_1:ssh_port пример name-router:11.22.33.44:routeros:ssh_read:PASS-ssh_read:empty:router:22 #Routers MT_CCR1009_M2_Servers:10.10.0.1:routeros:oxidized:pass123:empty:router:4422
MT_CCR1009_M2_Servers - наименование 10.10.0.1 - ip адрес routeros - модель oxidized - логин pass123 - пароль empty - если не требуется привилегированный режим то оставляем так, но например у Cisco и Eltex это будет второй пароль router - группа 4422 - порт для SSH

В файле config можно указать единый логин и пароль для подключения к определённой группе устройств, но мы не будем использовать.
Создание новой модели оборудования
Создаём папку для моделей
cd /path/to/data/folder/oxidized-docker/ mkdir model
Создаём файл для нашей модели, в моём случае это будет Сisco Catalyst
nano my_ios.rb
Настройки будут приведены в спойлере ниже
class My_IOS < Oxidized::Model prompt /^([\w.@()-]+[#>]\s?)$/ comment '! ' cmd :all do |cfg| # cfg.gsub! /\cH+\s{8}/, ‘’ # example how to handle pager # cfg.gsub! /\cH+/, ‘’ # example how to handle pager # get rid of errors for commands that don’t work on some devices cfg.gsub! /^% Invalid input detected at ‘^’ marker./, ‘’ cfg.cut_both end cmd :secret do |cfg| cfg.gsub! /^(snmp-server community)./, ‘\1 ’ cfg.gsub! /^(snmp-server host \S+( vrf \S+)?( informs?)?( version (1|2c|3 (noauth|auth|priv)))?)\s+\S+((\s+\S))\s/, ‘\1 \7’ cfg.gsub! /^(username .+ (password|secret) \d) .+/, ‘\1 ’ cfg.gsub! /^(enable (password|secret)( level \d+)? \d) .+/, ‘\1 ’ cfg.gsub! /^(\s+(?:password|secret)) (?:\d )?\S+/, ‘\1 ’ cfg.gsub! /^(.wpa-psk ascii \d) (\S+)/, ‘\1 ’ cfg.gsub! /^(.key 7) (\d.+)/, ‘\1 ’ cfg.gsub! /^(tacacs-server (.+ )?key) .+/, ‘\1 ’ cfg.gsub! /^(crypto isakmp key) (\S+) (.)/, ‘\1 \3’ cfg.gsub! /^(\s+ip ospf message-digest-key \d+ md5) .+/, ‘\1 ’ cfg.gsub! /^(\s+ip ospf authentication-key) .+/, ‘\1 ’ cfg.gsub! /^(\s+neighbor \S+ password) .+/, ‘\1 ’ cfg.gsub! /^(\s+vrrp \d+ authentication text) .+/, ‘\1 ’ cfg.gsub! /^(\s+standby \d+ authentication) .{1,8}/, ‘\1 \2’ cfg.gsub! /^(\s+key-string) .+/, ‘\1 ’ cfg.gsub! /^((tacacs|radius) server [^\n]+\n(\s+[^\n]+\n)\s+key) [^\n]+$/m, ‘\1 ’ cfg.gsub! /^(\s+ppp (chap|pap) password \d) .+/, ‘\1 ’ cfg end cmd ‘show version’ do |cfg| comments = [] comments << cfg.lines.first lines = cfg.lines lines.each_with_index do |line, i| slave = ‘’ slaveslot = ‘’ if line =~ /^Slave in slot (\d+) is running/ slave = " Slave:" slaveslot = ", slot #{Regexp.last_match(1)}" end comments << “Image:#{slave} Compiled: #{Regexp.last_match(1)}” if line =~ /^Compiled (.*)$/ comments << "Image:#{slave} Software: #{Regexp.last_match(1)}, #{Regexp.last_match(2)}" if line =~ /^(?:Cisco )?IOS .* Software,? \(([A-Za-z0-9_-]*)\), .*Version\s+(.*)$/ comments << "ROM Bootstrap: #{Regexp.last_match(3)}" if line =~ /^ROM: (IOS \S+ )?(System )?Bootstrap.*(Version.*)$/ comments << "BOOTFLASH: #{Regexp.last_match(1)}" if line =~ /^BOOTFLASH: .*(Version.*)$/ comments << "Memory: nvram #{Regexp.last_match(1)}" if line =~ /^(\d+[kK]) bytes of (non-volatile|NVRAM)/ comments << "Memory: flash #{Regexp.last_match(1)}" if line =~ /^(\d+[kK]) bytes of (flash memory|flash internal|processor board System flash|ATA CompactFlash)/i comments << "Memory: pcmcia #{Regexp.last_match(2)} #{Regexp.last_match(3)}#{Regexp.last_match(4)} #{Regexp.last_match(1)}" if line =~ /^(\d+[kK]) bytes of (Flash|ATA)?.*PCMCIA .*(slot|disk) ?(\d)/i if line =~ /(\S+(?:\sseries)?)\s+(?:\((\S+)\)\s+processor|\(revision[^)]+\)).*\s+with (\S+k) bytes/i sproc = Regexp.last_match(1) cpu = Regexp.last_match(2) mem = Regexp.last_match(3) cpuxtra = '' comments << "Chassis type:#{slave} #{sproc}" comments << "Memory:#{slave} main #{mem}" # check the next two lines for more CPU info comments << "Processor ID: #{Regexp.last_match(1)}" if cfg.lines[i + 1] =~ /processor board id (\S+)/i if cfg.lines[i + 2] =~ /(cpu at |processor: |#{cpu} processor,)/i # change implementation to impl and prepend comma cpuxtra = cfg.lines[i + 2].gsub(/implementation/, 'impl').gsub(/^/, ', ').chomp end comments << "CPU:#{slave} #{cpu}#{cpuxtra}#{slaveslot}" end comments << "Image: #{Regexp.last_match(1)}" if line =~ /^System image file is "([^"]*)"$/ end comments << "\n" comment comments.join "\n" end cmd ‘show vtp status’ do |cfg| cfg.gsub! /^$\n/, ‘’ cfg.gsub! /Configuration last modified by.*\n/, ‘’ cfg.gsub! /^/, 'VTP: ’ unless cfg.empty? comment “#{cfg}\n” end cmd ‘show inventory’ do |cfg| comment cfg end cmd ‘show vlan brief’ do |cfg| cfg.gsub! /^$\n/, ‘’ comment cfg end cmd ‘show running-config view full’ do |cfg| cfg = cfg.each_line.to_a[3…-1] cfg = cfg.reject { |line| line.match /^ntp clock-period / }.join cfg = cfg.each_line.reject { |line| line.match /^! (Last|No) configuration change (at|since)./ unless line =~ /\d+\sby\s\S+$/ }.join cfg.gsub! /^Current configuration : [^\n]\n/, ‘’ cfg.gsub! /^ tunnel mpls traffic-eng bandwidth[^\n]\n( (?: [^\n]\n)* tunnel mpls traffic-eng auto-bw)/mx, ‘\1’ cfg end cfg :telnet do username /^Username:/i password /^Password:/i end cfg :telnet, :ssh do # preferred way to handle additional passwords post_login do if vars(:enable) == true cmd “enable” elsif vars(:enable) cmd “enable”, /^[pP]assword:/ cmd vars(:enable) end end post_login ‘terminal length 0’ post_login ‘terminal width 0’ pre_logout ‘exit’ end end
После создания модели редактируем наш config по аналогии с рисунком ниже

Далее в router.db.csv добавляем запись
#Cisco 2960 Cisco2960_M2_Archive:10.10.0.10:my_ios:oxidized:P@ssw0rd-vDomene:empty:cisco_CLI:22
oxidized- это доменный пользователь
SSO (Прошивка и настройка Cisco Catalyst коммутаторов с привязкой к RADIUS NPS) SSO. Прошивка и настройка Extreme Networks x440, x450 коммутаторов с привязкой к RADIUS NPS
Изучив мои статьи, вам потребуется создать пользователя в домене с добавлением в группу доступа Switch-Read.
Проверка работоспособности Заходим в вебку (логин admin1, пароль admin) нажимаем reload и потом кнопку refrash напротив коммутатора Cisco2960_M2_Archive, нажав на “облачко” увидим загрузившуюся прошивку.

Все модели которые знает oxidized описаны на официальном сайте
Но вы поняли, что можно создавать и свои модели! ;)
P.S. Если не работает подключение по SSH, то добавляем в файле /etc/ssh/ssh_config
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc KexAlgorithms +diffie-hellman-group1-sha1,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1
Если в Вэб части не появляется новая модель,то переходим в папку /docker и выполняем
docker-compose restart
Далее прилагаю настройки моделей для Extreme, D-link, Cisco Nexus, Zyxel
Extreme Networks
nano /path/to/data/folder/oxidized-docker/model/my_xos.rb
class My_XOS < Oxidized::Model # Extreme Networks XOS prompt /^\s?*?\s?[-\w]+\s?[-\w.~]+(:\d+)? [#>] $/ comment '# ’ cmd :all do |cfg| # xos inserts leading \r characters and other trailing white space. # this deletes extraneous \r and trailing white space. cfg.each_line.to_a[1…-2].map { |line| line.delete(“\r”).rstrip }.join(“\n”) + “\n” end cmd ‘show tech-support’ do |cfg| comment cfg end cfg :telnet do username /^login:/ password /^\r*password:/ end cfg :telnet, :ssh do post_login do data = cmd ‘disable clipaging session’ match = data.match /^disable clipaging session\n\r?*?\s?[-\w]+\s?[-\w.~]+(:\d+)? [#>] $/m next if match cmd 'disable clipaging' end pre_logout do send "exit\n" send "n\n" end end end
D-link DES3200-26 rev.A1
nano /path/to/data/folder/oxidized-docker/model/my_dlink_3200_26_a1.rb
class My_Dlink_3200_26_A1 < Oxidized::Model # D-LINK Switches Dlink_DES-3200-26_A1 prompt /^(\r*[\w\s.@()/:-]+[#>]\s?)$/ comment '# ’ cmd :secret do |cfg| cfg.gsub! /^(create snmp community) \S+/, ‘\1 ’ cfg.gsub! /^(create snmp group) \S+/, ‘\1 ’ cfg end cmd :all do |cfg| cfg.each_line.to_a[2…-2].map { |line| line.delete(“\r”).rstrip }.join(“\n”) + “\n” end cmd ‘show switch’ do |cfg| cfg.gsub! /^System Uptime\s.+/, ‘System Uptime : “Value removed”’ # Omit constantly changing uptime info comment cfg end cmd ‘show vlan’ do |cfg| comment cfg end cmd ‘show config current_config’ do |cfg| cfg.gsub! /^# ACCOUNT LIST\ncreate account( \w* \w*)\n(\w*)\n(\w*)/, “# User Account\ncreate account\1\ \n<< Value removed >>\n<< Value removed >>” # cfg end cfg :telnet do username /\r*([\w\s.@()/:-]+)?([Uu]ser[Nn]ame|[Ll]ogin):/ password /\r*[Pp]ass[Ww]ord:/ end cfg :telnet, :ssh do # preferred way to handle additional passwords post_login do if vars(:enable) == true cmd “enable admin” elsif vars(:enable) cmd “enable admin” , /\r*([\w\s.@()/:-]+)?(PassWord):/i cmd vars(:enable) end end post_login ‘terminal length 0’ post_login ‘terminal clipading’ post_login 'disable clipaging' post_login 'terminal length 0' pre_logout 'logout' end end
D-link DES3200-26 rev.C1
nano /path/to/data/folder/oxidized-docker/model/my_dlink_3200_26_c1.rb
class My_Dlink_3200_26_C1 < Oxidized::Model # D-LINK Switches Dlink_DES-3200-26_C1 prompt /^(\r*[\w\s.@()/:-]+[#>]\s?)$/ comment '# ’ cmd :all do |cfg| cfg.each_line.to_a[2…-2].map { |line| line.delete(“\r”).rstrip }.join(“\n”) + “\n” end cmd ‘show switch’ do |cfg| cfg.gsub! /^System Uptime\s.+/, ‘System Uptime : “Value removed”’ # Omit constantly changing uptime info comment cfg end cmd ‘show vlan’ do |cfg| comment cfg end cmd ‘show config current_config’ do |cfg| cfg.gsub! /^# ACCOUNT LIST\ncreate account( \w* \w*)\n(\w*)\n(\w*)/, “# User Account\ncreate account\1\ \n<< Value removed >>\n<< Value removed >>” # cfg end cfg :telnet do username /\r*([\w\s.@()/:-]+)?([Uu]ser[Nn]ame|[Ll]ogin):/ password /\r*[Pp]ass[Ww]ord:/ end cfg :telnet, :ssh do # preferred way to handle additional passwords post_login do if vars(:enable) == true cmd “enable admin” elsif vars(:enable) cmd “enable admin” , /\r*([\w\s.@()/:-]+)?(PassWord):/i cmd vars(:enable) end end post_login ‘terminal length 0’ post_login 'terminal clipading' pre_logout 'logout' end end
Cisco Nexus
nano /path/to/data/folder/oxidized-docker/model/my_nxos.rb
class My_NXOS < Oxidized::Model prompt /^(\r?[\w.@_()-]+[#]\s?)$/ comment '! ' def filter(cfg) cfg.gsub! /\r\n?/, “\n” cfg.gsub! prompt, ‘’ end cmd :secret do |cfg| cfg.gsub! /^(snmp-server community)./, ‘\1 ’ cfg.gsub! /^(snmp-server user (\S+) (\S+) auth (\S+)) (\S+) (priv) (\S+)/, '\1 ’ cfg.gsub! /(password \d+) (\S+)/, ‘\1 ’ cfg.gsub! /^(radius-server key)./, ‘\1 ’ cfg.gsub! /^(tacacs-server host .+ key(?: \d+)?) \S+/, ‘\1 ’ cfg end cmd ‘show version’ do |cfg| cfg = filter cfg cfg = cfg.each_line.take_while { |line| not line.match(/uptime/i) } comment cfg.join “” end cmd ‘show inventory’ do |cfg| cfg = filter cfg comment cfg end cmd ‘show vlan brief’ do |cfg| cfg = filter cfg comment cfg end cmd ‘show running-config all’ do |cfg| cfg = filter cfg cfg.gsub! /^(show run.*)/, ‘’ cfg end cfg :ssh, :telnet do post_login ‘terminal length 0’ pre_logout ‘exit’ end cfg :telnet do username /^login:/ password /^Password:/ end end
Zyxel ES2108
nano /path/to/data/folder/oxidized-docker/model/my_zyos.rb
class My_ZyOS < Oxidized::Model prompt /^([\w.@()-]+[#>]\s\e7)$/ comment ';; ' cmd :all do |cfg| cfg.gsub! /^.*\e7/,‘’ end cmd ‘show version’ cmd ‘show running-config’ cmd ‘show aaa authentication’ cfg :ssh do username /^User name:/i password /^Password:/i end cfg :ssh do if vars :enable post_login do send “enable\n” # Interpret enable: true as meaning we won’t be prompted for a password unless vars(:enable).is_a? TrueClass expect /[pP]assword:\s?$/ send vars(:enable) + “\n” end expect /^.+[#]$/ end end pre_logout 'exit' end end
Если вы заметили что у Сергея Ершова на github так же имеются свои наработки по моделям D-link, располагаются они по пути /docker/oxidized_docker-compose/new-devices. Пользоваться ими возможно, после копирования.
cp /docker/oxidized_docker-compose/new-devices/* /path/to/data/folder/oxidized-docker/model
Список используемых источников:
https://github.com/ytti/oxidized https://docs.docker.com/compose/install/standalone/ https://computingforgeeks.com/install-docker-and-docker-compose-on-debian/ https://github.com/ytti/oxidized/tree/master/lib/oxidized/model https://github.com/ErshovSergey/oxidized_docker-compose https://www.ekzorchik.ru/2019/03/backing-up-mikrotik-via-oxidized/
