Python SSH

  • di

Contenuto della lezione

Ci sono diverse opzioni per usare SSH in Python ma Paramiko è la più popolare. Paramiko è una libreria di protocollo SSHv2 per Python. In questa lezione, vi mostrerò come usare Paramiko per connettersi ad un router Cisco IOS, eseguire un comando show e restituirci l’output.

Configurazione

Ecco la topologia:

Python H1 R1

Utilizzerò un router Cisco IOS con IOS versione 15.7(3)M3 ed eseguirò il codice Python dal mio computer.

Router

Sul router, dobbiamo abilitare SSH:

R1(config)#ip domain-name networklessons.localR1(config)#crypto key generate rsa general-keys modulus 1024R1(config)#ip ssh version 2R1(config)#username admin privilege 15 secret adminR1(config)#line vty 0 4R1(config-line)#transport input sshR1(config-line)#login local

Ho configurato un utente “admin” con livello di privilegio 15 in modo da avere pieno accesso al router una volta effettuato il login.

Python

Dobbiamo installare Paramiko, il che è facile con PIP:

pip install paramiko

Ora siamo pronti per provare un po’ di codice.

Codice d’esempio

Nel nostro primo esempio, ecco cosa cerchiamo di realizzare:

  • Connettersi al router con autenticazione nome utente/password.
  • Esegui il comando show ip route.
  • Cerca il percorso predefinito nell’output e mostracelo.

Ecco il mio codice:

import paramikorouter_ip = "172.16.1.100"router_username = "admin"router_password = "admin"ssh = paramiko.SSHClient()# Load SSH host keys.ssh.load_system_host_keys()# Add SSH host key automatically if needed.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())# Connect to router using username/password authentication.ssh.connect(router_ip, username=router_username, password=router_password, look_for_keys=False )# Run command.ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("show ip route")output = ssh_stdout.readlines()# Close connection.ssh.close()# Analyze show ip route outputfor line in output: if "0.0.0.0/0" in line: print("Found default route:") print(line)

Quando eseguiamo questo codice, ecco cosa otteniamo:

Found default route:S* 0.0.0.0/0 via 172.16.1.254

Questo è bello. Siamo riusciti a connetterci al router, eseguire il comando show ip route e cercare il percorso predefinito.

Codice di esempio migliorato

Come potremmo migliorare questo script con alcune delle cose che abbiamo imparato? Per esempio:

  • Il nostro codice esegue un singolo comando. Che ne dite di usare una funzione in modo da poter usare il nostro codice per connettersi a diversi dispositivi ed eseguire diversi comandi?
  • Che succede se la nostra connessione SSH fallisce? Sarebbe bello affrontare questo con un blocco try/except. Che ne dite di provare a connetterci più volte?

Vediamo cosa possiamo fare. Ecco il mio codice migliorato:

import paramikorouter_ip = "172.16.1.100"router_username = "admin"router_password = "admin1"ssh = paramiko.SSHClient()def run_command_on_device(ip_address, username, password, command): """ Connect to a device, run a command, and return the output.""" # Load SSH host keys. ssh.load_system_host_keys() # Add SSH host key when missing. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) total_attempts = 3 for attempt in range(total_attempts): try: print("Attempt to connect: %s" % attempt) # Connect to router using username/password authentication. ssh.connect(router_ip, username=router_username, password=router_password, look_for_keys=False ) # Run command. ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command) # Read output from command. output = ssh_stdout.readlines() # Close connection. ssh.close() return output except Exception as error_message: print("Unable to connect") print(error_message)# Run functionrouter_output = run_command_on_device(router_ip, router_username, router_password, "show ip route")# Analyze show ip route output# Make sure we didn't receive empty output.if router_output != None: for line in router_output: if "0.0.0.0/0" in line: print("Found default route:") print(line)

Cosa ho cambiato?

  • Ho creato una funzione per contenere il codice usato per connettersi al router.
  • Ho aggiunto un blocco try/except per la connessione con più tentativi. Quando la connessione fallisce, mostra il motivo.
  • Un controllo extra per vedere se l’output del router contiene qualche informazione.

Verifica

Eseguiamo nuovamente il nostro codice per vedere se funziona.

Password errata

Quando si fornisce una password errata, si ottiene questo output:

Attempt to connect: 0Unable to connectAuthentication failed.Attempt to connect: 1Unable to connectAuthentication failed.Attempt to connect: 2Unable to connectAuthentication failed.

Questo sembra buono. Il nostro codice ha tentato di connettersi tre volte e ha mostrato il motivo per cui non è riuscito a connettersi.

Host non disponibile

Quando l’host non è disponibile, si ottiene questo output:

Attempt to connect: 0Unable to connect A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respondAttempt to connect: 1Unable to connect A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respondAttempt to connect: 2Unable to connect A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

Ancora una volta, tre tentativi di connessione e mostra il motivo per cui il nostro script è fallito.

Conclusione

Ora avete imparato come potete connettervi a un dispositivo usando SSH e Python. Anche se questo funziona, potrebbe non essere la soluzione migliore. In questo esempio, ho eseguito il comando show ip route e ho cercato il percorso predefinito. Questo è semplice, ma cosa succede se vuoi analizzare i comandi di show che hanno molte informazioni?

È possibile analizzare l’output dei comandi di show come questo usando le espressioni regolari, ma è una sofferenza. Invece, se possibile, è meglio usare un’API REST dove il dispositivo restituisce l’output in formato JSON. Analizzare JSON in Python è molto più facile.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *