Lesson Contents
There are multiple options to use SSH in Python but Paramiko is the most popular one. Paramiko is an SSHv2 protocol library for Python. In this lesson, I’ll show you how to use Paramiko to connect to a Cisco IOS router, run a show command, and return the output to us.
Configuration
Here is the topology:
I’ll use a Cisco IOS router running IOS Version 15.7(3)M3 and I’ll run the Python code from my computer.
Router
On the router, we need to enable SSH:
R1(config)#ip domain-name networklessons.local
R1(config)#crypto key generate rsa general-keys modulus 1024
R1(config)#ip ssh version 2
R1(config)#username admin privilege 15 secret admin
R1(config)#line vty 0 4
R1(config-line)#transport input ssh
R1(config-line)#login local
I configured an “admin” user with privilege level 15 so that we have full access to the router once we log in.
Python
We need to install Paramiko, which is easy with PIP:
pip install paramiko
We are now ready to try some code.
Sample Code
In our first example, here’s what we try to accomplish:
- Connect to the router with username/password authentication.
- Run the
show ip route
command. - Look for the default route in the output and show it to us.
Here is my code:
import paramiko
router_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 output
for line in output:
if "0.0.0.0/0" in line:
print("Found default route:")
print(line)
When we run this code, here’s what we get:
Found default route:
S* 0.0.0.0/0 [1/0] via 172.16.1.254
This is nice. We managed to connect to the router, run the show ip route
command, and look for the default route.
Improved Sample Code
How could we improve this script with some of the things we learned? For example:
- Our code runs a single command. How about we use a function so we can use our code to connect to different devices and run different commands?
- What if our SSH connection fails? It would be nice to deal with this with a try/except block. How about we try to attempt to connect multiple times?
Let’s see what we can do. Here is my improved code:
import paramiko
router_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 function
router_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)
What did I change?
- I created a function to contain the code used to connect to the router.
- I added a
try/except
block for the connection with multiple attempts. When the connection fails, it shows the reason. - An extra check to see if the router output contains any information.
Verification
Let’s run our code again to see if it works.
Wrong Password
When you supply a wrong password, you get this output:
Attempt to connect: 0
Unable to connect
Authentication failed.
Attempt to connect: 1
Unable to connect
Authentication failed.
Attempt to connect: 2
Unable to connect
Authentication failed.
This looks good. Our code attempted to connect three times and showed the reason why it was unable to connect.
Host unavailable
When your host is unavailable, you get this output:
Attempt to connect: 0
Unable to connect
[Errno 10060] 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
Attempt to connect: 1
Unable to connect
[Errno 10060] 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
Attempt to connect: 2
Unable to connect
[Errno 10060] 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
Once again, three attempts to connect and it shows the reason why our script failed.
Conclusion
You have now learned how you can connect to a device using SSH and Python. Although this works, it might not be the best solution. In this example, I ran the show ip route
command and looked for the default route. This is simple, but what if you want to parse show commands that have a lot of information?
It’s possible to parse the output of show commands like this using regular expressions but it’s a pain. Instead, if possible, it’s better to use a REST API where the device returns the output in JSON format. Parsing JSON in Python is much easier.
I hope you enjoyed this lesson. If you have any questions feel free to leave a comment!
Hi Rene
Fantastic script.
It works on my homelab and on GNS3 too, do you know how make more commands in a single session?
Thanks
Hello Giovanni
In order to implement more commands in a single session, you simply input them in a similar manner in the
# Run command.
section of the script.I hope this has been helpful!
Laz
Hello Giovanni,
This lesson is part of a Python course which I’m currently working on, it’s almost finished. In the course I explain everything, so you’ll know how to write an example like this yourself.
As Lazaros explained, you can add multiple commands at the bottom of the script:
Rene
So it doesn’t seem to work.
It works using more channels like this …
... Continue reading in our forumHi.
... Continue reading in our forumI’m try to make a script to automate some tasks with Fortigate Fw.
When I try the connection , python sollevate this exception.