Child pages
  • Проверка доступности объекта МО по telnet с установленными реквизитами
Skip to end of metadata
Go to start of metadata

Часто возникает потребность ответить на вопрос "а на все ли объекты МО можно зайти с установленными логинами паролями?". Никто не застрахован от ошибок или факторов "так настроено, ничего не трогал (С)"

Идея проверки работает по такому алгоритму:

  1. Получить из БД все хосты для которых нужно произвести проверки. ( у меня есть некоторые объекты имеют в имени "loopback" что указывает на то что это ещё один интерфейс на оборудовании и его проверять не нужно   )
  2. Занести значения в массив
  3. Перебирать все полученные айпи в цикле.
  4. Получить из БД реквизиты доступа к МО
  5. Проверить доступен ли хост с помощью ping
  6. Передать  ip,user,passwd,hostname,profile_name,administrative_domain_id  expect скрипту и попытаться зайти на оборудование с ними и выполнить команды "show version" "dist ver"
  7. С помощью шаблонов для regex определяем какие попытки закончились неудачно.
  8. Строим график тенденции изменения количества таких хостов (очень удобно показывать руководству)
  9. Отправляем по почте график и результирующий файл на список рассылки

 

ls -la

/log

bad.txt

counter.rrd

cron.sh

fails.png

mail.sh

makegraph.sh

out.badhosts.txt

out.hostdown.txt

telnet.sh

 

Основной файл

cron.sh

#!/bin/bash

# скрипт должен вынуть из базы айпи логин пароль тип и выполнить экспат для оборудования.
# полученные результаты используются для проверки того что оборудование доступно по телнету.
# todo
# - сделать проверку какой профиль авторизации используется telnet ssh web
# - сделать проверку на аутонтефикацион профайл

# проверяем пингуется ли оно вообще
BASEDIR=/opt/scripts/maintenance.telnet

# выполняем сканирование сети.
# в качестве параметра берём диапазон переданный из консоли.
if [ "$1" = "scan" ]
    then
    # очищаем вывод от предыдущего запуска

rm -f $BASEDIR/log/* $BASEDIR/out.*

#SQLQUERY="SELECT address,\"user\",password,profile_name,name from sa_managedobject where name not like '%-loopback-%' and name not like 'SAE' order by address"
SQLQUERY="SELECT address from sa_managedobject where name not like '%-loopback-%' and name not like 'SAE'  and scheme = '0' order by address;"
# результат заносится в массив сразу.
# http://stam.blogs.com/8bits/2010/05/bash-query-mysql-and-store-result-in-an-array.html
declare -a SQLRESULT
# SQLRESULT=( 1 2 34 43)
SQLRESULT=( `echo $SQLQUERY | psql -U noc --dbname noc -X -A -t -q -F"     " --single-transaction --no-align  | tr '\n' ' '` )
#`echo $SQLQUERY | psql -U noc --dbname noc -X -A -t -q -F"     " --single-transaction --no-align  | tr '\n' ' '`


#echo ${SQLRESULT[]}
# перебираем все значения массива и запускаем телнет сессии
for i in ${SQLRESULT[@]};
    do
    echo $i;
    # получаем информацию о логине пароле
    SQLQUERYTELNET="SELECT \"user\",password,profile_name,administrative_domain_id,name from sa_managedobject where address = '$i' limit 1;"
    SQLRESULTELNET=`echo $SQLQUERYTELNET | psql -U noc --dbname noc -X -A -t -q -F"     " --single-transaction --no-align`
#    echo $SQLQUERYTELNET
#    echo $SQLRESULTELNET
    user=`echo $SQLRESULTELNET | awk '{print $1}'`
    password=`echo $SQLRESULTELNET | awk '{print $2}'`
    profile_name=`echo $SQLRESULTELNET | awk '{print $3}'`
    ad=`echo $SQLRESULTELNET | awk '{print $4}'`
    name=`echo $SQLRESULTELNET | awk '{print $5}'`
    echo "user: " $user
    echo "password: " $password
    echo "profile_name: " $profile_name
    echo "hostname: " $name
    
# проверяем пингуется ли оно вообще

    pingcheck="/bin/ping -W 2 -c 1 $i"
    pingcheckresult=`$pingcheck`
    RETVAL=$?
    echo $RETVAL
    if [ $RETVAL -ne 1 ]
    then
    # передаём в скрипт expect параметры авторизации и длаем слудующую итерацию
            $BASEDIR/telnet.sh $i $user $password > $BASEDIR/log/$ad-$i-$user-$profile_name--$name &
            echo "-------------------"
        else
            echo $i " host down"
            echo -E $i >> $BASEDIR/out.hostdown.txt
    fi
    
done

sleep 60
fi

# проверяем что есть и считаем
cd $BASEDIR/log && grep -l -f $BASEDIR/bad.txt ./* | sort | uniq > $BASEDIR/out.badhosts.txt
# сформировать графиг количества и прикрепить его к письму
cd $BASEDIR/log && grep -l -f $BASEDIR/bad.txt ./* | sort | uniq | wc -l
$BASEDIR/makegraph.sh
$BASEDIR/mail.sh


telnet.sh

#!/usr/bin/expect -f

# скрипт пытается подключиться к удалённому хосту с определённым набором логина пароля и вывести информацию о хосте.

# ftp-rfc <ip-addr>

# makes a telnet connection to ip-addr

exp_version -exit 5.0


set host [lindex $argv 0]

set user [lindex $argv 1]

set passw [lindex $argv 2]


# connect to host and disconnect

set timeout 2

spawn telnet $host

#sleep 2

 

expect -re {\*$}

sleep 1

send "$user\r"

expect -re {\*$}

sleep 1

send "$passw\r"

 

sleep 1

expect -re {\*$}

send "show version\r"

expect -re {\*$}

send "disp ver\r"

expect -re {\*$}

send "\r"

expect -re {\*$}

 

Построение графика

makegraph.sh

#!/bin/bash


   

BASEDIR=/opt/scripts/maintenance.telnet

 

# путь к rrdtool

# RRDtools path

RRDTOOLBIN="/usr/bin/rrdtool"

 

number=`cat $BASEDIR/out.badhosts.txt | wc -l`

 

if [ -a $BASEDIR/counter.rrd ]

    then

    $RRDTOOLBIN update $BASEDIR/counter.rrd N:$number

    echo -e "$RRDTOOLBIN update $BASEDIR/counter.rrd N:$number"

    else

    # дайл не найден и его надо создать

    echo "rrd not found"

    $RRDTOOLBIN create $BASEDIR/counter.rrd --step 86400 \

    DS:numberfail:GAUGE:100000000:0:U \

    RRA:AVERAGE:0.5:1:3000 \

    RRA:AVERAGE:0.5:6:3500 \

    RRA:AVERAGE:0.5:24:3875 \

    RRA:AVERAGE:0.5:288:3985 \

    RRA:MAX:0.5:1:3000 \

    RRA:MAX:0.5:6:3500 \

    RRA:MAX:0.5:24:3875 \

    RRA:MAX:0.5:288:3985

 

fi

$RRDTOOLBIN graph $BASEDIR/fails.png  --start now-30d --end now+1d -w 1150 -h 700 --title "Суммарное количество ошибок на интерфейсах Ethernet по АТС" DEF:number=$BASEDIR/counter.rrd:numberfail:AVERAGE LINE1:number#111111:\"Недоступно\ объектов\ МО-$number\"

 

Отправка почты.

mail.sh

#!/bin/bash

BASEDIR=/opt/scripts/maintenance.telnet

from="root@example.com"
to="noc@example.com"

subject="Список Оборудование  без управления через NOC"
body="Расшифровка файла:

./<номер административного домена>-<IP адресс оборудования>-<логин из NOC>-<Тип оборудования>-<сетевое имя по SNMP\IP если SNMP выключено>

Необходимо настроить на оборудовании авторизацию через RADIUS(предпочтительнее) и\или типовые пароли (admin\admin  cbr\cbr и тд).
Без авторизации не работают системы резервного копирования конфигураций, построения карт сети, отслеживание аварийных ситуаций

Тут нужен список административных доменов.

За инструкциями по настройке обращайте в раздел документации http://example.com/main/desktop/#kb.index

Все вопросы на .......
"
declare -a attachments
attachments=( "$BASEDIR/fails.png" "$BASEDIR/out.badhosts.txt"  )
declare -a attargs
  for att in "${attachments[@]}"; do
     attargs+=( "-a"  "$att" )
  done
mail -s "$subject" -r "$from" "${attargs[@]}" "$to" <<< "$body"

Список regex правил для проверки неуспешного входа. Не оставляйте в конце пустую строчку, иначе в отчёт будут попадать ВСЕ хосты.

bad.txt

Access denied

Authentication failed

Bad Password

Connection refused

Fail!

Failure: Login fail

Error: Failed to authenticate

Error: Local authentication is rejected

Error: Failed to send authen-req

Invalid login

Invalid login

Login failed

Login incorrect

Login incorrect

Login Incorrect

Login invalid

login:show version

password: logon failed

 

 

Related articles

1 Comment

  1. vl

    Всё что написано выше полный бред.

    делаете файл /opt/noc/commands/m-login.py

    и потом ./noc m-login и это работает. можно поставить в cron или через шелл.


    ./noc shell

    # -*- coding: utf-8 -*-
    '''
    Проверяет что логин пароль подходит и если нет то выставляет автоподбор
    '''


    from noc.sa.interfaces.igetversion import IGetVersion
    from noc.sa.models.managedobject import ManagedObject
    from noc.sa.models.managedobject import AdministrativeDomain
    from noc.sa.models.managedobjectprofile import ManagedObjectProfile
    from noc.sa.models.authprofile import *

    from noc.services.discovery.jobs.base import DiscoveryCheck

    #from core.ioloop.ping import Ping
    #from services.ping.service import PingService

    from noc.sa.models.objectstatus import ObjectStatus
    from core.script.base import BaseScript

    from noc.core.management.base import BaseCommand
    from noc.main.models.notificationgroup import NotificationGroup

    staticob = ManagedObjectProfile.objects.get(name='staticip')
    default =  ManagedObjectProfile.objects.get(name='default')
    loopback =  ManagedObjectProfile.objects.get(name='loopback')
    servers =  ManagedObjectProfile.objects.get(name='servers')
    #autodiscovery = AuthProfile.objects.get(name='autodiscovery')

    faillogin = {}
    bodymessage = ""


    #for m in ManagedObject.objects.filter(object_profile=servers).exclude(object_profile=staticob).exclude(name='SAE').exclude(object_profile=loopback):
    for m in ManagedObject.objects.filter().exclude(object_profile=staticob).exclude(name='SAE').exclude(object_profile=loopback):
        # print m, m.is_managed, ObjectStatus.get_status(m)
        if m.user == 'nocproject' and (m.name[:3] == "fsw" or m.name[:3] == 'asw'):
            m.auth_profile = AuthProfile.objects.get(name='autodiscovery')
            m.user = None
            m.password = None
            try:
                m.save()
            except:
                print "Fail save new login"
        if m.is_managed == True and ObjectStatus.get_status(m):
            # проверить что Login отрабатывает нормально
            #print m, m.is_managed, ObjectStatus.get_status(m)
            try:
                l = m.scripts.login()
            except:
                l = False
            print m, "Login:" , l
            if l == False:
                m.auth_profile = AuthProfile.objects.get(name='autodiscovery')
                m.user = None
                m.password = None
                m.super_password = None
                m.snmp_ro = None
                m.snmp_rw = None
                m.is_managed = False
                m.save()
                m.is_managed = True
                m.save()
                
                # добавляем в массив чтобы потом отправить по почте.
                faillogin.update({m.name: m.address})
                # faillogin

    if faillogin is not None:
        for key in faillogin.keys():
            print key, faillogin[key]
            bodymessage = bodymessage + key + " " + faillogin[key] + "\n"

    # обрезаем строку до нужного размера чтобы пролезла в nsq
    if len(bodymessage) > 1024000:
        bodymessage = bodymessage[:1000000]


    #bodymessage = "1111111"
    # если тело письма не пустое - отправляем уведомление.
    print bodymessage

    if bodymessage:
        gname = '15' # 15 - в телегу на канал.
        g = NotificationGroup.get_by_id(gname) # где get_by_id(x) номер Notification Group
        print g
        print g.notify("Оборудование без авторизации в ноке", bodymessage )