Python SSH

  • par

Contenu de la leçon

Il existe de multiples options pour utiliser SSH en Python mais Paramiko est la plus populaire. Paramiko est une bibliothèque de protocole SSHv2 pour Python. Dans cette leçon, je vais vous montrer comment utiliser Paramiko pour vous connecter à un routeur Cisco IOS, exécuter une commande show et nous renvoyer la sortie.

Configuration

Voici la topologie:

Python H1 R1

J’utiliserai un routeur Cisco IOS exécutant la version IOS 15.7(3)M3 et j’exécuterai le code Python depuis mon ordinateur.

Routeur

Sur le routeur, nous devons activer 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

J’ai configuré un utilisateur « admin » avec le niveau de privilège 15 afin que nous ayons un accès complet au routeur une fois connecté.

Python

Nous devons installer Paramiko, ce qui est facile avec PIP:

pip install paramiko

Nous sommes maintenant prêts à essayer du code.

Echantillon de code

Dans notre premier exemple, voici ce que nous essayons d’accomplir :

  • Connexion au routeur avec authentification par nom d’utilisateur/mot de passe.
  • Exécuter la commande show ip route.
  • Rechercher la route par défaut dans la sortie et nous la montrer.

Voici mon code :

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)

Lorsque nous exécutons ce code, voici ce que nous obtenons :

Found default route:S* 0.0.0.0/0 via 172.16.1.254

C’est bien. Nous avons réussi à nous connecter au routeur, à exécuter la show ip route commande et à rechercher la route par défaut.

Échantillon de code amélioré

Comment pourrions-nous améliorer ce script avec certaines des choses que nous avons apprises ? Par exemple :

  • Notre code exécute une seule commande. Que diriez-vous d’utiliser une fonction pour que nous puissions utiliser notre code pour nous connecter à différents appareils et exécuter différentes commandes ?
  • Que faire si notre connexion SSH échoue ? Il serait bien de traiter cela avec un bloc try/except. Et si nous essayions de tenter de nous connecter plusieurs fois ?

Voyons ce que nous pouvons faire. Voici mon code amélioré :

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)

Qu’est-ce que j’ai changé ?

  • J’ai créé une fonction pour contenir le code utilisé pour se connecter au routeur.
  • J’ai ajouté un bloc try/except pour la connexion avec plusieurs tentatives. Lorsque la connexion échoue, il affiche la raison.
  • Une vérification supplémentaire pour voir si la sortie du routeur contient des informations.

Vérification

Exécutons à nouveau notre code pour voir s’il fonctionne.

Mauvais mot de passe

Lorsque vous fournissez un mauvais mot de passe, vous obtenez cette sortie:

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

Cela semble bon. Notre code a tenté de se connecter trois fois et a montré la raison pour laquelle il n’a pas pu se connecter.

Hôte indisponible

Lorsque votre hôte est indisponible, vous obtenez cette sortie:

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

Encore une fois, trois tentatives de connexion et il montre la raison pour laquelle notre script a échoué.

Conclusion

Vous avez maintenant appris comment vous pouvez vous connecter à un périphérique en utilisant SSH et Python. Bien que cela fonctionne, ce n’est peut-être pas la meilleure solution. Dans cet exemple, j’ai exécuté la commande show ip route et j’ai recherché la route par défaut. C’est simple, mais que faire si vous voulez analyser les commandes de spectacle qui ont beaucoup d’informations ?

Il est possible d’analyser la sortie des commandes de spectacle comme cela en utilisant des expressions régulières, mais c’est une douleur. Au lieu de cela, si possible, il est préférable d’utiliser une API REST où le périphérique renvoie la sortie au format JSON. L’analyse syntaxique de JSON en Python est beaucoup plus facile.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *