Junos PyEZ tasuta ipv4 alamvõrkude otsimise ülesande näitel

Artikkel Junos PyEZ-iga töötamise kohta – "Pythoni mikroraamistik, mis võimaldab hallata ja automatiseerida Junos OS-i töötavaid seadmeid" automatiseerimine ja haldamine, kõike, mida me armastame. Selles artiklis kirjeldatud skripti kirjutamisel oli mitu eesmärki – Pythoni õppimine ja Junos OS-i kasutavate seadmete teabe kogumise või konfiguratsioonide muutmise ülesannete automatiseerimine. Selle konkreetse Python + Junos PyEZ kombinatsiooni valik tehti Pythoni programmeerimiskeelde sisenemise madala barjääri ja Junos PyEZ teegi kasutusmugavuse tõttu, mis ei nõua Junos OS-i ekspertteadmisi.

Ülesanne

Ettevõttele kuuluvate tasuta ipv4 alamvõrkude audit. Alamvõrgu vabaks olemise kriteeriumiks on selle kohta kirje puudumine lüliti marsruuteritel, mis töötab Junos OS-i käitava ruuterina.

Реализация

Python + Junos PyEZ, kuigi oli kiusatus seda teha paramiko ja ssh.exec_command kaudu, Selle tulemusena peate küsitavas seadmes konfigureerima netconfi seadme võrguhaldusprotokolli. Netconf töötab riistvaraga kaugprotseduurikõne RPC kaudu ja kasutab saadud teabe edastamiseks selles näites XML-i.

Junos PyEZ praeguse versiooni installimine PyPI-st toimub järgmise käsuga:

$ pip install junos-eznc

Saate installida ka projekti põhiharust GitHubis järgmise käsuga:

$ pip install git+https://github.com/Juniper/py-junos-eznc.git

Ja veel üks võimalus kaudu

$ pip install -r requirements.txt 

See käsk installib süsteemist puuduvad teegid, mis on tööks vajalikud. Minu versioonis nõuded.txt Neid on ainult kaks, uusimad versioonid on näidatud skripti kirjutamise ajal:

junos-eznc
netaddr

Vaikimisi võtab skript süsteemis praeguse kasutaja nime, sisse logida saab teise kasutaja nime all kasutades klahvi show_route.py -u getpass.getpass võtab parooli stdinist, nii et parool ei jää süsteemi. Seadmega ühenduse loomiseks peate sisestama ka selle hostinime või IP-aadressi, kui seda küsitakse. Kõik seadme autoriseerimiseks vajalikud andmed on vastu võetud.

Junos PyEZ toetab ühenduse loomist seadmetega, mis käitavad Junos OS-i, kasutades konsooli, telneti või netconfi ssh-i kaudu. Artiklis käsitletakse viimast võimalust.

Seadmetega ühendamiseks kasutage mooduli jnpr.junos klassi Device

with jnpr.junos.Device(host=router,
                           user=args.name,
                           passwd=password) as dev:

Päring esitatakse kõikidele marsruuterile teadaolevatele marsruutidele kaugprotseduurikõne või kaugprotseduurikõne kaudu, olenevalt sellest, kumb on mugavam.

data = dev.rpc.get_route_information()

Sarnane käsk Junos OS-is

user@router> show route | display xml

Lisades käsu lõppu rpc, saame päringusildi ja saame selle sobitada RPC meetodi nimega, nii saame teada teisi huvipakkuvaid nimesid. Väärib märkimist, et päringusildi kirjutamise süntaks erineb meetodi nimest, nimelt tuleks sidekriipsud asendada alakriipsudega.

user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")

Ülejäänud osa mähiti ajatsüklisse, et mitte korrata taotlust ruuterile, kui oli vaja kontrollida mõnda mõnda muud alamvõrku nendest, millest ruuter juba teab. Tasub mainida, et ruuter, millele ma päringu esitan, teab marsruute ainult OSPF-i kaudu, nii et servaruuteri puhul on parem skripti tööaja lühendamiseks taotlust veidi muuta.

data = dev.rpc.get_ospf_route_information()

Vaatame nüüd while-tsükli sisu

Alguses palutakse kasutajal sisestada alamvõrk maskiga ja mitte rohkem kui kolm oktetti sama alamvõrgu võrgust, see on vajalik otsinguvahemiku määramiseks. Mulle ei meeldi selline kriteeriumide ja otsinguvahemiku täpsustamine, kuid siiani pole ma paremat lahendust leidnud. Järgmiseks valin saadud alamvõrkude loendist route_list, kasutades muutujat, mis ei sisalda rohkem kui kolme oktetti, mind huvitavad alamvõrgud

tmp = re.search(r'^%sS*' % subnet_search, route_list[i])

IPNetworki, netaddr-mooduli kaudu saan alamvõrke ipv4-aadresside loendi kujul

range_subnet = netaddr.IPNetwork(tmp.group(0))

IPNetworki abil hangin kasutaja sisestatud võrgust maskiga aadresside vahemiku ja genereerin loendi kõigist selle vahemiku aadressidest, et võrrelda neid hõivatud aadresside loendiga.

for i in set(net_list).difference(set(busyip)):
        freeip.append(i)

Kuvan saadud vabade aadresside loendi alamvõrkude kujul

print(netaddr.IPSet(freeip))

Allpool on täielik skript, mida on testitud ruuterina kasutatavatel lülititel, mudelitel ex4550, ex4600


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import getpass
import netaddr
import re
import sys

import jnpr.junos

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user',
                    action='store',
                    dest='name',
                    help='Enter login from tacacs if it differs from the '
                         'username in the system.')
args = parser.parse_args()

if not args.name:
    args.name = getpass.getuser()    # Return the “login name” of the user.
router = input("Full routers name: ")
password = getpass.getpass("Password: ")

try:
    # Authenticates to a device running Junos, for get information about routs
    # into xml format and selects by tag.
    route_list = []
    with jnpr.junos.Device(host=router,
                           user=args.name,
                           passwd=password) as dev:
        data = dev.rpc.get_route_information()
    route_list = data.xpath("//rt-destination/text()")
except (jnpr.junos.exception.ConnectRefusedError,
        jnpr.junos.exception.ConnectUnknownHostError) as err:
    print("Equipment name or password wrong.")
    sys.exit(1)

while True:
    subnet = input("Net with mask: ")
    subnet_search = input("Input no more three octet: ")
    # Gets a list of busy IP addresses from the received subnets.
    busyip = []
    for i in range(len(route_list)):
        tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
        if tmp:
            range_subnet = netaddr.IPNetwork(tmp.group(0))
            for ip in range_subnet:
                busyip.append("%s" % ip)
    range_subnet = netaddr.IPNetwork(subnet)
    # Gets list ip adresses from subnetworks lists.
    net_list = []
    for ip in range_subnet:
        net_list.append("%s" % ip)
    # Сomparing lists.
    freeip = []
    for i in set(net_list).difference(set(busyip)):
        freeip.append(i)
    print(netaddr.IPSet(freeip))

    request = input("To run request again enter yes or y, "
                    "press 'enter', complete request: ")
    if request in ("yes", "y"):
        continue
    else:
        print('Bye')
        break

Allikas: www.habr.com

Lisa kommentaar