Админская фамилия

Make Sysadmins Great Again

PHP IPAM. Импорт из Excel

IP Address Management (сокращенно IPAM) – средство планирования, отслеживания и управления IP адресами в сети (via). В больших сетях отследить все используемые адреса и приготовиться к их изменению или внедрению новых – большая, трудновыполнимая задача. База данных IP адресов у многих ведется в различных табличка (Google Docs, Excel), у остальных не ведется совсем.При изменениях в сети оперировать информацией из этих мест становится все сложнее и документы быстро теряют свою актуальность.Именно поэтому было решено развернуть сервер управления IP адресами в нашей сети. После мук выбора я остановился на PHP IPAM - он показался мне наиболее дружелюбным и функциональным, к тому же имеет API для взаимодействия с внешними системами.Посмотреть на демо это системы можно тутКак происходит установка этой замечательной системы я рассказывать не буду - всё и так хорошо описано в Интернете. Если будут вопросы - спрашивайте в комментарияхА так как сеть у меня уже большая и информация о ней мало где отражена, то актуальнейшая информация находится в таблицах маршрутизации роутеров. Эту информацию нужно внести в базу данных сервера IPAM. А как это сделать, я сейчас расскажу.С помощью системы мониторинга The Dude выгружаем таблицу маршрутизации в csvЭкспорт из Dude в csvОткрываем Excel и загружаем данные. Данные - из текстаИмпорт csv в ExcelВыбираем наш файл. В открывшемся окне указываем формат - с разделителям и жмем далееС разделителямиThe Dude экспортирует в файл с раделителями - запятыми, поэтому выбираем “запятые” и жмем далееРазделители - запятыеНа следующем шаге жмем кнопку “Готово”Готово!Выбираем ячейку, начиная с которой нужно вставить данные - обычно это А1. И наслаждаемся результатом. Теперь можно подкорректировать табличку.ExcelТеперь нам нужно сформировать csv, который принял бы наш IPAM сервер. А у него следующий формат файла для импорта:Формат csv для импорта в IPAMsection name*(varchar(128)),    subnet*(varchar(255)),   mask(varchar(3)),  description(text),   vlan name(varchar(255)),   domain name(varchar(64)),   vrf name(varchar(32)). Обязательны только первые два параметра - имя секции и подсеть.Оставим только нужную нам информациюУбрали ненужноеКак видим, остались только данные о подсети и связанного с ней филиала. Но имя интерфейса нам ни к чему, поэтому из строки вида <sstp-pub-740102> надо сделать RB740102. В этом нам поможет ExcelНайти и заменитьТеперь нам нужно избавиться от закрывающего спецсимвола “>">Финиш близкоПриведем нашу табличку к такому видуГотовый ExcelИ сохраним как csv. Excel ругнется на то, что мы потеряем данные, но мы готовы на такой риск =)В итоге должны получить файл следующего видаCSVЕго уже можно импортировать в PHP IPAM. Заходим в Administration - Import/ExportImportВ PHP IPAM на данный момент в версии 1.2 rev1 доступен импорт только subnets. Поэтому выбираем subnets и жмем ImportImport subnetsЖмем BrowseBrowseВыбираем наш csv и жмем открыть.На этом этапе мы должны получить ошибку: Error: Upload directory is not writable, or does not exist.Error: Upload directory is not writable, or does not exist.Это значит, что у веб-сервера нет прав на запись в папку upload. Добавим эти права. Выполним в консоли  sudo chmod -R g+w o+w /var/www/html/phpipam/app/admin/import-export/upload/ Тут должен быть путь до вашего сервера IPAM! ImportПовторяем пункты импорта. Система выдаст предупреждение о том, что не все пункты сопоставлены. Точно - в первом столбце пусто. Выбираем там section name и жмем Preview. Если все хорошо, то система покажет список импортируемых подсетей и их именаUploaded dataЖмем Import и проверяем указанную в поле section csv-файла секцию. Наши записи успешно импортированы!Готово! 


Скрипт для проверки наличия USB-модема на RouterOS

Понадобился скрипт, определяющий наличие USB-модема, подключенного к Mikrotik. Присылает на почту название модема и его серийник. Хорошо бы допилить скрипт до отправки уровня сигнала и количества денег на счете, но мои модемы не дают доступа к своему меню - надо шить.:log info “Starting Modem Info Script…”;:local sysname [/system identity get name];:local sysver [/system package get system version];:local mname [/system resource usb get 1 value-name=name];:local mnumber [/system resource usb get 1 value-name=serial-number];:local smtpserv [:resolve “smtp.mail.ru”];:local Eaccount “mail@mail.ru”;:local pass “your_password”;:log info “Collecting Information”;:delay 5;:log info “Sending Information via E-mail…”;/tool e-mail send from="<$Eaccount>" to=$Eaccount server=$smtpserv </span>port=587 user=$Eaccount password=$pass start-tls=yes </span>subject=("$sysname Modem Information (" . [/system clock get date] . “)”) </span>body=("$sysname Modem.\nTime and Date stamp: " . [/system clock get time] . " " . </span>[/system clock get date] . “\nModem $mname, SN: $mnumber”);:log info “Modem Info Complete!”;


Скрипт для выявления порта свитча по маку. Опрос по SNMP

Допилил предыдущий скрипт . Необходимо знать аплинки каждого из свитчей. В моем случае, все они подключены к одному корневому (RootSwitch). Скрипт вытягивает по SNMP FDB таблицу корневого свитча, ищет в ней заданный MAC, сверяет его по заранее заданной таблице аплинков до свитчей доступа, переходит на следующий свитч и с него так же забирает FDB таблицу, а в ней уже ищет необходимый MAC. Информация выводится следующим образом “MAC, vlan, port корневого свитча; MAC, vlan, port конечного свитча”.Для работы с SNMP необходимо подключить модуль SharpSNMP.Из неожиданностей в OID  MAC адреса хранятся в десятичном формате, пришлось их переводить в шестнадцатеричный. Простым способом вернуть несколько значений из функции невозможно. Пришлось городить хэш-таблицу, в которой хранились бы три массива (MAC, vlan, port)В OID информация хранится следующим образом:OID                                                                                   Data—                                                                                       —-.1.3.6.1.2.1.17.7.1.2.1.1.2.1                                               223.1.3.6.1.2.1.17.7.1.2.1.1.2.41                                              63.1.3.6.1.2.1.17.7.1.2.1.1.2.4026                                         222.1.3.6.1.2.1.17.7.1.2.2.1.2.1.144.2.166.50.206.43                3.1.3.6.1.2.1.17.7.1.2.2.1.2.1.144.2.166.50.206.63                6.1.3.6.1.2.1.17.7.1.2.2.1.2.1.144.2.166.50.206.126              4.1.3.6.1.2.1.17.7.1.2.2.1.2.41.0.21.100.59.187.78                26.1.3.6.1.2.1.17.7.1.2.2.1.2.4026.0.9.136.173.129.150          26.1.3.6.1.2.1.17.7.1.2.2.1.3.4026.232.64.241.24.239.215      3.1.3.6.1.2.1.17.7.1.2.2.1.3.4026.232.64.241.24.242.213      3Первые три строки (может быть больше или меньше, в зависиомсти от количества vlan’ов): последняя цифра - номер vlan’а, data - количество MAC-адресов в этом влане в FDB-таблице.Далее следуют строки с перечислением MAC-адресов, сгруппированные по vlan’ам: после символов .1.3.6.1.2.1.17.7.1.2.2.1.2. идет номер vlan (1, 41, 4026 в нашем случае), а за ним MAC адрес в десятичном формате. В поле Data - порт с найденным MAC-ом.Далее следуют строки, начинающиеся на .1.3.6.1.2.1.17.7.1.2.2.1.3. Они содержат информацию, о способе получения MAC-адреса. Если параметр 3 - MAC получен методом learning (опрос порта), 4 - MAC коммутатора, с которого взяли FDB.Мы будем обрабатывать строки из второго блока. Сначала отсекаем ненужную нам часть OID, затем разбиваем на подстроки и запоминаем данные. Полученные данные выводим по порядку в 3 массива - MAC, port, vlan.Собственно скрипт:function findonswitch ([string]$ip) {$oid=".1.3.6.1.2.1.17.7.1.2.2.1.2."$mas = Invoke-SnmpWalk $ip “.1.3.6.1.2.1.17.7.1.2” #vlans$i=0$vlan=@()$mac=@()$port=@()foreach ($pt in $mas){ if ($pt.OID -like “$oid”) { $pt.OID = $pt.OID.remove(0,28) $vlan += $pt.OID.Substring(0, $pt.OID.IndexOf(".")) $temp = $pt.OID.Substring($pt.OID.IndexOf(".") + 1, $pt.OID.Length - $pt.OID.IndexOf(".")-1) ###перевод из Dec в Hex $mas=$temp.split(".") $nmac=@() foreach ($sdec in $mas) { $dec = [int]$sdec $nmac += ‘{0:X2}’ -f $dec } $str=$nmac -join “-" ### $mac += $str $port += $pt.Data } }$return= @{}$return.vlan=$vlan$return.mac=$mac$return.port=$portreturn $return}####################################################################$rootIP = “192.168.0.21”$sport = (“1”, “2”, “5”, “12”, “13”, “14”, “43”, “44”, “65”, “66”, “74”, “107”)$swDB = (“192.168.0.42”, “192.168.0.44”, “192.168.0.61”, “192.168.0.52”, “192.168.0.51”, “192.168.0.12”, “192.168.0.33”, “192.168.0.32”, “192.168.0.41”, “192.168.0.43”, “192.168.0.11”, “192.168.0.34”)function findinarr ($array, $value) {    for ($i=0; $i -lt $array.count;$i++) {         if($array[$i] -eq $value){$i}    }}$res=findonswitch $rootIP$dataMACRoot = $res.mac$dataPortRoot = $res.port$dataVlanRoot = $res.vlan$mac = Read-Host “Enter MAC”if ($mac.indexof(”:") -ne 0){ $mac=$mac.replace(":", “-”)}$i=0$flag=0foreach ($S in $dataMACRoot){ if ($mac -eq $s) { $portRoot = $dataPortRoot[$i] $vlanRoot = $dataVlanRoot[$i] Write-Host $mac on $portRoot ‘in vlan’ $vlanRoot on RootSwitch if ($flag -eq 0) { $portRoot1 = $dataPortRoot[$i] } $flag++ } $i++}$A = findinarr $sport $portRoot1$res=findonswitch $swDB[$A]$dataMAC = $res.mac$dataPort = $res.port$dataVlan = $res.vlan$i=0foreach ($S in $dataMAC){ if ($mac -eq $s) { $port = $dataPort[$i] $vlan = $dataVlan[$i] Write-Host $mac on $port ‘in vlan’ $vlan on ‘switch’ $swDB[$A] } $i++}Работа второй части скрипта (после ###########) описана в предыдущем посте. Тут она претерпела некоторые изменения, в связи с входящей информацией из массива, а не из csv-файла, но логика не изменилась.


PowerShell. Заметки.

Начал использовать PowerShell. Инструмент очень мощный. По мощности сравним с шеллом никсов. Не буду утверждать что круче - не разбираюсь ни в том, ни в другом. Решил сделать в качестве памятки несколько заметок по использованию этого инструмента.1. Заметка номер раз. Простейшие регулярные выражения в PS.^ - начало строки$ - конец строки. - один любой символУдалить подстроку или заменить её - -replace . Простейший способ редактирования строк без вникания в код и написания “нормальных” регэкспов - тупо удалить нужное кол-во символов. (Get-Content .\list.txt)  -replace “^………………………………” | Set-Content list1.txtПолучили содержание файла, прошли по строкам, в каждой строке удалили какое-то количество первых символов, записали в файл.2. Получить список файлов, открывавшихся определенным пользователем в определенную дату.Get-EventLog security -after (Get-Date -hour 0 -minute 0 -second 0) | ?{$.eventid -eq 560} | ?{$.username -eq “username”}Здесь мы получаем события журнала безопасности за текущую дату с 0 часов, 0 минут, 0 секунд с eventid равным 560 (аудит успеха. открытие объекта. Эта информация здесь: Описание событий системы безопасности) и именем пользователя username.Но для того, чтобы эта команда сработала, необходимо чтобы велся аудит доступа к файловой системе. Об этом можно почитать тут. Позже сам напишу подобный мануал.Дальше больше3. Теперь скрипт по мотивам предыдущей заметки. Назначение: получить список пользователей, пытавшихся открыть файлы на ФС. Получаем время доступа, имя файла и имя пользователя.$Events = Get-EventLog security | ?{$.eventid -eq 560}$Data = New-Object System.Management.Automation.PSObject$Data | Add-Member NoteProperty Time ($null)$Data | Add-Member NoteProperty UserName ($null)$Data | Add-Member NoteProperty File ($null)$Events | %{$Data.time = $.TimeGenerated$message = $.message.split("n") | %{$_.trimstart()} | %{$_.trimend()}</span></i><br /><i><span style="color: #990000;"><br /></span></i><i><span style="color: #990000;">$Data.UserName = ($message | ?{$_ -like "Пользователь-клиент:*"} | %{$_ -replace "^.+:."} )&nbsp;</span></i><br /><i><span style="color: #990000;">$Data.File = ($message | ?{$_ -like "Имя объекта:*"} | %{$_ -replace "^.+:."})&nbsp;</span></i><br /><i><span style="color: #990000;"><br /></span></i><i><span style="color: #990000;"><br /></span></i><i><span style="color: #990000;">$data | Out-File F:\Docs\fs1.txt -Append</span></i><br /><i><span style="color: #990000;">}&nbsp;</span></i><br /><br />Разберем по строкам.<br /><br />Первая строка получает события типа "безопасность" с кодом 560 (Get-Eventlog - получить данные журнала событий, security - данные журнала "безопасность", где свойство eventid каждого (|) события ($_) эквивалентно (-eq) 560).<br /><br />Вторая строка создает объект PSObject. 3-5 строки добавляют в объект поля Time, UserName и File.<br /><br />Затем пробегаемся по событиям следующим способом.<br />В поле time объекта Data записываем время создания строки с сообщением (время доступа к файлу).<br /><br />&nbsp;Строкой&nbsp;<i><span style="color: #990000;">$message = $_.message.split("n") | %{$.trimstart()} | %{$_.trimend()} — в переменную message заносим массив строк, которые разделяются символом переноса строки (’n), функции trimstart(), trimend() убирают все лишние символы в конце и в начале строки, функция split разделяет строку.Далее во вновь образовавшемся массиве мы ищем совпадения по строке «Пользователь-клиент:» и «Имя объекта:», а -replace в дальнейшем удаляет эти регулярные выражения, оставляя саму информацию. И последней строкой записываем то, что получилось в итоге в файл. Получается что-то типа этого:Time                                    UserName                                File                                   —-                                    ——–                                —-                                   13.06.2013 16:52:22                     Seti                                    Docs\Сети\Общая папка\Реестры счетTime                                    UserName                                File                                   —-                                    ——–                                —-                                   13.06.2013 16:52:22                     Seti                                    Docs\Сети\Общая папка\Реестры счетСкрипт создан при помощи этих постов: хабр, Поданс.


Перенос учетных записей в домен

Надоело переносить учетки пользователей из локальных в доменные при внедрении Active Directory. Решил найти автоматизированное решение. Оказывается не я первый озадачился этой проблемой =) Есть как минимум 5 вариантов автоматизации. Рассмотрим их по порядку.User State Migration Tool. Бесплатная утилита от Microsoft. Поставляется в комплекте Windows Automated Installation Kit. Используется из консоли. Мануал. У меня не получилось выполнить сохранение профиля - scanstate встал на последнем этапе на 1% и никак не реагировал.Active Directory Migration Tool. Продукт от той же всем известной компании. Предназначен для миграции из домена в домен. Сейчас нас не интересует. Мануал.В Windows 7 можно воспользоваться стандартным средством переноса данных.Moveuser - тоже от MS. Работает на XP. Версия для 7.User Profile Wizard. Бесплатная утилита от ForensIT. Смогла перенести все данные и настройки. Проблем пока не замечено. Ещё можно написать скрипт на WMI/batch/PowerShell/brainfuck/что-то_ещё - но это уже другая история.После переноса профиля обязательно проверяйте всё - скорее всего что-то обработалось неправильно и придется доделывать руками.Тема на форуме, где я поднимал этот вопрос.


Скрипт. Заливка файлов на FTP

Этот скрипт был написан для предотвращения нежелательных последствий от BSOD. Скрипт просматривает папку с дампами BSOD. Если дампы есть (синий экран был), то создаёт на FTP-сервере папку с датой создания дампа в качестве имени, а внутри неё папку с именем сбойной машины. И уже в эту папку копирует дампы. Затем переименовывает дампы в *.dmp.old, чтобы на следующий день их не копировать. Если скрипт запущен впервые, он копирует дампы как положено (каждый на свою дату).Краткое описание скрипта:Секция check. Проверяет, есть ли уже дампы. Если нет, скрипт заканчивает свою работу. Если да - переходит на следующую секцию.Секция makeftpcommand. Создаёт файл с именем script, в который пишет команды для работы с FTP.Секция makedirectory. Анализирует папку с дампами и записывает в script команду для создания папки на FTP-сервере с именем вида дата/имя_машины.Секция copyfiles. Заливает дамп в нужную папку.Секция rename. Переименовывает дамп в .dmp.old, чтобы при следующем запуске не копировать уже скопированные файлы.Оставшиеся строки закрывают файл script, выполняют его и удаляют.@echo on@echo =======================================@echo Copying memory dumps on FTP-server@echo =======================================@echo Script startedset $SRC="%systemroot%\minidump":check@echo Checking files@if exist $SRC*.dmp goto makeftpcommand:makeftpcommandset addr=scriptecho.open 127.0.0.1>> %ADDR%echo.anonymous>> %ADDR%echo.>> %ADDR%echo.binary>> %ADDR%:makedirectory@echo Making directoriesfor %%a in (%$SRC%) do (for /f “tokens=1” %%b in ("%%~ta") do (echo.mkdir %%~b%computername%>>%ADDR%)):copyfiles@echo Copying filesfor %%a in (%$SRC%) do (for /f “tokens=1” %%b in ("%%~ta") do (echo.cd %%~b%computername%>>%ADDR% && echo.send %%a >>%ADDR% && echo.cd ../..>>%ADDR%)):renamefor /f “tokens=1” %%a in (‘dir /b %$SRC%*.’) do ren %$SRC%%%a %%a.oldecho.bye>> %ADDR%ftp.exe -s:%ADDR% del /F /Q script


Скрипт для поднятия pptp в Ubuntu

Каждый раз при включении компа прописыать роутинг и поднимать впн неудобно. Проще написать скрипт, который сделает всё это сам и кинуть его в автозагрузку.Вот скрипт:#!/bin/bash           #указываем кто будет выполнять скрипт (bash)route del default     #убираем дефолтный маршрутLOG="/var/log/pptp-run.log"     #логи будут писаться в /var/log/pptp-run.logwhile true;do echo -e “\n==============================================\n date” >> $LOG /usr/sbin/pptp vpn.server.ru >> $LOG     #вывод сообщений из pptp в pptp-run.log sleep 10;doneСохраняем его в /usr/local/bin/pptp-run-sh. Не забываем сделать его исполняемым: chmod +x pptp-run.shИ прописываем в автозагрузку:sudo nano /etc/rc.localпоследней строчкой указываем:  /usr/local/bin/pptp-run.shВсё! Скрипт будет выполняться при запуске системы с правами системы (а может и нет=)), а так же при очередном “отваливании” впн-соединения. 


Автоматизация

Недавно по работе понадобилась сделать так, чтобы при появлении окошка от программы, в нем автоматически нажимались определенные кнопки и окошко закрывалось(чтобы не грузить пользователей лишней работой). Первые мысли - батник или VBScript. VBScript я совсем не знаю, хотя ради такого можно было разобраться. А вот насчет батника гугл сказал, что не прокатит. В итоге остановился на прекрасной программке - AutoIT. Это программка со скриптовым языком, позволяющая автоматизировать работу.Всё предельно просто. Мой скрипт ждал появление окошка, затем жал на кнопочку, потом во втором окошке - ещё одну, снова ждём около минуты и нажимаем ОК. На всё про всё включая чтения FAQ, гугление и написание скрипта у меня ушло минут 15. Так что рекомендую!FAQ на OSZoneВот мой скрипт:If WinExists(@ScriptName) Then Exit                          ; Проверяем не запущена лиAutoItWinSetTitle(@ScriptName)                                 ; уже копия скриптаRun("\192.168.0.254\SoftwareInfentory\tniaudit.exe")    ; Запускаем софтинуWinWaitActive(“Confirm”)                                            ; Ждём окноSend("!y")                                                                  ; Жмем YesWinWaitActive(“Information”)                                       ; Ждём окноSend(’{ENTER}’)                                                         ; Жмём кнопку, выбранную                                                                                ; по умолчаниюWinWaitActive(“Information”)                                       ; Ждём окно Send(’{ENTER}’)                                                         ; Жмём кнопку, выбранную                                                                                ; по умолчаниюUPD 29.10.10.А сегодня появился пост на хабре на эту тему =)Ещё по AutoIt была серия статей в журнале Системный администратор (2005.4 - 2005.7)