Saturday, October 3, 2015

Python - Using Paramiko to SSH to routers and switches

In the previous post, I demonstrated how to telnet to a router or a switch ( or any other telnet-able device) using python. But since most of the production network devices uses SSH, I'll be showing how to do that using a library using Paramiko module for Python.

There are many other way to SSH to a router or a switch, one of them is pexpect  but if you're using windows, you'll have to either install cgwin or using Paramiko which has SSH built in right in the module.

Step 1 - Installing Paramiko

There are two way to install Paramiko, the easiest one is using PIP command and this is simple done by opening the command prompt in windows or terminal screen and issuing the following command.

pip install paramiko



Since I already have Paramiko installed, it will just notify me about the needed dependencies and confirm that everything is OK.

One thing though, always make sure that you're connected to the internet directly without being behind a firewall or proxy. I faced many issued not being able to install Paramiko when my PC was behind a proxy.

Step 2 - Using Paramiko in Python

import paramiko
import time
username = 'lab'
password = 'lab123'
IP = '192.168.70.100'
ssh_pre = paramiko.SSHClient()
ssh_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_pre.connect(IP, username=username, password=password)
ssh = ssh_pre.invoke_shell()
ssh.send('show version | no-more \n')
time.sleep(3)
output = ssh.recv(65535)
ssh.close()
print output


Here's the output

--- JUNOS 14.1R1.10 built 2014-06-07 09:37:07 UTC
show version | no-more 
lab@vMX> show version | no-more 
Hostname: vMX
Model: vmx
Junos: 14.1R1.10
JUNOS Base OS Software Suite [14.1R1.10]
JUNOS Base OS boot [14.1R1.10]
JUNOS Crypto Software Suite [14.1R1.10]
JUNOS Online Documentation [14.1R1.10]
JUNOS Kernel Software Suite [14.1R1.10]
JUNOS Packet Forwarding Engine Support (M320) [14.1R1.10]
JUNOS Packet Forwarding Engine Support (M/T/EX Common) [14.1R1.10]
JUNOS Routing Software Suite [14.1R1.10]
JUNOS Runtime Software Suite [14.1R1.10]
JUNOS Services AACL PIC package [14.1R1.10]
JUNOS Services Application Level Gateway [14.1R1.10]
JUNOS Services Application Level Gateway (xlp64) [14.1R1.10]
JUNOS Services Application Level Gateway (xlr64) [14.1R1.10]
JUNOS AppId Services PIC Package [14.1R1.10]
JUNOS Services AppId PIC package (xlr64) [14.1R1.10]
JUNOS Border Gateway Function PIC package [14.1R1.10]
JUNOS Services Captive Portal and Content Delivery PIC package [14.1R1.10]
JUNOS Services HTTP Content Management PIC package [14.1R1.10]
JUNOS Services HTTP Content Management PIC package (xlr64) [14.1R1.10]
JUNOS IDP Services PIC Package [14.1R1.10]
JUNOS Packet Forwarding Engine Trio Simulation Package [14.1R1.10]
JUNOS Services JFLOW PIC package [14.1R1.10]
JUNOS Services JFLOW PIC package (xlp64) [14.1R1.10]
JUNOS Services LL-PDF PIC package [14.1R1.10]
JUNOS MobileNext PIC package [14.1R1.10]
JUNOS MobileNext PIC package (xlr64) [14.1R1.10]
JUNOS Services Mobile Subscriber Service Container package [14.1R1.10]
JUNOS Services Mobile Subscriber Service PIC package (xlr64) [14.1R1.10]
JUNOS Services NAT PIC package [14.1R1.10]
JUNOS Services NAT PIC package (xlp64) [14.1R1.10]
JUNOS Services NAT PIC package (xlr64) [14.1R1.10]
JUNOS Services PTSP PIC package [14.1R1.10]
JUNOS Services RPM PIC package [14.1R1.10]
JUNOS Services RPM PIC package (xlp64) [14.1R1.10]
JUNOS Services Stateful Firewall PIC package [14.1R1.10]
JUNOS Services Stateful Firewall PIC package (xlp64) [14.1R1.10]
JUNOS Services Stateful Firewall PIC package (xlr64) [14.1R1.10]
JUNOS BSG PIC package [14.1R1.10]
JUNOS Services Crypto Base PIC package [14.1R1.10]
JUNOS Services Crypto Base PIC package [14.1R1.10]
JUNOS Services Crypto Base PIC package(xlr64) [14.1R1.10]
JUNOS Services IPSec PIC package [14.1R1.10]
JUNOS Services IPSec PIC package [14.1R1.10]
JUNOS Services IPSec PIC(xlr64) package [14.1R1.10]
JUNOS Services SSL PIC package [14.1R1.10]

lab@vMX> >>> 


as you can see, the script is fairly easy a few lines of code and you're done.

let's take the code line by line


First you import Paramiko module and time module ( which I will explain why in just a moment)
import paramiko 
import time

then you define your variables which are the username, password and the router IP

username = 'lab'password = 'lab123'IP = '192.168.70.100'

Then we made the variable ssh_pre to resemble the SSHClient class in the paramiko module

ssh_pre = paramiko.SSHClient()

now this is why I like paramiko, when ever you first connect to a ssh server, there has to be a key exchange and you have to accept the key in order for the session to be established. What's nice about paramiko is that it can accept whatever the key that is being negotiated with the server automatically. of course from the security prespective this isn't the safest thing to do, but hey, when was the last time you saw someone read the host key?! ;)

ssh_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())

Now we instruct paramiko to connect to the router using the preconfigured usename and password

ssh_pre.connect(IP, username=username, password=password)

The next line is pretty interesting, by default if you're going to use the standard input/out library with paramiko, you'll only be able to send a single line or a command and read it's output. if you need to send another command, you'll have to close the session, reconnect and issue another command. what this command do is give you the ability to send multiple commands and receive the output at once or you can issue a single command and get it's output and another one without closing the session. this is pretty useful since connecting and disconnecting multiple times isn't a really nice thing to do to you're server eh..

so what we did is assign the already configures ssh_pre with the ability to send multiple lines to a new variable called ssh for simplicity

ssh = ssh_pre.invoke_shell()

we now can send a line to the router ( don't forget the \n at the end of the command)

ssh.send('show version | no-more \n')

Then we tell the script to settle down for three seconds using the time module, and the reason we do that is that sometimes the line is very slow and you need to wait for a second before the whole output is printed on the screen. this is how you tell that to a computer otherwise it will send the line and read the buffer in a mere milliseconds while the router is still sending the output.

time.sleep(3)

we assign a variable names output to receive all of the info received by the buffer

output = ssh.recv(65535)

now we close the SSH connection and print the buffer output

ssh.close()
print output


If you found this to be useful for you as a network engineer, please +1 the post and share it to your colleagues. you can also subscribe to my blog via RSS as I'll be posting many scripts that are specifically targeting network engineers