SlideShare a Scribd company logo
Page 1 of 185
1 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
Python Network Programming
by Mihai Cătălin Teodosiu, CCNP, Udemy & GNS3 Academy Instructor
Page 2 of 185
2 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
1. What’s this document all about?
Note: This e-book is a comprehensive guide containing all the applications developed
throughout my Python Network Programming courses: “Python Network Programming
- Part 1: Build 7 Python Apps”, “Python Network Programming - Part 2: Multivendor
Environment” & “Python Network Programming - Part 3: Scapy & Security Tools”.
Note: This document is intended for students enrolled in all three courses and is
distributed for personal use only. The distribution of this material to people not
enrolled in the “Python Network Programming” course series is strictly prohibited
and is subject to copyright infringement. The author of this document is entitled to
invoke legal and technological measures to prevent and penalize copyright infringement.
More information here: https://en.wikipedia.org/wiki/Copyright_infringement
IMPORTANT, BEFORE YOU CONTINUE!
All the code, scripts and applications are explained, turned into working applications and
tested inside the course. For detailed explanations and testing, please see the course
sections referenced by each application below. Pay attention to comments in the code!
Page 3 of 185
3 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2. Python Network Programming - Part 1: Build 7 Python Apps
NOTE! Python programming knowledge is required in order to understand the network
automation applications below. Learn Python from scratch inside the video course series!
2.1. Telnet with Python
(template only, reference: Section 11. Python Networking)
#Open telnet connection to devices
def open_telnet_conn(ip):
#Change exception message
try:
#Define telnet parameters
username = 'teopy'
password = 'python'
TELNET_PORT = 23
TELNET_TIMEOUT = 5
READ_TIMEOUT = 5
#Logging into device
connection = telnetlib.Telnet(ip, TELNET_PORT, TELNET_TIMEOUT)
output = connection.read_until("name:", READ_TIMEOUT)
connection.write(username + "n")
output = connection.read_until("word:", READ_TIMEOUT)
connection.write(password + "n")
time.sleep(1)
#Setting terminal length for entire output - no pagination
connection.write("terminal length 0n")
time.sleep(1)
#Entering global config mode
connection.write("n")
connection.write("configure terminaln")
time.sleep(1)
#Open user selected file for reading
selected_cmd_file = open(cmd_file, 'r')
#Starting from the beginning of the file
selected_cmd_file.seek(0)
#Writing each line in the file to the device
for each_line in selected_cmd_file.readlines():
connection.write(each_line + 'n')
time.sleep(1)
Page 4 of 185
4 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Closing the file
selected_cmd_file.close()
#Test for reading command output
#output = connection.read_very_eager()
#print output
#Closing the connection
connection.close()
except IOError:
print "Input parameter error! Please check username, password and
file name."
#Calling the Telnet function
open_telnet_conn(ip)
Page 5 of 185
5 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.2. SSH with Python
(template only, reference: Section 11. Python Networking)
#Open SSHv2 connection to devices
def open_ssh_conn(ip):
#Change exception message
try:
#Define SSH parameters
selected_user_file = open(user_file, 'r')
#Starting from the beginning of the file
selected_user_file.seek(0)
username = selected_user_file.readlines()[0].split(',')[0]
#Starting from the beginning of the file
selected_user_file.seek(0)
password = selected_user_file.readlines()[0].split(',')[1]
#Logging into device
session = paramiko.SSHClient()
session.set_missing_host_key_policy(
paramiko.AutoAddPolicy())
session.connect(ip, username = username, password = password)
connection = session.invoke_shell()
#Setting terminal length for entire output - no pagination
connection.send("terminal length 0n")
time.sleep(1)
#Entering global config mode
connection.send("n")
connection.send("configure terminaln")
time.sleep(1)
#Open user selected file for reading
selected_cmd_file = open(cmd_file, 'r')
#Starting from the beginning of the file
selected_cmd_file.seek(0)
#Writing each line in the file to the device
for each_line in selected_cmd_file.readlines():
connection.send(each_line + 'n')
time.sleep(2)
Page 6 of 185
6 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Closing the user file
selected_user_file.close()
#Closing the command file
selected_cmd_file.close()
#Checking command output for IOS syntax errors
output = connection.recv(65535)
if re.search(r"% Invalid input detected at", output):
print "* There was at least one IOS syntax error on device %s"
% ip
else:
print "nDONE for device %s" % ip
#Test for reading command output
#print output + "n"
#Closing the connection
session.close()
except paramiko.AuthenticationException:
print "* Invalid username or password. n* Please check the
username/password file or the device configuration!"
print "* Closing program...n"
#Calling the SSH function
open_ssh_conn(ip)
Page 7 of 185
7 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.3. SNMP with Python
(template only, reference: Section 11. Python Networking)
#!/usr/bin/env python
from pysnmp.entity.rfc3413.oneliner import cmdgen
#SNMP function
def snmp_get(ip):
#Creating command generator object
cmdGen = cmdgen.CommandGenerator()
#Performing SNMP GETNEXT operations on the OSPF OIDs
#The basic syntax of nextCmd: nextCmd(authData, transportTarget,
*varNames)
#The nextCmd method returns a tuple of (errorIndication, errorStatus,
errorIndex, varBindTable)
errorIndication, errorStatus, errorIndex, varBindNbrTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.2.1.14.10.1.3')
#print
cmdGen.nextCmd(cmdgen.CommunityData(comm),cmdgen.UdpTransportTarget((ip,
161)),'1.3.6.1.2.1.14.10.1.3')
#print varBindNbrTable
errorIndication, errorStatus, errorIndex, varBindNbrIpTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.2.1.14.10.1.1')
#print varBindNbrIpTable
errorIndication, errorStatus, errorIndex, varBindHostTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.4.1.9.2.1.3')
#print varBindHostTable
Page 8 of 185
8 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
errorIndication, errorStatus, errorIndex, varBindHostIdTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.2.1.14.1.1')
#print varBindHostIdTable
Page 9 of 185
9 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.4. Application #1 - Basic subnet calculator
(full code, reference: Section 13. Application #1 - Basic subnet calculator)
Logical flow diagram
Page 10 of 185
10 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
############# Application #1 - Part #1 #############
import random
import sys
def subnet_calc():
try:
print "n"
#Checking IP address validity
while True:
ip_address = raw_input("Enter an IP address: ")
#Checking octets
a = ip_address.split('.')
if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) !=
127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255
and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255):
break
else:
print "nThe IP address is INVALID! Please retry!n"
continue
masks = [255, 254, 252, 248, 240, 224, 192, 128, 0]
#Checking Subnet Mask validity
while True:
subnet_mask = raw_input("Enter a subnet mask: ")
#Checking octets
b = subnet_mask.split('.')
if (len(b) == 4) and (int(b[0]) == 255) and (int(b[1]) in
masks) and (int(b[2]) in masks) and (int(b[3]) in masks) and (int(b[0]) >=
int(b[1]) >= int(b[2]) >= int(b[3])):
break
else:
print "nThe subnet mask is INVALID! Please retry!n"
continue
############# Application #1 - Part #2 #############
#Algorithm for subnet identification, based on IP and Subnet Mask
#Convert mask to binary string
mask_octets_padded = []
mask_octets_decimal = subnet_mask.split(".")
#print mask_octets_decimal
for octet_index in range(0, len(mask_octets_decimal)):
Page 11 of 185
11 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#print bin(int(mask_octets_decimal[octet_index]))
binary_octet =
bin(int(mask_octets_decimal[octet_index])).split("b")[1]
#print binary_octet
if len(binary_octet) == 8:
mask_octets_padded.append(binary_octet)
elif len(binary_octet) < 8:
binary_octet_padded = binary_octet.zfill(8)
mask_octets_padded.append(binary_octet_padded)
#print mask_octets_padded
decimal_mask = "".join(mask_octets_padded)
#print decimal_mask #Example: for 255.255.255.0 =>
11111111111111111111111100000000
#Counting host bits in the mask and calculating number of
hosts/subnet
no_of_zeros = decimal_mask.count("0")
no_of_ones = 32 - no_of_zeros
no_of_hosts = abs(2 ** no_of_zeros - 2) #return positive value for
mask /32
#print no_of_zeros
#print no_of_ones
#print no_of_hosts
#Obtaining wildcard mask
wildcard_octets = []
for w_octet in mask_octets_decimal:
wild_octet = 255 - int(w_octet)
wildcard_octets.append(str(wild_octet))
#print wildcard_octets
wildcard_mask = ".".join(wildcard_octets)
#print wildcard_mask
############# Application #1 - Part #3 #############
#Convert IP to binary string
ip_octets_padded = []
ip_octets_decimal = ip_address.split(".")
for octet_index in range(0, len(ip_octets_decimal)):
binary_octet =
bin(int(ip_octets_decimal[octet_index])).split("b")[1]
if len(binary_octet) < 8:
binary_octet_padded = binary_octet.zfill(8)
Page 12 of 185
12 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
ip_octets_padded.append(binary_octet_padded)
else:
ip_octets_padded.append(binary_octet)
#print ip_octets_padded
binary_ip = "".join(ip_octets_padded)
#print binary_ip #Example: for 192.168.2.100 =>
11000000101010000000001001100100
#Obtain the network address and broadcast address from the binary
strings obtained above
network_address_binary = binary_ip[:(no_of_ones)] + "0" *
no_of_zeros
#print network_address_binary
broadcast_address_binary = binary_ip[:(no_of_ones)] + "1" *
no_of_zeros
#print broadcast_address_binary
net_ip_octets = []
for octet in range(0, len(network_address_binary), 8):
net_ip_octet = network_address_binary[octet:octet+8]
net_ip_octets.append(net_ip_octet)
#print net_ip_octets
net_ip_address = []
for each_octet in net_ip_octets:
net_ip_address.append(str(int(each_octet, 2)))
#print net_ip_address
network_address = ".".join(net_ip_address)
#print network_address
bst_ip_octets = []
for octet in range(0, len(broadcast_address_binary), 8):
bst_ip_octet = broadcast_address_binary[octet:octet+8]
bst_ip_octets.append(bst_ip_octet)
#print bst_ip_octets
bst_ip_address = []
for each_octet in bst_ip_octets:
bst_ip_address.append(str(int(each_octet, 2)))
#print bst_ip_address
broadcast_address = ".".join(bst_ip_address)
#print broadcast_address
Page 13 of 185
13 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Results for selected IP/mask
print "n"
print "Network address is: %s" % network_address
print "Broadcast address is: %s" % broadcast_address
print "Number of valid hosts per subnet: %s" % no_of_hosts
print "Wildcard mask: %s" % wildcard_mask
print "Mask bits: %s" % no_of_ones
print "n"
############# Application #1 - Part #4 #############
#Generation of random IP in subnet
while True:
generate = raw_input("Generate random ip address from subnet?
(y/n)")
if generate == "y":
generated_ip = []
#Obtain available IP address in range, based on the
difference between octets in broadcast address and network address
for indexb, oct_bst in enumerate(bst_ip_address):
#print indexb, oct_bst
for indexn, oct_net in enumerate(net_ip_address):
#print indexn, oct_net
if indexb == indexn:
if oct_bst == oct_net:
#Add identical octets to the generated_ip
list
generated_ip.append(oct_bst)
else:
#Generate random number(s) from within
octet intervals and append to the list
generated_ip.append(str(random.randint(int(oct_net), int(oct_bst))))
#IP address generated from the subnet pool
#print generated_ip
y_iaddr = ".".join(generated_ip)
#print y_iaddr
print "Random IP address is: %s" % y_iaddr
print "n"
continue
else:
print "Ok, bye!n"
break
except KeyboardInterrupt:
print "nnProgram aborted by user. Exiting...n"
sys.exit()
Page 14 of 185
14 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Calling the function
subnet_calc()
Page 15 of 185
15 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.5. Application #2 – SSH/Telnet network configuration
(full code, reference: Section 14. Application #2 – SSH/Telnet network
configuration)
Logical flow diagram
Page 16 of 185
16 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.5.1. SSH network configuration
############# Application #2 - Part #1 #############
import paramiko
import threading
import os.path
import subprocess
import time
import sys
import re
#Checking IP address file and content validity
def ip_is_valid():
check = False
global ip_list
while True:
#Prompting user for input
print "n# # # # # # # # # # # # # # # # # # # # # # # # # # #
#n"
ip_file = raw_input("# Enter IP file name and extension: ")
print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #"
#Changing exception message
try:
#Open user selected file for reading (IP addresses file)
selected_ip_file = open(ip_file, 'r')
#Starting from the beginning of the file
selected_ip_file.seek(0)
#Reading each line (IP address) in the file
ip_list = selected_ip_file.readlines()
#Closing the file
selected_ip_file.close()
except IOError:
print "n* File %s does not exist! Please check and try
again!n" % ip_file
#Checking octets
for ip in ip_list:
a = ip.split('.')
if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) !=
127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255
and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255):
check = True
Page 17 of 185
17 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
break
else:
print 'n* There was an INVALID IP address! Please check
and try again!n'
check = False
continue
#Evaluating the 'check' flag
if check == False:
continue
elif check == True:
break
############# Application #2 - Part #2 #############
#Checking IP reachability
print "n* Checking IP reachability. Please wait...n"
check2 = False
while True:
for ip in ip_list:
ping_reply = subprocess.call(['ping', '-c', '2', '-w', '2', '-
q', '-n', ip])
if ping_reply == 0:
check2 = True
continue
elif ping_reply == 2:
print "n* No response from device %s." % ip
check2 = False
break
else:
print "n* Ping to the following device has FAILED:", ip
check2 = False
break
#Evaluating the 'check' flag
if check2 == False:
print "* Please re-check IP address list or device.n"
ip_is_valid()
elif check2 == True:
print 'n* All devices are reachable. Waiting for
username/password file...n'
break
#Checking user file validity
def user_is_valid():
global user_file
Page 18 of 185
18 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
while True:
print "# # # # # # # # # # # # # # # # # # # # # # # # # # # #n"
user_file = raw_input("# Enter user/pass file name and extension:
")
print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #"
#Changing output messages
if os.path.isfile(user_file) == True:
print "n* Username/password file has been validated. Waiting
for command file...n"
break
else:
print "n* File %s does not exist! Please check and try
again!n" % user_file
continue
#Checking command file validity
def cmd_is_valid():
global cmd_file
while True:
print "nn# # # # # # # # # # # # # # # # # # # # # # # # # # #
#n"
cmd_file = raw_input("# Enter command file name and extension: ")
print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #"
#Changing output messages
if os.path.isfile(cmd_file) == True:
print "n* Sending command(s) to device(s)...n"
break
else:
print "n* File %s does not exist! Please check and try
again!n" % cmd_file
continue
#Change exception message
try:
#Calling IP validity function
ip_is_valid()
except KeyboardInterrupt:
print "nn* Program aborted by user. Exiting...n"
sys.exit()
#Change exception message
try:
#Calling user file validity function
user_is_valid()
except KeyboardInterrupt:
print "nn* Program aborted by user. Exiting...n"
Page 19 of 185
19 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
sys.exit()
#Change exception message
try:
#Calling command file validity function
cmd_is_valid()
except KeyboardInterrupt:
print "nn* Program aborted by user. Exiting...n"
sys.exit()
############# Application #2 - Part #3 #############
#Open SSHv2 connection to devices
def open_ssh_conn(ip):
#Change exception message
try:
#Define SSH parameters
selected_user_file = open(user_file, 'r')
#Starting from the beginning of the file
selected_user_file.seek(0)
#Reading the username from the file
username = selected_user_file.readlines()[0].split(',')[0]
#Starting from the beginning of the file
selected_user_file.seek(0)
#Reading the password from the file
password =
selected_user_file.readlines()[0].split(',')[1].rstrip("n")
#Logging into device
session = paramiko.SSHClient()
#For testing purposes, this allows auto-accepting unknown host
keys
#Do not use in production! The default would be RejectPolicy
session.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#Connect to the device using username and password
session.connect(ip, username = username, password = password)
#Start an interactive shell session on the router
connection = session.invoke_shell()
#Setting terminal length for entire output - disable pagination
connection.send("terminal length 0n")
time.sleep(1)
#Entering global config mode
connection.send("n")
connection.send("configure terminaln")
Page 20 of 185
20 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
time.sleep(1)
#Open user selected file for reading
selected_cmd_file = open(cmd_file, 'r')
#Starting from the beginning of the file
selected_cmd_file.seek(0)
#Writing each line in the file to the device
for each_line in selected_cmd_file.readlines():
connection.send(each_line + 'n')
time.sleep(2)
#Closing the user file
selected_user_file.close()
#Closing the command file
selected_cmd_file.close()
#Checking command output for IOS syntax errors
router_output = connection.recv(65535)
if re.search(r"% Invalid input detected at", router_output):
print "* There was at least one IOS syntax error on device %s"
% ip
else:
print "nDONE for device %s" % ip
#Test for reading command output
#print router_output + "n"
#Closing the connection
session.close()
except paramiko.AuthenticationException:
print "* Invalid username or password. n* Please check the
username/password file or the device configuration!"
print "* Closing program...n"
############# Application #2 - Part #4 #############
#Creating threads
def create_threads():
threads = []
for ip in ip_list:
th = threading.Thread(target = open_ssh_conn, args = (ip,))
#args is a tuple with a single element
th.start()
threads.append(th)
for th in threads:
th.join()
Page 21 of 185
21 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Calling threads creation function
create_threads()
#End of program
Page 22 of 185
22 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.5.2. Telnet network configuration
#!/usr/bin/env python
import telnetlib
import threading
import os.path
import subprocess
import time
import sys
#Checking IP address validity
def ip_is_valid():
check = False
global ip_list
while True:
#Prompting user for input
ip_file = raw_input("Enter IP file name and extension: ")
#Changing exception message
try:
#Open user selected file for reading (IP addresses file)
selected_ip_file = open(ip_file, 'r')
#Starting from the beginning of the file
selected_ip_file.seek(0)
#Reading each line (IP address) in the file
ip_list = selected_ip_file.readlines()
#Closing the file
selected_ip_file.close()
except IOError:
print "nFile %s does not exist! Please check and try
again!n" % ip_file
#Checking octets
for ip in ip_list:
a = ip.split('.')
if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) !=
127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255
and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255):
check = True
break
else:
Page 23 of 185
23 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
print 'n* There was an INVALID IP address! Please check
and try again!n'
check = False
continue
#Evaluating the 'check' flag
if check == False:
continue
elif check == True:
break
#Checking IP reachability
print "nChecking IP reachability...n"
check2 = False
while True:
for ip in ip_list:
ping_reply = subprocess.call(['ping', '-c', '3', '-w', '3', '-
q', '-n', ip])
if ping_reply == 0:
check2 = True
continue
elif ping_reply == 2:
print "nNo response from device %s." % ip
check2 = False
break
else:
print "nPing to the following device has FAILED:", ip
check2 = False
break
#Evaluating the 'check' flag
if check2 == False:
print "Please re-check IP address list or device.n"
ip_is_valid()
elif check2 == True:
print 'nAll devices are reachable. Waiting for command
file...n'
break
#Checking command file validity
def cmd_is_valid():
global cmd_file
while True:
cmd_file = raw_input("Enter command file name and extension: ")
#Changing exception message
Page 24 of 185
24 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
if os.path.isfile(cmd_file) == True:
print "nSending command(s) to device(s)...n"
break
else:
print "nFile %s does not exist! Please check and try
again!n" % cmd_file
continue
#Change exception message
try:
#Calling IP validity function
ip_is_valid()
except KeyboardInterrupt:
print "nnProgram aborted by user. Exiting...n"
sys.exit()
#Change exception message
try:
#Calling command file validity function
cmd_is_valid()
except KeyboardInterrupt:
print "nnProgram aborted by user. Exiting...n"
sys.exit()
#Open telnet connection to devices
def open_telnet_conn(ip):
#Change exception message
try:
#Define telnet parameters
username = 'teopy'
password = 'python'
#Specify the Telnet port (default is 23, anyway)
port = 23
#Specify the connection timeout in seconds for blocking
operations, like the connection attempt
connection_timeout = 5
#Specify a timeout in seconds. Read until the string is found or
until the timout has passed
reading_timeout = 5
#Logging into device
connection = telnetlib.Telnet(ip, port, connection_timeout)
#Waiting to be asked for an username
router_output = connection.read_until("Username:",
reading_timeout)
#Enter the username when asked and a "n" for Enter
Page 25 of 185
25 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
connection.write(username + "n")
#Waiting to be asked for a password
router_output = connection.read_until("Password:",
reading_timeout)
#Enter the password when asked and a "n" for Enter
connection.write(password + "n")
time.sleep(1)
#Setting terminal length for the entire output - disabling
pagination
connection.write("terminal length 0n")
time.sleep(1)
#Entering global config mode
connection.write("n")
connection.write("configure terminaln")
time.sleep(1)
#Open user selected file for reading
selected_cmd_file = open(cmd_file, 'r')
#Starting from the beginning of the file
selected_cmd_file.seek(0)
#Writing each line in the file to the device
for each_line in selected_cmd_file.readlines():
connection.write(each_line + 'n')
time.sleep(1)
#Closing the file
selected_cmd_file.close()
#Test for reading command output
#router_output = connection.read_very_eager()
#print router_output
#Closing the connection
connection.close()
except IOError:
print "Input parameter error! Please check username, password and
file name."
#Creating threads
def create_threads():
threads = []
for ip in ip_list:
th = threading.Thread(target = open_telnet_conn, args = (ip,))
#args is a tuple with a single element
th.start()
threads.append(th)
Page 26 of 185
26 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
for th in threads:
th.join()
#Calling threads creation function
create_threads()
#End of program
Page 27 of 185
27 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.6. Application #3 - DHCP client simulator
(full code, reference: Section 15. Application #3 - DHCP client simulator)
Logical flow diagram
Page 28 of 185
28 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
############# Application #3 - Part #1 #############
#DHCP client simulator
#In scapy interactive mode - DHCP packets:
'''
'Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP'
DHCP DISCOVER:
'Ether(src='08:00:27:f9:51:87', dst='ff:ff:ff:ff:ff:ff',
type=2048)/IP(frag=0L, src='0.0.0.0', proto=17, tos=16,
dst='255.255.255.255', chksum=14742, len=328, options=[], version=4L,
flags=0L, ihl=5L, ttl=128, id=0)/UDP(dport=67, sport=68, len=308,
chksum=47898)/BOOTP(hlen=6,
sname='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0',
hops=0, giaddr='0.0.0.0',
chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x
00x00", yiaddr='0.0.0.0', secs=0, flags=0L, htype=1,
file='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00',
siaddr='0.0.0.0', options='cx82Sc', op=1)/DHCP(options=[('message-
type', 1), ('hostname', 'kali-teo'), ('param_req_list',
'x01x1cx02x03x0fx06wx0c,/x1ay*'), 'end', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad'])'
DHCP OFFER:
'Ether(src='c0:04:1a:5c:00:01', dst='08:00:27:f9:51:87',
type=2048)/IP(frag=0L, src='192.168.2.111', proto=17, tos=0,
dst='192.168.2.1', chksum=13540, len=328, options=[], version=4L,
flags=0L, ihl=5L, ttl=255, id=0)/UDP(dport=68, sport=67, len=308,
chksum=19350)/BOOTP(hlen=6,
sname='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0',
hops=0, giaddr='0.0.0.0',
chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x
00x00", yiaddr='192.168.2.1', secs=0, flags=0L, htype=1,
file='x00x00x00x00x00x00x00x00x00x00x00x00x00
Page 29 of 185
29 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00',
siaddr='0.0.0.0', options='cx82Sc', op=2)/DHCP(options=[('message-
type', 2), ('server_id', '192.168.2.111'), ('lease_time', 86400),
('renewal_time', 43200), ('rebinding_time', 75600), ('subnet_mask',
'255.255.255.0'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad'])'
DHCP OFFER (more options):
'Ether(src='ca:04:15:ec:00:08', dst='00:00:5e:4a:a3:fe',
type=2048)/IP(frag=0L, src='192.168.2.111', proto=17, tos=0,
dst='192.168.2.236', chksum=9573, len=328, options=[], version=4L,
flags=0L, ihl=5L, ttl=255, id=3732)/UDP(dport=68, sport=67, len=308,
chksum=3558)/BOOTP(hlen=6,
sname='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00', xid=868370, ciaddr='0.0.0.0', hops=0,
giaddr='0.0.0.0',
chaddr='x00x00^Jxa3xfex00x00x00x00x00x00x00x00x0
0x00', yiaddr='192.168.2.236', secs=0, flags=0L, htype=1,
file='x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00', siaddr='0.0.0.0',
options='cx82Sc', op=2)/DHCP(options=[('message-type', 2), ('server_id',
'192.168.2.111'), ('lease_time', 86400), ('renewal_time', 43200),
('rebinding_time', 75600), ('subnet_mask', '255.255.255.0'), ('router',
'192.168.2.254'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad'])'
DHCP REQUEST:
'Ether(src='08:00:27:f9:51:87', dst='ff:ff:ff:ff:ff:ff',
type=2048)/IP(frag=0L, src='0.0.0.0', proto=17, tos=16,
dst='255.255.255.255', chksum=14742, len=328, options=[], version=4L,
flags=0L, ihl=5L, ttl=128, id=0)/UDP(dport=67, sport=68, len=308,
chksum=61228)/BOOTP(hlen=6,
sname='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
Page 30 of 185
30 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0',
hops=0, giaddr='0.0.0.0',
chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x
00x00", yiaddr='0.0.0.0', secs=0, flags=0L, htype=1,
file='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00',
siaddr='0.0.0.0', options='cx82Sc', op=1)/DHCP(options=[('message-
type', 3), ('server_id', '192.168.2.111'), ('requested_addr',
'192.168.2.1'), ('hostname', 'kali-teo'), ('param_req_list',
'x01x1cx02x03x0fx06wx0c,/x1ay*'), 'end', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad'])'
DHCP ACK:
'Ether(src='c0:04:1a:5c:00:01', dst='08:00:27:f9:51:87',
type=2048)/IP(frag=0L, src='192.168.2.111', proto=17, tos=0,
dst='192.168.2.1', chksum=13539, len=328, options=[], version=4L,
flags=0L, ihl=5L, ttl=255, id=1)/UDP(dport=68, sport=67, len=308,
chksum=18582)/BOOTP(hlen=6,
sname='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0',
hops=0, giaddr='0.0.0.0',
chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x
00x00", yiaddr='192.168.2.1', secs=0, flags=0L, htype=1,
file='x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0
0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00',
siaddr='0.0.0.0', options='cx82Sc', op=2)/DHCP(options=[('message-
type', 5), ('server_id', '192.168.2.111'), ('lease_time', 86400),
('renewal_time', 43200), ('rebinding_time', 75600), ('subnet_mask',
'255.255.255.0'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad',
'pad', 'pad', 'pad', 'pad', 'pad'])'
'''
Page 31 of 185
31 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
import subprocess
import logging
import random
import sys
#This will suppress all messages that have a lower level of seriousness
than error messages, while running or loading Scapy
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
logging.getLogger("scapy.interactive").setLevel(logging.ERROR)
logging.getLogger("scapy.loading").setLevel(logging.ERROR)
try:
from scapy.all import *
except ImportError:
print "Scapy package for Python is not installed on your system."
print "Get it from https://pypi.python.org/pypi/scapy and try again."
sys.exit()
#To see a list of what commands Scapy has available, run the lsc()
function.
#Run the ls() command to see ALL the supported protocols.
#Run the ls(protocol) command to see the fields and default values for any
protocol.
#See packet layers with the .summary() function.
#See packet contents with the .show() function.
#Dig into a specific packet layer using a list index:
pkts[3][2].summary()...
#...the first index chooses the packet out of the pkts list, the second
index chooses the layer for that specific packet.
#Using the .command() packet method will return a string of the command
necessary to recreate that sniffed packet.
print "n! Make sure to run this program as ROOT !n"
#Setting network interface in promiscuous mode
net_iface = raw_input("Enter the interface to the target network: ")
subprocess.call(["ifconfig", net_iface, "promisc"], stdout=None,
stderr=None, shell=False)
print "nInterface %s was set to PROMISC mode." % net_iface
Page 32 of 185
32 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Scapy normally makes sure that replies come from the same IP address the
stimulus was sent to.
#But our DHCP packet is sent to the IP broadcast address (255.255.255.255)
and any answer packet will have the IP address of the replying DHCP server
as its source IP address (e.g. 192.168.2.101).
#Because these IP addresses don't match, we have to disable Scapy's check
with conf.checkIPaddr = False before sending the stimulus.
#Source:
https://bitbucket.org/pbi/test/wiki/doc/IdentifyingRogueDHCPServers
conf.checkIPaddr = False
############# Application #3 - Part #2 #############
################## DHCP SEQUENCE #################
all_given_leases = []
server_id = []
client_mac = []
#Generate entire DHCP sequence
def generate_dhcp_seq():
global all_given_leases
#Defining some DHCP parameters
x_id = random.randrange(1, 1000000)
hw = "00:00:5e" + str(RandMAC())[8:]
hw_str = mac2str(hw)
#print hw
#Assigning the .command() output of a captured DHCP DISCOVER packet to
a variable
dhcp_dis_pkt = Ether(dst="ff:ff:ff:ff:ff:ff",
src=hw)/IP(src="0.0.0.0",dst="255.255.255.255") /
UDP(sport=68,dport=67)/BOOTP(op=1, xid=x_id,
chaddr=hw_str)/DHCP(options=[("message-type","discover"),("end")])
#Sending the DISCOVER packet and catching the OFFER reply
#Generates two lists (answ and unansw). answd is a list containg a
tuple: the first element is the DISCOVER packet, the second is the OFFER
packet
answd, unanswd = srp(dhcp_dis_pkt, iface=pkt_inf, timeout = 2.5,
verbose=0)
#print answd
#print unanswd
#print answd.summary()
#print unanswd.summary()
#print answd[0][1][BOOTP].yiaddr
#The IP offered by the DHCP server to the client is extracted from the
received answer
offered_ip = answd[0][1][BOOTP].yiaddr
#print offered_ip
Page 33 of 185
33 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Assigning the .command() output of a captured DHCP REQUEST packet to
a variable
dhcp_req_pkt = Ether(dst="ff:ff:ff:ff:ff:ff",
src=hw)/IP(src="0.0.0.0",dst="255.255.255.255") /
UDP(sport=68,dport=67)/BOOTP(op=1, xid=x_id,
chaddr=hw_str)/DHCP(options=[("message-type","request"),("requested_addr",
offered_ip),("end")])
#Sending the REQUEST for the offered IP address
#Capturing the ACK from the server
answr, unanswr = srp(dhcp_req_pkt, iface=pkt_inf, timeout = 2.5,
verbose=0)
#print answr
#print unanswr
#print answr[0][1][IP].src
#print answr[0][1][BOOTP].yiaddr
#The IP offered by the DHCP server to the client is extracted from the
received answer
offered_ip_ack = answr[0][1][BOOTP].yiaddr
#DHCP Server IP/ID
server_ip = answr[0][1][IP].src
#print server_ip
#Adding each leased IP to the list of leases
all_given_leases.append(offered_ip_ack)
#Adding the server IP to a list
server_id.append(server_ip)
client_mac.append(hw)
return all_given_leases, server_id, client_mac
############# Application #3 - Part #3 #############
################## DHCP RELEASE #################
def generate_dhcp_release(ip, hw, server):
#Defining DHCP Transaction ID
x_id = random.randrange(1, 1000000)
hw_str = mac2str(hw)
#Creating the RELEASE packet
dhcp_rls_pkt = IP(src=ip,dst=server) /
UDP(sport=68,dport=67)/BOOTP(chaddr=hw_str, ciaddr=ip,
xid=x_id)/DHCP(options=[("message-type","release"),("server_id",
server),("end")])
Page 34 of 185
34 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Sending the RELEASE packet
send(dhcp_rls_pkt, verbose=0)
############# Application #3 - Part #4 #############
################## USER MENU #################
try:
#Enter option for the first screen
while True:
print "nUse this tool to:ns - Simulate DHCP Clientsnr -
Simulate DHCP Releasene - Exit programn"
user_option_sim = raw_input("Enter your choice: ")
if user_option_sim == "s":
print "nObtained leases will be exported to
'DHCP_Leases.txt'!"
pkt_no = raw_input("nNumber of DHCP clients to simulate: ")
pkt_inf = raw_input("Interface on which to send packets: ")
print "nWaiting for clients to obtain IP addresses...n"
try:
#Calling the function for the required number of times
(pkt_no)
for iterate in range(0, int(pkt_no)):
all_leased_ips = generate_dhcp_seq()[0]
#print all_leased_ips
except IndexError:
print "No DHCP Server detected or connection is broken."
print "Check your network settings and try again.n"
sys.exit()
#List of all leased IPs
dhcp_leases = open("DHCP_Leases.txt", "w")
#print all_leased_ips
#print server_id
#print client_mac
#Print each leased IP to the file
for index, each_ip in enumerate(all_leased_ips):
print >>dhcp_leases, each_ip + "," + server_id[index] +
"," + client_mac[index]
dhcp_leases.close()
Page 35 of 185
35 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
continue
elif user_option_sim == "r":
while True:
print "ns - Release a single addressna - Release all
addressesne - Exit to the previous screenn"
user_option_release = raw_input("Enter your choice: ")
if user_option_release == "s":
print "n"
user_option_address = raw_input("Enter IP address to
release: ")
#print all_leased_ips
#print server_id
#print client_mac
try:
#Check if required IP is in the list and run the
release function for it
if user_option_address in all_leased_ips:
index =
all_leased_ips.index(user_option_address)
generate_dhcp_release(user_option_address,
client_mac[index], server_id[index])
print "nSending RELEASE packet...n"
else:
print "IP Address not in list.n"
continue
except (NameError, IndexError):
print "nSimulating DHCP RELEASES cannot be done
separately, without prior DHCP Client simulation."
print "Restart the program and simulate DHCP
Clients and RELEASES in the same program session.n"
sys.exit()
elif user_option_release == "a":
#print all_leased_ips
#print server_id
#print client_mac
try:
#Check if required IP is in the list and run the
release function for it
for user_option_address in all_leased_ips:
Page 36 of 185
36 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
index =
all_leased_ips.index(user_option_address)
generate_dhcp_release(user_option_address,
client_mac[index], server_id[index])
except (NameError, IndexError):
print "nSimulating DHCP RELEASES cannot be done
separately, without prior DHCP Client simulation."
print "Restart the program and simulate DHCP
Clients and RELEASES in the same program session.n"
sys.exit()
print "nThe RELEASE packets have been sent.n"
#Erasing all leases from the file
open("DHCP_Leases.txt", "w").close()
print "File 'DHCP_Leases.txt' has been cleared."
continue
else:
break
else:
print "Exiting... See ya...nn"
sys.exit()
except KeyboardInterrupt:
print "nnProgram aborted by user. Exiting...n"
sys.exit()
#End of program
Page 37 of 185
37 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.7. Application #4 - Network parameters extraction
(full code, reference: Section 16. Application #4 - Network parameters extraction)
Logical flow diagram
Page 38 of 185
38 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
############# Application #4 - Part #1 #############
#Configure the permissions on the script first! 'chmod 755 script.py"
#Make sure to have SSHv2 enabled and RSA 1024 bit key generated on every
device!
import MySQLdb as mdb
import paramiko
import threading
import os.path
import subprocess
import datetime
import time
import sys
import re
#Module for output coloring
from colorama import init, deinit, Fore, Style
# Procedure for configuring Linux scheduler:
# root@kali:/# crontab -l view scheduled tasks
# root@kali:/# crontab -e edit scheduler
# Add the following line to run the script every 5 minutes, every hour,
every day, every month:
# */5 * * * * /path_to_file/NetMon_SQL_v1.py /path_to_file/NETWORK_IP
/path_to_file/SSH_USERPASS.txt /path_to_file/SQL_CONN.txt
# For more info about configuring scheduler:
http://kvz.io/blog/2007/07/29/schedule-tasks-on-linux-using-crontab/
# Before scheduling this task, run the script in the console to check for
errors:
# Go to the folder containing the script and all files, using cd
/netmon_folder_path
# Enter this command: python NetMon_SQL_v1.py NETWORK_IP.txt
SSH_USERPASS.txt SQL_CONN.txt
# Check the console output and SQL_Error_Log.txt file for any errors.
# Running the script is recommended at intervals of at least 5 minutes.
#Initialize colorama
init()
#Checking number of arguments passed into the script
if len(sys.argv) == 4:
ip_file = sys.argv[1]
user_file = sys.argv[2]
sql_file = sys.argv[3]
print Fore.BLUE + Style.BRIGHT + "nn* The script will be executed
using files:n"
print Fore.BLUE + "Cisco network IP file is: " + Fore.YELLOW + "%s" %
ip_file
Page 39 of 185
39 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
print Fore.BLUE + "SSHv2 connection file is: " + Fore.YELLOW + "%s" %
user_file
print Fore.BLUE + "MySQL connection file is: " + Fore.YELLOW + "%s" %
sql_file
print Fore.BLUE + Style.BRIGHT + "n"
else:
print Fore.RED + Style.BRIGHT + "nIncorrect number of arguments
(files) passed into the script."
print Fore.RED + "Please try again.n"
sys.exit()
#Checking IP address file and content validity
def ip_is_valid():
check = False
global ip_list
while True:
#Changing exception message
try:
#Open user selected file for reading (IP addresses file)
selected_ip_file = open(ip_file, 'r')
#Starting from the beginning of the file
selected_ip_file.seek(0)
#Reading each line (IP address) in the file
ip_list = selected_ip_file.readlines()
#Closing the file
selected_ip_file.close()
except IOError:
print Fore.RED + "n* File %s does not exist! Please check and
try again!n" % ip_file
sys.exit()
#Checking octets
for ip in ip_list:
a = ip.split('.')
if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) !=
127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255
and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255):
check = True
break
else:
print 'n* There was an INVALID IP address! Please check
and try again!n'
check = False
continue
Page 40 of 185
40 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Evaluating the 'check' flag
if check == False:
sys.exit()
elif check == True:
break
#Checking IP reachability
print "* Checking IP reachability... Please wait...n"
check2 = False
while True:
for ip in ip_list:
ping_reply = subprocess.call(['ping', '-c', '3', '-w', '3', '-
q', '-n', ip], stdout = subprocess.PIPE)
if ping_reply == 0:
check2 = True
continue
elif ping_reply == 2:
print Fore.RED + "n* No response from device %s." % ip
check2 = False
break
else:
print Fore.RED + "n* Ping to the following device has
FAILED:", ip
check2 = False
break
#Evaluating the 'check' flag
if check2 == False:
print Fore.RED + "* Please re-check IP address list or
device.n"
sys.exit()
elif check2 == True:
print 'n* All devices are reachable. Checking SSHv2
connection file...n'
break
#Checking user file validity
def user_is_valid():
global user_file
while True:
#Changing output messages
if os.path.isfile(user_file) == True:
print "n* SSHv2 connection file has been validated. Checking
MySQL connection file...n"
break
Page 41 of 185
41 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
else:
print Fore.RED + "n* File %s does not exist! Please check and
try again!n" % user_file
sys.exit()
#Checking SQL connection command file validity
def sql_is_valid():
global sql_file
while True:
#Changing output messages
if os.path.isfile(sql_file) == True:
print "n* MySQL connection file has been validated...n"
print "n* Any MySQL errors will be logged to: " + Fore.YELLOW
+ "SQL_Error_Log.txtn" + Fore.BLUE
print "n* Reading network data and writing to MySQL...n"
break
else:
print Fore.RED + "n* File %s does not exist! Please check and
try again!n" % sql_file
sys.exit()
#Change exception message
try:
#Calling IP validity function
ip_is_valid()
except KeyboardInterrupt:
print Fore.RED + "nn* Program aborted by user. Exiting...n"
sys.exit()
#Change exception message
try:
#Calling user file validity function
user_is_valid()
except KeyboardInterrupt:
print Fore.RED + "nn* Program aborted by user. Exiting...n"
sys.exit()
#Change exception message
try:
#Calling MySQL file validity function
sql_is_valid()
except KeyboardInterrupt:
print Fore.RED + "nn* Program aborted by user. Exiting...n"
sys.exit()
############# Application #4 - Part #2 #############
check_sql = True
def sql_connection(command, values):
Page 42 of 185
42 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
global check_sql
#Define SQL connection parameters
selected_sql_file = open(sql_file, 'r')
#Starting from the beginning of the file
selected_sql_file.seek(0)
sql_host = selected_sql_file.readlines()[0].split(',')[0]
#Starting from the beginning of the file
selected_sql_file.seek(0)
sql_username = selected_sql_file.readlines()[0].split(',')[1]
#Starting from the beginning of the file
selected_sql_file.seek(0)
sql_password = selected_sql_file.readlines()[0].split(',')[2]
#Starting from the beginning of the file
selected_sql_file.seek(0)
sql_database =
selected_sql_file.readlines()[0].split(',')[3].rstrip("n")
#Connecting and writing to database
try:
sql_conn = mdb.connect(sql_host, sql_username, sql_password,
sql_database)
cursor = sql_conn.cursor()
cursor.execute("USE NetMon")
cursor.execute(command, values)
#Commit changes
sql_conn.commit()
except mdb.Error, e:
sql_log_file = open("SQL_Error_Log.txt", "a")
#Print any SQL errors to the error log file
print >>sql_log_file, str(datetime.datetime.now()) + ": Error %d:
%s" % (e.args[0],e.args[1])
#Closing sql log file:
sql_log_file.close()
#Setting check_sql flag to False if any sql error occurs
check_sql = False
#Closing the sql file
Page 43 of 185
43 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
selected_sql_file.close()
#Initialize the necessary lists and dictionaries
cpu_values = []
io_mem_values = []
proc_mem_values = []
upint_values = []
top3_cpu = {}
top3_io_mem = {}
top3_proc_mem = {}
top3_upint = {}
#Open SSHv2 connection to devices
def open_ssh_conn(ip):
global check_sql
#Change exception message
try:
#Define SSH parameters
selected_user_file = open(user_file, 'r')
#Starting from the beginning of the file
selected_user_file.seek(0)
#Reading the username from the file
username = selected_user_file.readlines()[0].split(',')[0]
#Starting from the beginning of the file
selected_user_file.seek(0)
#Reading the password from the file
password =
selected_user_file.readlines()[0].split(',')[1].rstrip("n")
#Logging into device
session = paramiko.SSHClient()
#For testing purposes, this allows auto-accepting unknown host
keys
#Do not use in production! The default would be RejectPolicy
session.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#Connect to the device using username and password
session.connect(ip, username = username, password = password)
#Start an interactive shell session on the router
connection = session.invoke_shell()
#Setting terminal length for entire output - disable pagination
connection.send("terminal length 0n")
time.sleep(1)
Page 44 of 185
44 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Entering global config mode
#connection.send("n")
#connection.send("configure terminaln")
#time.sleep(1)
#Reading commands from within the script
#Using the "" line continuation character for better readability
of the commands to be sent
selected_cisco_commands = '''show version | include (,
Version|uptime is|bytes of memory|Hz)&
show inventory&
show interfaces | include bia&
show processes cpu | include CPU
utilization&
show memory statistics&
show ip int brief | include
(Ethernet|Serial)&
show cdp neighbors detail | include
Device ID&
show ip protocols | include Routing
Protocol'''
#Splitting commands by the "&" character
command_list = selected_cisco_commands.split("&")
#Writing each line in the command string to the device
for each_line in command_list:
connection.send(each_line + 'n')
time.sleep(3)
#Closing the user file
selected_user_file.close()
#Checking command output for IOS syntax errors
output = connection.recv(65535)
if re.search(r"% Invalid input detected at", output):
print Fore.RED + "* There was at least one IOS syntax error on
device %s" % ip
else:
print Fore.GREEN + "* All parameters were extracted from
device %s" % ip,
#Test for reading command output
#print output + "n"
############# Application #4 - Part #3 #############
#Extracting device parameters
#...starting with the ones destined to the NetworkDevices table in
MySQL
dev_hostname = re.search(r"(.+) uptime is", output)
Page 45 of 185
45 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
hostname = dev_hostname.group(1)
#print hostname
dev_mac = re.findall(r"(bia (.+?))", output)
#print dev_mac
mac = dev_mac[0]
#print mac
dev_vendor = re.search(r"(.+?) (.+) bytes of memory", output)
vendor = dev_vendor.group(1)
#print vendor
dev_model = re.search(r"(.+?) (.+?) (.+) bytes of memory", output)
model = dev_model.group(2)
#print model
dev_image_name = re.search(r" ((.+)), Version", output)
image_name = dev_image_name.group(1)
#print image_name
dev_os = re.search(r"), Version (.+),", output)
os = dev_os.group(1)
#print os
serial_no = ""
if len(re.findall(r"(.+), SN: (.+?)rn", output)) == 0:
serial_no = "unknown"
else:
serial_no = re.findall(r"(.+), SN: (.+?)rn",
output)[0][1].strip()
#print serial_no
dev_uptime = re.search(r" uptime is (.+)n", output)
uptime = dev_uptime.group(1)
uptime_value_list = uptime.split(', ')
#Getting the device uptime in seconds
y_sec = 0
w_sec = 0
d_sec = 0
h_sec = 0
m_sec = 0
for j in uptime_value_list:
if 'year' in j:
y_sec = int(j.split(' ')[0]) * 31449600
elif 'week' in j:
w_sec = int(j.split(' ')[0]) * 604800
elif 'day' in j:
d_sec = int(j.split(' ')[0]) * 86400
Page 46 of 185
46 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
elif 'hour' in j:
h_sec = int(j.split(' ')[0]) * 3600
elif 'minute' in j:
m_sec = int(j.split(' ')[0]) * 60
total_uptime_sec = y_sec + w_sec + d_sec + h_sec + m_sec
#print total_uptime_sec
cpu_model = ""
if re.search(r".isco (.+?) ((.+)) processor(.+)n", output) ==
None:
cpu_model = "unknown"
else:
cpu_model = re.search(r".isco (.+?) ((.+)) processor(.+)n",
output).group(2)
#print cpu_model
cpu_speed = ""
if re.search(r"(.+?)at (.+?)MHz(.+)n", output) == None:
cpu_speed = "unknown"
else:
cpu_speed = re.search(r"(.+?)at (.+?)MHz(.+)n",
output).group(2)
#print cpu_speed
serial_int = ""
if re.findall(r"Serial([0-9]*)/([0-9]*) (.+)n", output) == None:
serial_int = "no serial"
else:
serial_int = len(re.findall(r"Serial([0-9]*)/([0-9]*) (.+)n",
output))
#print serial_int
dev_cdp_neighbors = re.findall(r"Device ID: (.+)rn", output)
all_cdp_neighbors = ','.join(dev_cdp_neighbors)
#print all_cdp_neighbors
dev_routing_pro = re.findall(r"Routing Protocol is "(.+)"rn",
output)
#print dev_routing_pro
is_internal = []
is_external = []
for protocol in dev_routing_pro:
if 'bgp' in protocol:
is_external.append(protocol)
else:
is_internal.append(protocol)
internal_pro = ','.join(is_internal)
external_pro = ','.join(is_external)
#print internal_pro
#print external_pro
Page 47 of 185
47 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
############# Application #4 - Part #4 #############
### CPU ###
dev_cpu_util_per5min = re.search(r"CPU utilization for five
seconds: (.+) five minutes: (.+?)%", output)
cpu_util_per5min = dev_cpu_util_per5min.group(2)
#print cpu_util_per5min
#Append CPU value for each device to the cpu_values list
cpu_values.append(int(cpu_util_per5min))
#Get top 3 CPU devices
top3_cpu[hostname] = cpu_util_per5min
### Processor Memory ###
dev_used_proc_mem = re.search(r"Processor(.+)n ", output)
dev_used_proc_mem = dev_used_proc_mem.group(1)
#print dev_used_proc_mem
total_proc_mem = dev_used_proc_mem.split(' ')[2].strip()
used_proc_mem = dev_used_proc_mem.split(' ')[3].strip()
#print total_proc_mem
#print used_proc_mem
#Get percentage of used proc mem
proc_mem_percent = format(int(used_proc_mem) * 100 /
float(total_proc_mem), ".2f")
#print proc_mem_percent
#Append used proc memory values for each device to the mem_values
list
proc_mem_values.append(float(proc_mem_percent))
#Get top 3 proc memory devices
top3_proc_mem[hostname] = proc_mem_percent
### I/O Memory ###
dev_used_io_mem = re.search(r" I/O(.+)n", output)
dev_used_io_mem = dev_used_io_mem.group(1)
#print dev_used_io_mem
total_io_mem = dev_used_io_mem.split(' ')[2].strip()
used_io_mem = dev_used_io_mem.split(' ')[3].strip()
#print total_io_mem
#print used_io_mem
#Get percentage of used proc mem
io_mem_percent = format(int(used_io_mem) * 100 /
float(total_io_mem), ".2f")
#print io_mem_percent
Page 48 of 185
48 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Append used I/O memory values for each device to the mem_values
list
io_mem_values.append(float(io_mem_percent))
#Get top 3 I/O memory devices
top3_io_mem[hostname] = io_mem_percent
### UP Interfaces ###
dev_total_int = re.findall(r"([A-Za-z]*)Ethernet([0-
9]*)(.+)YES(.+)n", output)
total_int = len(dev_total_int)
#print total_int
dev_total_up_int = re.findall(r"(.+)Ethernet([0-9]*)/([0-
9]*)[s]*(.+)up[s]*up", output)
total_up_int = len(dev_total_up_int)
#print total_up_int
#Get percentage of Eth UP interfaces out of the total number of
Eth interfaces
intf_percent = format(total_up_int * 100 / float(total_int),
".2f")
#print intf_percent
#Append percentage of UP interfaces for each device to the
upint_values list
upint_values.append(float(intf_percent))
#Get top 3 UP Eth interfaces density devices
top3_upint[hostname] = intf_percent
#Insert/Update if exists all network devices data into the MySQL
database table NetworkDevices. Calling sql_connection function
sql_connection("REPLACE INTO
NetworkDevices(Hostname,MACAddr,Vendor,Model,Image,IOSVersion,SerialNo,Upt
ime,CPUModel,CPUSpeed,SerialIntfNo,CiscoNeighbors,IntRoutingPro,ExtRouting
Pro) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
(hostname, mac, vendor, model, image_name, os, serial_no,
total_uptime_sec, cpu_model, cpu_speed, serial_int, all_cdp_neighbors,
internal_pro, external_pro))
#Closing the SSH connection
session.close()
except paramiko.AuthenticationException:
print Fore.RED + "* Invalid SSH username or password. n* Please
check the username/password file or the device configuration!n"
check_sql = False
#Creating threads
def create_threads():
threads = []
Page 49 of 185
49 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
for ip in ip_list:
th = threading.Thread(target = open_ssh_conn, args = (ip,))
#args is a tuple with a single element
th.start()
threads.append(th)
for th in threads:
th.join()
#Calling threads creation function
create_threads()
############# Application #4 - Part #5 #############
#Poll date and time are based on the system clock
poll_timestamp = datetime.datetime.now()
#print poll_timestamp
###Testing code###
#print cpu_values
#print proc_mem_values
#print io_mem_values
#print upint_values
#print top3_cpu
#print top3_proc_mem
#print top3_io_mem
#print top3_upint
###
#Defining a function to get top 3 devices in CPU/mem/intf usage
def top3(each_dict):
global top3_list
top3 = []
for host, usage in sorted(each_dict.items(), key = lambda x: x[1],
reverse = True)[:3]:
top3.append(host)
top3_list = ",".join(top3)
#print top3_list
#CPU average function
def cpu_average():
try:
cpu = sum(cpu_values) / float(len(cpu_values))
#Calling the top3 function for the CPU dictionary
top3(top3_cpu)
#Write values to the MySQL database CPUUtilization table
sql_connection("INSERT INTO
CPUUtilization(NetworkCPUUtilizationPercent,Top3CPUDevices,PollTimestamp)
VALUES(%s, %s, %s)", (cpu, top3_list, poll_timestamp))
Page 50 of 185
50 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
except ZeroDivisionError:
print "* There was an error while computing a network parameter.
No record has been added to MySQL. Please retry."
cpu_average()
#Used proc memory average function
def mem_proc_average():
try:
mem_proc = sum(proc_mem_values) / float(len(proc_mem_values))
#Calling the top3 function for the mem proc dictionary
top3(top3_proc_mem)
#Write values to the MySQL database ProcMemUtilization table
sql_connection("INSERT INTO
ProcMemUtilization(NetworkProcMemUtilizationPercent,Top3ProcMemDevices,Pol
lTimestamp) VALUES(%s, %s, %s)", (mem_proc, top3_list, poll_timestamp))
except ZeroDivisionError:
print "* There was an error while computing a network parameter.
No record has been added to MySQL. Please retry."
mem_proc_average()
#Used I/O memory average function
def mem_io_average():
try:
mem_io = sum(io_mem_values) / float(len(io_mem_values))
#Calling the top3 function for the mem I/O dictionary
top3(top3_io_mem)
#Write values to the MySQL database IOMemUtilization table
sql_connection("INSERT INTO
IOMemUtilization(NetworkIOMemUtilizationPercent,Top3IOMemDevices,PollTimes
tamp) VALUES(%s, %s, %s)", (mem_io, top3_list, poll_timestamp))
except ZeroDivisionError:
print "* There was an error while computing a network parameter.
No record has been added to MySQL. Please retry."
mem_io_average()
#Total UP Eth interfaces function
def upint_total():
try:
upint = sum(upint_values) / float(len(upint_values))
#Calling the top3 function for the UP intf dictionary
top3(top3_upint)
#Write values to the MySQL database UPEthInterfaces table
Page 51 of 185
51 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
sql_connection("INSERT INTO
UPEthInterfaces(NetworkUPEthIntfPercent,Top3UPEthIntf,PollTimestamp)
VALUES(%s, %s, %s)", (upint, top3_list, poll_timestamp))
except ZeroDivisionError:
print "* There was an error while computing a network parameter.
No record has been added to MySQL. Please retry."
upint_total()
#print check_sql
if check_sql == True:
print "n* All parameters were successfully exported to MySQL."
else:
print Fore.RED + "n* There was a problem exporting data to MySQL.n*
Check the files, database and SQL_Error_Log.txt.n"
#De-initialize colorama
deinit()
#End of program
Page 52 of 185
52 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.8. Application #5 - OSPF network discovery via SNMP
(full code, reference: Section 17. Application #5 - OSPF network discovery via
SNMP)
Logical flow diagram
Page 53 of 185
53 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
############# Application #5 - Part #1 #############
'''
Make the following configuration on each router in the network:
configure terminal
snmp-server community public RO
'''
# Open a regular Linux terminal
# Go to the folder containing the script, using cd /folder_path
# Enter "sudo python OSPF_SNMP.py" and the password for the account
# You may also need to configure the permissions on the script first!
"chmod 755 script.py"
# Check the console output for any errors
#Necessary Python packages (they are already installed on the Debian VM)
#https://pypi.python.org/pypi/setuptools
#https://pypi.python.org/pypi/networkx
#https://pypi.python.org/pypi/matplotlib
#https://pypi.python.org/pypi/pysnmp
#https://pypi.python.org/pypi/colorama
import pprint
import subprocess
import binascii
import sys
try:
import matplotlib.pyplot as matp
except ImportError:
print Fore.RED + Style.BRIGHT + "n* Module matplotlib needs to be
installed on your system."
print "* Download it from: https://pypi.python.org/pypi/matplotlibn"
+ Fore.WHITE + Style.BRIGHT
sys.exit()
try:
import networkx as nx
except ImportError:
print Fore.RED + Style.BRIGHT + "n* Module networkx needs to be
installed on your system."
print "* Download it from: https://pypi.python.org/pypi/networkx"
print "* You should also install decorator:
https://pypi.python.org/pypi/decoratorn" + Fore.WHITE + Style.BRIGHT
sys.exit()
try:
#Module for output coloring
from colorama import init, deinit, Fore, Style
except ImportError:
Page 54 of 185
54 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
print Fore.RED + Style.BRIGHT + "n* Module colorama needs to be
installed on your system."
print "* Download it from: https://pypi.python.org/pypi/coloraman" +
Fore.WHITE + Style.BRIGHT
sys.exit()
try:
#Module for SNMP
from pysnmp.entity.rfc3413.oneliner import cmdgen
except ImportError:
print Fore.RED + Style.BRIGHT + "n* Module pysnmp needs to be
installed on your system."
print "* Download it from: https://pypi.python.org/pypi/pysnmpn" +
Fore.WHITE + Style.BRIGHT
sys.exit()
#Initialize colorama
init()
#Prompting user for input
try:
print Style.BRIGHT + "n######################## OSPF DISCOVERY TOOL
########################"
print "Make sure to connect to a device already running OSPF in the
network!"
print "SNMP community string should be the same on all devices running
OSPF!n"
ip = raw_input(Fore.BLUE + Style.BRIGHT + "n* Please enter root
device IP: ")
comm = raw_input("n* Please enter community string: ")
except KeyboardInterrupt:
print Fore.RED + Style.BRIGHT + "nn* Program aborted by user.
Exiting...n"
sys.exit()
############# Application #5 - Part #2 #############
#Checking IP address validity
def ip_is_valid():
while True:
#Checking octets
a = ip.split('.')
if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) !=
127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255
and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255):
break
Page 55 of 185
55 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
else:
print 'n* There was an INVALID IP address! Please check and
try again!n'
sys.exit()
#Checking IP reachability
print Fore.GREEN + Style.BRIGHT + "n* Valid IP address. Checking IP
reachability...n"
while True:
ping_reply = subprocess.call(['ping', '-c', '3', '-w', '3', '-q',
'-n', ip], stdout = subprocess.PIPE)
if ping_reply == 0:
print Fore.GREEN + Style.BRIGHT + "* Device is reachable.
Performing SNMP extraction...n"
print Fore.GREEN + Style.BRIGHT + "* This may take a few
moments...n"
break
elif ping_reply == 2:
print Fore.RED + Style.BRIGHT + "n* No response from device
%s." % ip
sys.exit()
else:
print Fore.RED + Style.BRIGHT + "n* Ping to the following
device has FAILED:", ip
print "n"
sys.exit()
#Change exception message
try:
#Calling IP validity function
ip_is_valid()
except KeyboardInterrupt:
print Fore.RED + Style.BRIGHT + "nn* Program aborted by user.
Exiting...n"
sys.exit()
ospf = []
#SNMP function
def snmp_get(ip):
nbridlist = []
nbriplist = []
ospf_devices = {}
#Creating command generator object
cmdGen = cmdgen.CommandGenerator()
Page 56 of 185
56 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Performing SNMP GETNEXT operations on the OSPF OIDs
#The basic syntax of nextCmd: nextCmd(authData, transportTarget,
*varNames)
#The nextCmd method returns a tuple of (errorIndication, errorStatus,
errorIndex, varBindTable)
errorIndication, errorStatus, errorIndex, varBindNbrTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.2.1.14.10.1.3')
#print
cmdGen.nextCmd(cmdgen.CommunityData(comm),cmdgen.UdpTransportTarget((ip,
161)),'1.3.6.1.2.1.14.10.1.3')
#print varBindNbrTable
errorIndication, errorStatus, errorIndex, varBindNbrIpTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.2.1.14.10.1.1')
#print varBindNbrIpTable
errorIndication, errorStatus, errorIndex, varBindHostTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.4.1.9.2.1.3')
#print varBindHostTable
errorIndication, errorStatus, errorIndex, varBindHostIdTable =
cmdGen.nextCmd(cmdgen.CommunityData(comm),
cmdgen.UdpTransportTarget((ip, 161)),
'1.3.6.1.2.1.14.1.1')
#print varBindHostIdTable
#Extract and print out the results
for varBindNbrTableRow in varBindNbrTable:
for oid, nbrid in varBindNbrTableRow:
hex_string = binascii.hexlify(str(nbrid))
#print hex_string
octets = [hex_string[i:i+2] for i in range(0, len(hex_string),
2)]
#print octets
ip = [int(i, 16) for i in octets]
Page 57 of 185
57 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#print ip
nbr_r_id = '.'.join(str(i) for i in ip)
#print nbr_r_id
nbridlist.append(nbr_r_id)
#print('%s = %s' % (oid, nbr_r_id))
for varBindNbrIpTableRow in varBindNbrIpTable:
for oid, nbrip in varBindNbrIpTableRow:
hex_string = binascii.hexlify(str(nbrip))
octets = [hex_string[i:i+2] for i in range(0, len(hex_string),
2)]
ip = [int(i, 16) for i in octets]
nbr_ip = '.'.join(str(i) for i in ip)
nbriplist.append(nbr_ip)
#print('%s = %s' % (oid, nbr_ip))
for varBindHostTableRow in varBindHostTable:
for oid, host in varBindHostTableRow:
ospf_host = str(host)
#print('%s = %s' % (oid, host))
for varBindHostIdTableRow in varBindHostIdTable:
for oid, hostid in varBindHostIdTableRow:
hex_string = binascii.hexlify(str(hostid))
octets = [hex_string[i:i+2] for i in range(0, len(hex_string),
2)]
ip = [int(i, 16) for i in octets]
ospf_host_id = '.'.join(str(i) for i in ip)
#print('%s = %s' % (oid, hostid))
#Adding OSPF data by device in the ospf_device dictionary
ospf_devices["Host"] = ospf_host
ospf_devices["HostId"] = ospf_host_id
ospf_devices["NbrRtrId"] = nbridlist
ospf_devices["NbrRtrIp"] = nbriplist
ospf.append(ospf_devices)
return ospf
#Calling the function for the user specified IP address
ospf = snmp_get(ip)
#pprint.pprint(ospf)
############# Application #5 - Part #3 #############
def find_unqueried_neighbors():
#Host OSPF Router IDs
all_host_ids = []
for n in range(0, len(ospf)):
hid = ospf[n]["HostId"]
all_host_ids.append(hid)
Page 58 of 185
58 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#print "HID"
#print all_host_ids
#print "n"
#Neighbor OSPF Router IDs
all_nbr_ids = []
for n in range(0, len(ospf)):
for each_nid in ospf[n]["NbrRtrId"]:
if each_nid == "0.0.0.0":
pass
else:
all_nbr_ids.append(each_nid)
#print "NBR"
#print all_nbr_ids
#print list(set(all_nbr_ids))
#print "n"
#Determining which neighbors were not queried and adding them to a
list
all_outsiders = []
for p in all_nbr_ids:
if p not in all_host_ids:
all_outsiders.append(p)
#print "OUT"
#print all_outsiders
#print "n"
#Running the snmp_get() function for each unqueried neighbor
for q in all_outsiders:
for r in range(0, len(ospf)):
for index, s in enumerate(ospf[r]["NbrRtrId"]):
#print index, s
if q == s:
new_ip = ospf[r]["NbrRtrIp"][index]
snmp_get(new_ip)
else:
pass
return all_host_ids, all_nbr_ids, ospf
############# Application #5 - Part #4 #############
#Calling the function above
while True:
Page 59 of 185
59 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
if (len(list(set(find_unqueried_neighbors()[0]))) ==
len(list(set(find_unqueried_neighbors()[1])))):
break
final_devices_list = find_unqueried_neighbors()[2]
#pprint.pprint(final_devices_list)
#Creating list of neighborships
neighborship_dict = {}
for each_dictionary in final_devices_list:
for index, each_neighbor in enumerate(each_dictionary["NbrRtrId"]):
each_tuple = (each_dictionary["HostId"], each_neighbor)
neighborship_dict[each_tuple] = each_dictionary["NbrRtrIp"][index]
#pprint.pprint(neighborship_dict)
############# Application #5 - Part #5 #############
while True:
try:
#User defined actions
print Fore.BLUE + Style.BRIGHT + "* Please choose an action:nn1
- Display OSPF devices on the screenn2 - Export OSPF devices to CSV
filen3 - Generate OSPF network topologyne - Exit"
user_choice = raw_input("n* Enter your choice: ")
print "n"
#Defining actions
if user_choice == "1":
for each_dict in final_devices_list:
print "Hostname: " + Fore.YELLOW + Style.BRIGHT + "%s" %
each_dict["Host"] + Fore.BLUE + Style.BRIGHT
print "OSFP RID: " + Fore.YELLOW + Style.BRIGHT + "%s" %
each_dict["HostId"] + Fore.BLUE + Style.BRIGHT
print "OSPF Neighbors by ID: " + Fore.YELLOW +
Style.BRIGHT + "%s" % ', '.join(each_dict["NbrRtrId"]) + Fore.BLUE +
Style.BRIGHT
print "OSPF Neighbors by IP: " + Fore.YELLOW +
Style.BRIGHT + "%s" % ', '.join(each_dict["NbrRtrIp"]) + Fore.BLUE +
Style.BRIGHT
print "n"
continue
#Printing devices to CSV file
elif user_choice == "2":
print Fore.CYAN + Style.BRIGHT + "* Generating " + Fore.YELLOW
+ Style.BRIGHT + "OSPF_DEVICES" + Fore.CYAN + Style.BRIGHT + " file...n"
Page 60 of 185
60 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
print Fore.CYAN + Style.BRIGHT + "* Check the script folder.
Import the file into Excel for a better view of the devices.n"
csv_file = open("OSPF_DEVICES.txt", "w")
print >>csv_file, "Hostname" + ";" + "OSPFRouterID" + ";" +
"OSPFNeighborRouterID" + ";" + "OSPFNeighborIP"
for each_dict in final_devices_list:
print >>csv_file, each_dict["Host"] + ";" +
each_dict["HostId"] + ";" + ', '.join(each_dict["NbrRtrId"]) + ";" + ',
'.join(each_dict["NbrRtrIp"])
csv_file.close()
continue
############# Application #5 - Part #6 #############
#Generating OSPF network topology
elif user_choice == "3":
print Fore.CYAN + Style.BRIGHT + "* Generating OSPF network
topology...n" + Fore.BLUE + Style.BRIGHT
#Drawing the topology using the list of neighborships
G = nx.Graph()
G.add_edges_from(neighborship_dict.keys())
pos = nx.spring_layout(G, k = 0.1, iterations = 70)
nx.draw_networkx_labels(G, pos, font_size = 9, font_family =
"sans-serif", font_weight = "bold")
nx.draw_networkx_edges(G, pos, width = 4, alpha = 0.4,
edge_color = 'black')
nx.draw_networkx_edge_labels(G, pos, neighborship_dict,
label_pos = 0.3, font_size = 6)
nx.draw(G, pos, node_size = 700, with_labels = False)
matp.show()
continue
elif user_choice == "e":
print Fore.RED + Style.BRIGHT + "* Exiting... Bye!n"
sys.exit()
else:
print Fore.RED + Style.BRIGHT + "* Invalid option. Please
retry.n"
continue
except KeyboardInterrupt:
print Fore.RED + Style.BRIGHT + "nn* Program aborted by user.
Exiting...n"
sys.exit()
#De-initialize colorama
Page 61 of 185
61 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
deinit()
#End of program
Page 62 of 185
62 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.9. Application #6 - Basic network sniffer
(full code, reference: Section 18. Application #6 - Basic network sniffer)
This application is a basic network sniffer, which captures some predefined protocols and
saves info about each network packet in an external file.
As with the other applications in this course, the full code is available for download.
Based on what you have learned so far in the course, it’s your job now to study,
understand and test the code against a network device, as you’ve seen me doing with the
previous applications.
Feel free to alter the code in any way you want, add new protocols to be captured, more
data to be exported in the external file and so on. New functionality of any kind is welcome.
Just make sure to adapt your code to the contents of the packet in Scapy.
Also, please read the first 33 lines in the code carefully, as they are a good introduction
to the code that follows.
As you’ve probably guessed, I used Scapy to build this sniffer, because this tool allows
packet handling, decoding and analysis in a very intuitive way.
Also, pay special attention to the recommendations and settings that I made before
starting to build the user menu and so on. I am referring to these lines and the ones above
them:
net_iface = raw_input("* Enter the interface on which to run the sniffer (like 'eth1'):
")
subprocess.call(["ifconfig", net_iface, "promisc"], stdout=None, stderr=None,
shell=False)
Further more, please read the comments before every code block, as they are good
guidelines to what functionality is covered by that piece of code.
As you can see at line 72, the program asks the user what network interface is the capture
process going to be executed on. A good example is entering “eth1”.
net_iface = raw_input("* Enter the interface on which to run the sniffer (like 'eth1'):
")
Then, at line 80, the user is asked to enter the number of packets he wishes to be captured
by the sniffer:
Page 63 of 185
63 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
pkt_to_sniff = raw_input("* Enter the number of packets to capture (0 is infinity): ")
At line 92, the program requires the number of seconds to run the capture:
time_to_sniff = raw_input("* Enter the number of seconds to run the capture: ")
At line 103, the program asks the user for the protocol to filter the packets by:
proto_sniff = raw_input("* Enter the protocol to filter by (arp|bootp|icmp|0 is all): ")
Lines 115 and 116 are dedicated to choosing the file name and creating the file, by
opening it for writing (“w”):
file_name = raw_input("* Please give a name to the log file: ")
sniffer_log = open(file_name, "w")
At line 124, you can find the function that takes care of the parameter extraction from
each packet and logging the packet info to the file: def packet_log(pkt)
The program implements a counter for each packet, then records the source MAC
address and destination MAC address to the file, on a single row.
Finally, the sniffing process is initialized by the sniff() function in Scapy, at line 138,
passing the values collected from the user as arguments to this function.
pkt = sniff(iface=net_iface, count=int(pkt_to_sniff), timeout=int(time_to_sniff),
prn=packet_log)
Now, to test the program, first you should have direct connectivity from the Debian VM to
the router in GNS3 (R1 - 192.168.2.101 was my test device):
root@debian:/home/debian/workingdir# ping 192.168.2.101
PING 192.168.2.101 (192.168.2.101) 56(84) bytes of data.
64 bytes from 192.168.2.101: icmp_req=1 ttl=255 time=429 ms
Let’s choose ICMP packets for capturing purposes and after the capture is started, I am
going to ping the VM (192.168.2.100) from R1.
Please see the following way to use the program menu as an example:
root@debian:/home/debian/workingdir# python Sniffer.py
! Make sure to run this program as ROOT !
* Enter the interface on which to run the sniffer (like 'eth1'): eth1
Page 64 of 185
64 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
Interface eth1 was set to PROMISC mode.
Enter the number of packets to capture (0 is infinity): 0
The program will capture packets until the timeout expires.
* Enter the number of seconds to run the capture: 10
The program will capture packets for 10 seconds.
* Enter the protocol to filter by (arp|bootp|icmp|0 is all): icmp
The program will capture only ICMP packets.
* Please give a name to the log file: udemy.txt
* Starting the capture... Waiting for 10 seconds...
At this point, the program listens for all the ICMP packets it receives in the next 10
seconds on eth1 (ping from R1 now!). The results will be exported to the udemy.txt file.
And these are the results in this case:
root@debian:/home/debian/workingdir# cat udemy.txt
Packet 1: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 2: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 3: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 4: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 5: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 6: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 7: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 8: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 9: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 10: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 11: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 12: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 13: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 14: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 15: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 16: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 17: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 18: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Packet 19: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c
Packet 20: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
Page 65 of 185
65 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
Logical flow diagram
############# Application #6 - Basic Network Sniffer #############
#In Scapy, we will use the sniff() function to capture network packets.
#To see a list of what commands Scapy has available, run the lsc()
function.
#Run the ls() command to see ALL the supported protocols.
#Run the ls(protocol) command to see the fields and default values for any
protocol.
#See packet layers with the .summary() function.
#See packet contents with the .show() function.
#Dig into a specific packet layer using a list index:
pkts[3][2].summary()...
Page 66 of 185
66 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#...the first index chooses the packet out of the pkts list, the second
index chooses the layer for that specific packet.
#Using the .command() packet method will return a string of the command
necessary to recreate that sniffed packet.
#To see the list of optional arguments for the sniff() function:
'''
>>> print sniff.__doc__
Sniff packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] +
L2ListenSocket args) -> list of packets
count: number of packets to capture. 0 means infinity
store: wether to store sniffed packets or discard them
prn: function to apply to each packet. If something is returned,
it is displayed. Ex:
ex: prn = lambda x: x.summary()
lfilter: python function applied to each packet to determine
if further action may be done
ex: lfilter = lambda x: x.haslayer(Padding)
offline: pcap file to read packets from, instead of sniffing them
timeout: stop sniffing after a given time (default: None)
L2socket: use the provided L2socket
opened_socket: provide an object ready to use .recv() on
stop_filter: python function applied to each packet to determine
if we have to stop the capture after this packet
ex: stop_filter = lambda x: x.haslayer(TCP)
'''
#Importing the necessary modules
import logging
import subprocess
#This will suppress all messages that have a lower level of seriousness
than error messages, while running or loading Scapy
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
logging.getLogger("scapy.interactive").setLevel(logging.ERROR)
logging.getLogger("scapy.loading").setLevel(logging.ERROR)
try:
from scapy.all import *
except ImportError:
print "Scapy package for Python is not installed on your system."
print "Get it from https://pypi.python.org/pypi/scapy and try again."
sys.exit()
Page 67 of 185
67 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Asking the user for some parameters: interface on which to sniff, the
number of packets to sniff, the time interval to sniff, the protocol
#Making the necessary configurations
print "n! Make sure to run this program as ROOT !n"
#Setting network interface in promiscuous mode
#Wikipedia: In computer networking, promiscuous mode or "promisc mode"[1]
is a mode for a wired network interface controller (NIC) or wireless
network interface controller (WNIC)...
#...that causes the controller to pass all traffic it receives to the
central processing unit (CPU) rather than passing only the frames that the
controller is intended to receive.
#This mode is normally used for packet sniffing that takes place on a
router or on a computer connected to a hub.
#Also, when using our setup (VirtualBox-to-GNS3), you should go to the
Settings section for the virtual machine you are using...
#...select the adapter that connects to the GNS3 network and set
Promiscuous Mode: Allow All
net_iface = raw_input("* Enter the interface on which to run the sniffer
(like 'eth1'): ")
subprocess.call(["ifconfig", net_iface, "promisc"], stdout=None,
stderr=None, shell=False)
print "nInterface %s was set to PROMISC mode." % net_iface
print
#Asking the user for the number of packets to sniff (the "count"
parameter)
pkt_to_sniff = raw_input("Enter the number of packets to capture (0 is
infinity): ")
#Considering the case when the user enters 0 (infinity)
if int(pkt_to_sniff) != 0:
print "nThe program will capture %d packets." % int(pkt_to_sniff)
print
elif int(pkt_to_sniff) == 0:
print "nThe program will capture packets until the timeout expires."
print
#Asking the user for the time interval to sniff (the "timeout" parameter)
time_to_sniff = raw_input("* Enter the number of seconds to run the
capture: ")
#Handling the value entered by the user
if int(time_to_sniff) != 0:
print "nThe program will capture packets for %d seconds." %
int(time_to_sniff)
print
Page 68 of 185
68 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
#Asking the user for any protocol filter he might want to apply to the
sniffing process
#For this example I chose three protocols: ARP, BOOTP, ICMP
#You can customize this to add your own desired protocols
proto_sniff = raw_input("* Enter the protocol to filter by
(arp|bootp|icmp|0 is all): ")
#Considering the case when the user enters 0 (all)
if (proto_sniff == "arp") or (proto_sniff == "bootp") or (proto_sniff ==
"icmp"):
print "nThe program will capture only %s packets." %
proto_sniff.upper()
print
elif int(proto_sniff) == 0:
print "nThe program will capture all protocols."
print
#Creating an external file for packet logging
file_name = raw_input("* Please give a name to the log file: ")
sniffer_log = open(file_name, "w")
#Initializing the packet counter
packet_no = 0
#This is the function that will be applied to each captured packet
#The function will extract some parameters from the packet and then log
each packet to an external file
def packet_log(pkt):
#The packet index
global packet_no
#Filtering the packets based on the protocol. Using the lower() method
to ignore the case when searching for the protocol in the packet.
if proto_sniff.lower() in pkt[0][1].summary().lower():
packet_no = packet_no + 1
#Writing the data for each packet to the external file
print >>sniffer_log, "Packet " + str(packet_no) + ": " + "SMAC: "
+ pkt[0].src + " DMAC: " + pkt[0].dst
print "n* Starting the capture... Waiting for %s seconds..." %
time_to_sniff
#Running the sniffing process
pkt = sniff(iface=net_iface, count=int(pkt_to_sniff),
timeout=int(time_to_sniff), prn=packet_log)
#print pkt.show()
#Printing the closing message
print "n* The timeout of %s seconds has passed." % time_to_sniff
Page 69 of 185
69 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
print "* Please check the %s file to see the captured packets.n" %
file_name
#Closing the log file
sniffer_log.close()
#End of program. Feel free to modify it, test it, add new protocols to
sniff and improve de code whenever you feel the need to.
Page 70 of 185
70 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
2.10. Application #7 - Configuration file comparator
(full code, reference: Section 19. Application #7 - Configuration file comparator)
This application connects to a router in the network via Telnet, extracts the output
of “show running-config” and “show startup-config”, filters the irrelevant lines and
finally compares the configurations. Now, I know this can be accomplished using
the “show archive config differences”command in Cisco CLI, but I wanted you to know
how can this task be accomplished using Python.
As with the other applications in this course, the full code is available for download.
Based on what you have learned so far in the course, it’s your job now to study,
understand and test the code against a network device, as you’ve seen me doing with the
previous applications.
Feel free to alter the code in any way you want. New functionality of any kind is welcome,
enhancements as well. Just make sure to adapt your code to the command output format.
Also, please read the first 13 lines in the code carefully, as they are a good introduction
to the code that follows. As you can see, the first thing you should do is configure Telnet
access on the router and the username and password:
username teopy privilege 15 password 0 python
line vty 0 4
privilege level 15
login local
transport input telnet ssh
At line 27, I have defined the ip_validity() function, which takes care of checking whether
the IP address of the router, which the user enters at the prompt, is valid or not. You have
already seen this kind of validity check in action in the previous applications, so there is
nothing new here. The same comment is valid for the file_validity() function (line 46).
Both functions are defined at this point and will be called later in the code.
At line 61, the telnet() function is defined, which takes a single parameter:command. The
value of this parameter will be passed to theconnection.write() method at line 96.
Starting with line 108, I defined the user menu, which will accept 3 options, except e -
Exit program:
1 - Compare running-config with startup-config
2 - Compare running-config with local file
3 - Compare startup-config with local file
I had treated only the first option, comparing the running-config with the startup-config -
Page 71 of 185
71 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
lines 115-196, leaving you with the job of coding and testing the other two options, having
my code from option 1 as a guideline.
Now, let’s look at option 1 for a bit. First, I called the ip_validity() function to get this out
of the way. Next, a very important step, I called the telnet()function for each of the two
commands I am interested in, and saved the returned output to a separate
variable: output_run for the running-config and output_start for the startup-config.
Then, I have created (opened for writing) two files, each of them storing the output of the
corresponding command. The file names are intuitively chosen. Don’t forget to close the
files after writing the contents of those variables, to save the information.
Next, I opened the files for reading and used the readlines() method on each file object
to store the lines in each file as elements of a list. Of course, then I closed the files.
Then, using a for loop, I have filtered the lines in each file which were of no interest to
our goal. We are only interested in the lines starting with the one defining the IOS
version: “version 12.4” for example. That is actually the first relevant line in each file.
Now, after “cleaning” the files, we are left with only the pure router configurations. It’s time
to create a new file (file_diff.txt), in which all the config differences are going to be stored.
Actually, we are going to compare the two lists obtained with the readlines() method.
Finally, using list comprehensions, we are going to find the lines in the running-config
which are not present in the startup-config and vice versa. In case there are multiple
differences, we use a for loop to iterate over the lists and then print those differences
directly into the file_diff.txt file., one per line As stated in the code, the rule is:
A "+" sign means the line is present in the RUNNING-CONFIG but not in the
STARTUP-CONFIG
A "-" sign means the line is present in the STARTUP-CONFIG but not in the
RUNNING-CONFIG
Now, let’s make a quick test. If you have just started the router and made no config yet,
then the startup-config and running-config are the same. No surprise here. But, to make
the test more relevant, let’s configure a few things before starting the comparison, without
saving the changes to the startup-config. So, let’s go to router R1:
R1(config)#username udemy1 password udemy
R1(config)#username udemy2 password udemy
R1(config)#username udemy3 password udemy
Now, these three configurations are the differences between the startup-config and the
running-config. We should see them after running our program, saved in
the file_diff.txt file. Let’s test this:
Page 72 of 185
72 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
root@debian:/home/debian/workingdir# python ConfigFileComp.py
Use this tool to:
1 - Compare running-config with startup-config
2 - Compare running-config with local file
3 - Compare startup-config with local file
e - Exit program
Enter your choice: 1
Enter an IP address: 192.168.2.101
Please wait while the config file is being analyzed...
Use this tool to:
1 - Compare running-config with startup-config
2 - Compare running-config with local file
3 - Compare startup-config with local file
e - Exit program
Enter your choice: e
Exiting... See ya...
Now let’s check the results. We should see all three commands with a “+”sign, right?
root@debian:/home/debian/workingdir# cat file_diff.txt
+username udemy1 password 0 udemy
+username udemy2 password 0 udemy
+username udemy3 password 0 udemy
root@debian:/home/debian/workingdir#
...and success! As expected, the three commands are marked as differences, in the file.
Page 73 of 185
73 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
Logical flow diagram
Page 74 of 185
74 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
############# Application #7 - Config File Comparator #############
#This program will:
# * Connect to a router via Telnet and it will compare the running-config
file to the startup-config file on that device (this can be usually done
with: show archive config differences)
# * Compare a locally stored config file (.txt) with the running-config
file or startup-config file running on a router.
#Please see the "Python File Operations" section in the course for a recap
of the necessary concepts.
#Don't forget to configure Telnet access on the router!
#username teopy privilege 15 password 0 python
#line vty 0 4
# privilege level 15
# login local
# transport input telnet ssh
#The first part of the program is very similar to Application #2 in the
course.
import telnetlib
import os.path
import subprocess
import time
import sys
def ip_validity():
global ip_address
#Checking IP validity
while True:
ip_address = raw_input("Enter an IP address: ")
#Checking octets
a = ip_address.split('.')
if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) !=
127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255
and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255):
break
else:
print "nThe IP address is INVALID! Please retry!n"
continue
def file_validity():
while True:
Page 75 of 185
75 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu
cfg_file = raw_input("Enter config file name and extension: ")
#Changing exception message
if os.path.isfile(cfg_file) == True:
print "nFile was found...n"
break
else:
print "nFile %s does not exist! Please check and try
again!n" % cfg_file
continue
def telnet(command):
#Connecting to router via Telnet
#Define telnet parameters
username = 'teopy'
password = 'python'
#Specify the Telnet port (default is 23, anyway)
port = 23
#Specify the connection timeout in seconds for blocking operations,
like the connection attempt
connection_timeout = 5
#Specify a timeout in seconds. Read until the string is found or until
the timout has passed
reading_timeout = 5
#Logging into device
connection = telnetlib.Telnet(ip_address, port, connection_timeout)
#Waiting to be asked for an username
router_output = connection.read_until("Username:", reading_timeout)
#Enter the username when asked and a "n" for Enter
connection.write(username + "n")
#Waiting to be asked for a password
router_output = connection.read_until("Password:", reading_timeout)
#Enter the password when asked and a "n" for Enter
connection.write(password + "n")
time.sleep(1)
#Setting terminal length for the entire output - disabling pagination
connection.write("terminal length 0n")
time.sleep(1)
#Entering global config mode
connection.write("n")
connection.write(command + "n")
time.sleep(5)
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide
Python Network Programming – Course Applications Guide

More Related Content

What's hot

Socket programming
Socket programmingSocket programming
Socket programming
NemiRathore
 
Network programming using python
Network programming using pythonNetwork programming using python
Network programming using python
Ali Nezhad
 
Network Sockets
Network SocketsNetwork Sockets
Network Sockets
Peter R. Egli
 
Socket programming-tutorial-sk
Socket programming-tutorial-skSocket programming-tutorial-sk
Socket programming-tutorial-sk
sureshkarthick37
 
Socket programming using C
Socket programming using CSocket programming using C
Socket programming using C
Ajit Nayak
 
Socket programming in C
Socket programming in CSocket programming in C
Socket programming in CDeepak Swain
 
Socket programming
Socket programmingSocket programming
Socket programming
Anurag Tomar
 
Sockets
Sockets Sockets
Sockets
Gopaiah Sanaka
 
Socket programming
Socket programming Socket programming
Socket programming
Rajivarnan (Rajiv)
 
Socket programming in c
Socket programming in cSocket programming in c
Socket programming in c
Md. Golam Hossain
 
Socket System Calls
Socket System CallsSocket System Calls
Socket System Calls
Avinash Varma Kalidindi
 
Socket programming
Socket programmingSocket programming
Socket programming
Muhammad Fouad Ilyas Siddiqui
 
اسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونیاسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونی
Mohammad Reza Kamalifard
 
Networking & Socket Programming In Java
Networking & Socket Programming In JavaNetworking & Socket Programming In Java
Networking & Socket Programming In Java
Ankur Agrawal
 
Socket programming
Socket programmingSocket programming
Socket programming
harsh_bca06
 
Networking chapter III
Networking chapter IIINetworking chapter III
Networking chapter III
Jayakumar Balasubramanian
 
Elementary TCP Sockets
Elementary TCP SocketsElementary TCP Sockets
Elementary TCP Sockets
Saksham Khurana
 
theday, windows hacking with commandline
theday, windows hacking with commandlinetheday, windows hacking with commandline
theday, windows hacking with commandlineidsecconf
 

What's hot (20)

Socket programming
Socket programmingSocket programming
Socket programming
 
Network programming using python
Network programming using pythonNetwork programming using python
Network programming using python
 
Ppt of socket
Ppt of socketPpt of socket
Ppt of socket
 
Network Sockets
Network SocketsNetwork Sockets
Network Sockets
 
Socket programming-tutorial-sk
Socket programming-tutorial-skSocket programming-tutorial-sk
Socket programming-tutorial-sk
 
Socket programming using C
Socket programming using CSocket programming using C
Socket programming using C
 
Socket programming in C
Socket programming in CSocket programming in C
Socket programming in C
 
Socket programming
Socket programmingSocket programming
Socket programming
 
Sockets
Sockets Sockets
Sockets
 
Socket programming
Socket programming Socket programming
Socket programming
 
Socket programming in c
Socket programming in cSocket programming in c
Socket programming in c
 
Socket System Calls
Socket System CallsSocket System Calls
Socket System Calls
 
Socket programming
Socket programmingSocket programming
Socket programming
 
Basic socket programming
Basic socket programmingBasic socket programming
Basic socket programming
 
اسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونیاسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه یازدهم کلاس پایتون برای هکرهای قانونی
 
Networking & Socket Programming In Java
Networking & Socket Programming In JavaNetworking & Socket Programming In Java
Networking & Socket Programming In Java
 
Socket programming
Socket programmingSocket programming
Socket programming
 
Networking chapter III
Networking chapter IIINetworking chapter III
Networking chapter III
 
Elementary TCP Sockets
Elementary TCP SocketsElementary TCP Sockets
Elementary TCP Sockets
 
theday, windows hacking with commandline
theday, windows hacking with commandlinetheday, windows hacking with commandline
theday, windows hacking with commandline
 

Similar to Python Network Programming – Course Applications Guide

Parallel Processing with IPython
Parallel Processing with IPythonParallel Processing with IPython
Parallel Processing with IPython
Enthought, Inc.
 
Penetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utilityPenetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utility
IOSR Journals
 
جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲
جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲
جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲
Mohammad Reza Kamalifard
 
Parrot Drones Hijacking
Parrot Drones HijackingParrot Drones Hijacking
Parrot Drones Hijacking
Priyanka Aash
 
Python for the Network Nerd
Python for the Network NerdPython for the Network Nerd
Python for the Network Nerd
Matt Bynum
 
26.1.7 lab snort and firewall rules
26.1.7 lab   snort and firewall rules26.1.7 lab   snort and firewall rules
26.1.7 lab snort and firewall rules
Freddy Buenaño
 
5. configuring multiple switch with files
5. configuring multiple switch with files5. configuring multiple switch with files
5. configuring multiple switch with files
Vishnu Vardhan
 
Python para equipos de ciberseguridad
Python para equipos de ciberseguridad Python para equipos de ciberseguridad
Python para equipos de ciberseguridad
Jose Manuel Ortega Candel
 
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
CODE BLUE
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
Ben Scofield
 
How to Design a Great API (using flask) [ploneconf2017]
How to Design a Great API (using flask) [ploneconf2017]How to Design a Great API (using flask) [ploneconf2017]
How to Design a Great API (using flask) [ploneconf2017]
Devon Bernard
 
Python para equipos de ciberseguridad(pycones)
Python para equipos de ciberseguridad(pycones)Python para equipos de ciberseguridad(pycones)
Python para equipos de ciberseguridad(pycones)
Jose Manuel Ortega Candel
 
Ato2019 weave-services-istio
Ato2019 weave-services-istioAto2019 weave-services-istio
Ato2019 weave-services-istio
Lin Sun
 
Weave Your Microservices with Istio
Weave Your Microservices with IstioWeave Your Microservices with Istio
Weave Your Microservices with Istio
All Things Open
 
All Things Open 2019 weave-services-istio
All Things Open 2019 weave-services-istioAll Things Open 2019 weave-services-istio
All Things Open 2019 weave-services-istio
Lin Sun
 
Activity 5
Activity 5Activity 5
Activity 5
Heidi Owens
 
Penetration Testing for Easy RM to MP3 Converter Application and Post Exploit
Penetration Testing for Easy RM to MP3 Converter Application and Post ExploitPenetration Testing for Easy RM to MP3 Converter Application and Post Exploit
Penetration Testing for Easy RM to MP3 Converter Application and Post Exploit
JongWon Kim
 
Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...
Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...
Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...
Edureka!
 
Cisco Malware: A new risk to consider in perimeter security designs
Cisco Malware: A new risk to consider in perimeter security designsCisco Malware: A new risk to consider in perimeter security designs
Cisco Malware: A new risk to consider in perimeter security designs
Manuel Santander
 
Fire & Ice: Making and Breaking macOS Firewalls
Fire & Ice: Making and Breaking macOS FirewallsFire & Ice: Making and Breaking macOS Firewalls
Fire & Ice: Making and Breaking macOS Firewalls
Priyanka Aash
 

Similar to Python Network Programming – Course Applications Guide (20)

Parallel Processing with IPython
Parallel Processing with IPythonParallel Processing with IPython
Parallel Processing with IPython
 
Penetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utilityPenetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utility
 
جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲
جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲
جلسه پنجم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲- ارائه ۲
 
Parrot Drones Hijacking
Parrot Drones HijackingParrot Drones Hijacking
Parrot Drones Hijacking
 
Python for the Network Nerd
Python for the Network NerdPython for the Network Nerd
Python for the Network Nerd
 
26.1.7 lab snort and firewall rules
26.1.7 lab   snort and firewall rules26.1.7 lab   snort and firewall rules
26.1.7 lab snort and firewall rules
 
5. configuring multiple switch with files
5. configuring multiple switch with files5. configuring multiple switch with files
5. configuring multiple switch with files
 
Python para equipos de ciberseguridad
Python para equipos de ciberseguridad Python para equipos de ciberseguridad
Python para equipos de ciberseguridad
 
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
How to Design a Great API (using flask) [ploneconf2017]
How to Design a Great API (using flask) [ploneconf2017]How to Design a Great API (using flask) [ploneconf2017]
How to Design a Great API (using flask) [ploneconf2017]
 
Python para equipos de ciberseguridad(pycones)
Python para equipos de ciberseguridad(pycones)Python para equipos de ciberseguridad(pycones)
Python para equipos de ciberseguridad(pycones)
 
Ato2019 weave-services-istio
Ato2019 weave-services-istioAto2019 weave-services-istio
Ato2019 weave-services-istio
 
Weave Your Microservices with Istio
Weave Your Microservices with IstioWeave Your Microservices with Istio
Weave Your Microservices with Istio
 
All Things Open 2019 weave-services-istio
All Things Open 2019 weave-services-istioAll Things Open 2019 weave-services-istio
All Things Open 2019 weave-services-istio
 
Activity 5
Activity 5Activity 5
Activity 5
 
Penetration Testing for Easy RM to MP3 Converter Application and Post Exploit
Penetration Testing for Easy RM to MP3 Converter Application and Post ExploitPenetration Testing for Easy RM to MP3 Converter Application and Post Exploit
Penetration Testing for Easy RM to MP3 Converter Application and Post Exploit
 
Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...
Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...
Advanced Python Tutorial | Learn Advanced Python Concepts | Python Programmin...
 
Cisco Malware: A new risk to consider in perimeter security designs
Cisco Malware: A new risk to consider in perimeter security designsCisco Malware: A new risk to consider in perimeter security designs
Cisco Malware: A new risk to consider in perimeter security designs
 
Fire & Ice: Making and Breaking macOS Firewalls
Fire & Ice: Making and Breaking macOS FirewallsFire & Ice: Making and Breaking macOS Firewalls
Fire & Ice: Making and Breaking macOS Firewalls
 

Recently uploaded

FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
Peter Spielvogel
 

Recently uploaded (20)

FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
 

Python Network Programming – Course Applications Guide

  • 1. Page 1 of 185 1 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu Python Network Programming by Mihai Cătălin Teodosiu, CCNP, Udemy & GNS3 Academy Instructor
  • 2. Page 2 of 185 2 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 1. What’s this document all about? Note: This e-book is a comprehensive guide containing all the applications developed throughout my Python Network Programming courses: “Python Network Programming - Part 1: Build 7 Python Apps”, “Python Network Programming - Part 2: Multivendor Environment” & “Python Network Programming - Part 3: Scapy & Security Tools”. Note: This document is intended for students enrolled in all three courses and is distributed for personal use only. The distribution of this material to people not enrolled in the “Python Network Programming” course series is strictly prohibited and is subject to copyright infringement. The author of this document is entitled to invoke legal and technological measures to prevent and penalize copyright infringement. More information here: https://en.wikipedia.org/wiki/Copyright_infringement IMPORTANT, BEFORE YOU CONTINUE! All the code, scripts and applications are explained, turned into working applications and tested inside the course. For detailed explanations and testing, please see the course sections referenced by each application below. Pay attention to comments in the code!
  • 3. Page 3 of 185 3 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2. Python Network Programming - Part 1: Build 7 Python Apps NOTE! Python programming knowledge is required in order to understand the network automation applications below. Learn Python from scratch inside the video course series! 2.1. Telnet with Python (template only, reference: Section 11. Python Networking) #Open telnet connection to devices def open_telnet_conn(ip): #Change exception message try: #Define telnet parameters username = 'teopy' password = 'python' TELNET_PORT = 23 TELNET_TIMEOUT = 5 READ_TIMEOUT = 5 #Logging into device connection = telnetlib.Telnet(ip, TELNET_PORT, TELNET_TIMEOUT) output = connection.read_until("name:", READ_TIMEOUT) connection.write(username + "n") output = connection.read_until("word:", READ_TIMEOUT) connection.write(password + "n") time.sleep(1) #Setting terminal length for entire output - no pagination connection.write("terminal length 0n") time.sleep(1) #Entering global config mode connection.write("n") connection.write("configure terminaln") time.sleep(1) #Open user selected file for reading selected_cmd_file = open(cmd_file, 'r') #Starting from the beginning of the file selected_cmd_file.seek(0) #Writing each line in the file to the device for each_line in selected_cmd_file.readlines(): connection.write(each_line + 'n') time.sleep(1)
  • 4. Page 4 of 185 4 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Closing the file selected_cmd_file.close() #Test for reading command output #output = connection.read_very_eager() #print output #Closing the connection connection.close() except IOError: print "Input parameter error! Please check username, password and file name." #Calling the Telnet function open_telnet_conn(ip)
  • 5. Page 5 of 185 5 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.2. SSH with Python (template only, reference: Section 11. Python Networking) #Open SSHv2 connection to devices def open_ssh_conn(ip): #Change exception message try: #Define SSH parameters selected_user_file = open(user_file, 'r') #Starting from the beginning of the file selected_user_file.seek(0) username = selected_user_file.readlines()[0].split(',')[0] #Starting from the beginning of the file selected_user_file.seek(0) password = selected_user_file.readlines()[0].split(',')[1] #Logging into device session = paramiko.SSHClient() session.set_missing_host_key_policy( paramiko.AutoAddPolicy()) session.connect(ip, username = username, password = password) connection = session.invoke_shell() #Setting terminal length for entire output - no pagination connection.send("terminal length 0n") time.sleep(1) #Entering global config mode connection.send("n") connection.send("configure terminaln") time.sleep(1) #Open user selected file for reading selected_cmd_file = open(cmd_file, 'r') #Starting from the beginning of the file selected_cmd_file.seek(0) #Writing each line in the file to the device for each_line in selected_cmd_file.readlines(): connection.send(each_line + 'n') time.sleep(2)
  • 6. Page 6 of 185 6 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Closing the user file selected_user_file.close() #Closing the command file selected_cmd_file.close() #Checking command output for IOS syntax errors output = connection.recv(65535) if re.search(r"% Invalid input detected at", output): print "* There was at least one IOS syntax error on device %s" % ip else: print "nDONE for device %s" % ip #Test for reading command output #print output + "n" #Closing the connection session.close() except paramiko.AuthenticationException: print "* Invalid username or password. n* Please check the username/password file or the device configuration!" print "* Closing program...n" #Calling the SSH function open_ssh_conn(ip)
  • 7. Page 7 of 185 7 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.3. SNMP with Python (template only, reference: Section 11. Python Networking) #!/usr/bin/env python from pysnmp.entity.rfc3413.oneliner import cmdgen #SNMP function def snmp_get(ip): #Creating command generator object cmdGen = cmdgen.CommandGenerator() #Performing SNMP GETNEXT operations on the OSPF OIDs #The basic syntax of nextCmd: nextCmd(authData, transportTarget, *varNames) #The nextCmd method returns a tuple of (errorIndication, errorStatus, errorIndex, varBindTable) errorIndication, errorStatus, errorIndex, varBindNbrTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.2.1.14.10.1.3') #print cmdGen.nextCmd(cmdgen.CommunityData(comm),cmdgen.UdpTransportTarget((ip, 161)),'1.3.6.1.2.1.14.10.1.3') #print varBindNbrTable errorIndication, errorStatus, errorIndex, varBindNbrIpTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.2.1.14.10.1.1') #print varBindNbrIpTable errorIndication, errorStatus, errorIndex, varBindHostTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.4.1.9.2.1.3') #print varBindHostTable
  • 8. Page 8 of 185 8 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu errorIndication, errorStatus, errorIndex, varBindHostIdTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.2.1.14.1.1') #print varBindHostIdTable
  • 9. Page 9 of 185 9 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.4. Application #1 - Basic subnet calculator (full code, reference: Section 13. Application #1 - Basic subnet calculator) Logical flow diagram
  • 10. Page 10 of 185 10 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ############# Application #1 - Part #1 ############# import random import sys def subnet_calc(): try: print "n" #Checking IP address validity while True: ip_address = raw_input("Enter an IP address: ") #Checking octets a = ip_address.split('.') if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) != 127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255 and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255): break else: print "nThe IP address is INVALID! Please retry!n" continue masks = [255, 254, 252, 248, 240, 224, 192, 128, 0] #Checking Subnet Mask validity while True: subnet_mask = raw_input("Enter a subnet mask: ") #Checking octets b = subnet_mask.split('.') if (len(b) == 4) and (int(b[0]) == 255) and (int(b[1]) in masks) and (int(b[2]) in masks) and (int(b[3]) in masks) and (int(b[0]) >= int(b[1]) >= int(b[2]) >= int(b[3])): break else: print "nThe subnet mask is INVALID! Please retry!n" continue ############# Application #1 - Part #2 ############# #Algorithm for subnet identification, based on IP and Subnet Mask #Convert mask to binary string mask_octets_padded = [] mask_octets_decimal = subnet_mask.split(".") #print mask_octets_decimal for octet_index in range(0, len(mask_octets_decimal)):
  • 11. Page 11 of 185 11 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #print bin(int(mask_octets_decimal[octet_index])) binary_octet = bin(int(mask_octets_decimal[octet_index])).split("b")[1] #print binary_octet if len(binary_octet) == 8: mask_octets_padded.append(binary_octet) elif len(binary_octet) < 8: binary_octet_padded = binary_octet.zfill(8) mask_octets_padded.append(binary_octet_padded) #print mask_octets_padded decimal_mask = "".join(mask_octets_padded) #print decimal_mask #Example: for 255.255.255.0 => 11111111111111111111111100000000 #Counting host bits in the mask and calculating number of hosts/subnet no_of_zeros = decimal_mask.count("0") no_of_ones = 32 - no_of_zeros no_of_hosts = abs(2 ** no_of_zeros - 2) #return positive value for mask /32 #print no_of_zeros #print no_of_ones #print no_of_hosts #Obtaining wildcard mask wildcard_octets = [] for w_octet in mask_octets_decimal: wild_octet = 255 - int(w_octet) wildcard_octets.append(str(wild_octet)) #print wildcard_octets wildcard_mask = ".".join(wildcard_octets) #print wildcard_mask ############# Application #1 - Part #3 ############# #Convert IP to binary string ip_octets_padded = [] ip_octets_decimal = ip_address.split(".") for octet_index in range(0, len(ip_octets_decimal)): binary_octet = bin(int(ip_octets_decimal[octet_index])).split("b")[1] if len(binary_octet) < 8: binary_octet_padded = binary_octet.zfill(8)
  • 12. Page 12 of 185 12 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ip_octets_padded.append(binary_octet_padded) else: ip_octets_padded.append(binary_octet) #print ip_octets_padded binary_ip = "".join(ip_octets_padded) #print binary_ip #Example: for 192.168.2.100 => 11000000101010000000001001100100 #Obtain the network address and broadcast address from the binary strings obtained above network_address_binary = binary_ip[:(no_of_ones)] + "0" * no_of_zeros #print network_address_binary broadcast_address_binary = binary_ip[:(no_of_ones)] + "1" * no_of_zeros #print broadcast_address_binary net_ip_octets = [] for octet in range(0, len(network_address_binary), 8): net_ip_octet = network_address_binary[octet:octet+8] net_ip_octets.append(net_ip_octet) #print net_ip_octets net_ip_address = [] for each_octet in net_ip_octets: net_ip_address.append(str(int(each_octet, 2))) #print net_ip_address network_address = ".".join(net_ip_address) #print network_address bst_ip_octets = [] for octet in range(0, len(broadcast_address_binary), 8): bst_ip_octet = broadcast_address_binary[octet:octet+8] bst_ip_octets.append(bst_ip_octet) #print bst_ip_octets bst_ip_address = [] for each_octet in bst_ip_octets: bst_ip_address.append(str(int(each_octet, 2))) #print bst_ip_address broadcast_address = ".".join(bst_ip_address) #print broadcast_address
  • 13. Page 13 of 185 13 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Results for selected IP/mask print "n" print "Network address is: %s" % network_address print "Broadcast address is: %s" % broadcast_address print "Number of valid hosts per subnet: %s" % no_of_hosts print "Wildcard mask: %s" % wildcard_mask print "Mask bits: %s" % no_of_ones print "n" ############# Application #1 - Part #4 ############# #Generation of random IP in subnet while True: generate = raw_input("Generate random ip address from subnet? (y/n)") if generate == "y": generated_ip = [] #Obtain available IP address in range, based on the difference between octets in broadcast address and network address for indexb, oct_bst in enumerate(bst_ip_address): #print indexb, oct_bst for indexn, oct_net in enumerate(net_ip_address): #print indexn, oct_net if indexb == indexn: if oct_bst == oct_net: #Add identical octets to the generated_ip list generated_ip.append(oct_bst) else: #Generate random number(s) from within octet intervals and append to the list generated_ip.append(str(random.randint(int(oct_net), int(oct_bst)))) #IP address generated from the subnet pool #print generated_ip y_iaddr = ".".join(generated_ip) #print y_iaddr print "Random IP address is: %s" % y_iaddr print "n" continue else: print "Ok, bye!n" break except KeyboardInterrupt: print "nnProgram aborted by user. Exiting...n" sys.exit()
  • 14. Page 14 of 185 14 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Calling the function subnet_calc()
  • 15. Page 15 of 185 15 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.5. Application #2 – SSH/Telnet network configuration (full code, reference: Section 14. Application #2 – SSH/Telnet network configuration) Logical flow diagram
  • 16. Page 16 of 185 16 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.5.1. SSH network configuration ############# Application #2 - Part #1 ############# import paramiko import threading import os.path import subprocess import time import sys import re #Checking IP address file and content validity def ip_is_valid(): check = False global ip_list while True: #Prompting user for input print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #n" ip_file = raw_input("# Enter IP file name and extension: ") print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #" #Changing exception message try: #Open user selected file for reading (IP addresses file) selected_ip_file = open(ip_file, 'r') #Starting from the beginning of the file selected_ip_file.seek(0) #Reading each line (IP address) in the file ip_list = selected_ip_file.readlines() #Closing the file selected_ip_file.close() except IOError: print "n* File %s does not exist! Please check and try again!n" % ip_file #Checking octets for ip in ip_list: a = ip.split('.') if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) != 127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255 and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255): check = True
  • 17. Page 17 of 185 17 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu break else: print 'n* There was an INVALID IP address! Please check and try again!n' check = False continue #Evaluating the 'check' flag if check == False: continue elif check == True: break ############# Application #2 - Part #2 ############# #Checking IP reachability print "n* Checking IP reachability. Please wait...n" check2 = False while True: for ip in ip_list: ping_reply = subprocess.call(['ping', '-c', '2', '-w', '2', '- q', '-n', ip]) if ping_reply == 0: check2 = True continue elif ping_reply == 2: print "n* No response from device %s." % ip check2 = False break else: print "n* Ping to the following device has FAILED:", ip check2 = False break #Evaluating the 'check' flag if check2 == False: print "* Please re-check IP address list or device.n" ip_is_valid() elif check2 == True: print 'n* All devices are reachable. Waiting for username/password file...n' break #Checking user file validity def user_is_valid(): global user_file
  • 18. Page 18 of 185 18 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu while True: print "# # # # # # # # # # # # # # # # # # # # # # # # # # # #n" user_file = raw_input("# Enter user/pass file name and extension: ") print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #" #Changing output messages if os.path.isfile(user_file) == True: print "n* Username/password file has been validated. Waiting for command file...n" break else: print "n* File %s does not exist! Please check and try again!n" % user_file continue #Checking command file validity def cmd_is_valid(): global cmd_file while True: print "nn# # # # # # # # # # # # # # # # # # # # # # # # # # # #n" cmd_file = raw_input("# Enter command file name and extension: ") print "n# # # # # # # # # # # # # # # # # # # # # # # # # # # #" #Changing output messages if os.path.isfile(cmd_file) == True: print "n* Sending command(s) to device(s)...n" break else: print "n* File %s does not exist! Please check and try again!n" % cmd_file continue #Change exception message try: #Calling IP validity function ip_is_valid() except KeyboardInterrupt: print "nn* Program aborted by user. Exiting...n" sys.exit() #Change exception message try: #Calling user file validity function user_is_valid() except KeyboardInterrupt: print "nn* Program aborted by user. Exiting...n"
  • 19. Page 19 of 185 19 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu sys.exit() #Change exception message try: #Calling command file validity function cmd_is_valid() except KeyboardInterrupt: print "nn* Program aborted by user. Exiting...n" sys.exit() ############# Application #2 - Part #3 ############# #Open SSHv2 connection to devices def open_ssh_conn(ip): #Change exception message try: #Define SSH parameters selected_user_file = open(user_file, 'r') #Starting from the beginning of the file selected_user_file.seek(0) #Reading the username from the file username = selected_user_file.readlines()[0].split(',')[0] #Starting from the beginning of the file selected_user_file.seek(0) #Reading the password from the file password = selected_user_file.readlines()[0].split(',')[1].rstrip("n") #Logging into device session = paramiko.SSHClient() #For testing purposes, this allows auto-accepting unknown host keys #Do not use in production! The default would be RejectPolicy session.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #Connect to the device using username and password session.connect(ip, username = username, password = password) #Start an interactive shell session on the router connection = session.invoke_shell() #Setting terminal length for entire output - disable pagination connection.send("terminal length 0n") time.sleep(1) #Entering global config mode connection.send("n") connection.send("configure terminaln")
  • 20. Page 20 of 185 20 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu time.sleep(1) #Open user selected file for reading selected_cmd_file = open(cmd_file, 'r') #Starting from the beginning of the file selected_cmd_file.seek(0) #Writing each line in the file to the device for each_line in selected_cmd_file.readlines(): connection.send(each_line + 'n') time.sleep(2) #Closing the user file selected_user_file.close() #Closing the command file selected_cmd_file.close() #Checking command output for IOS syntax errors router_output = connection.recv(65535) if re.search(r"% Invalid input detected at", router_output): print "* There was at least one IOS syntax error on device %s" % ip else: print "nDONE for device %s" % ip #Test for reading command output #print router_output + "n" #Closing the connection session.close() except paramiko.AuthenticationException: print "* Invalid username or password. n* Please check the username/password file or the device configuration!" print "* Closing program...n" ############# Application #2 - Part #4 ############# #Creating threads def create_threads(): threads = [] for ip in ip_list: th = threading.Thread(target = open_ssh_conn, args = (ip,)) #args is a tuple with a single element th.start() threads.append(th) for th in threads: th.join()
  • 21. Page 21 of 185 21 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Calling threads creation function create_threads() #End of program
  • 22. Page 22 of 185 22 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.5.2. Telnet network configuration #!/usr/bin/env python import telnetlib import threading import os.path import subprocess import time import sys #Checking IP address validity def ip_is_valid(): check = False global ip_list while True: #Prompting user for input ip_file = raw_input("Enter IP file name and extension: ") #Changing exception message try: #Open user selected file for reading (IP addresses file) selected_ip_file = open(ip_file, 'r') #Starting from the beginning of the file selected_ip_file.seek(0) #Reading each line (IP address) in the file ip_list = selected_ip_file.readlines() #Closing the file selected_ip_file.close() except IOError: print "nFile %s does not exist! Please check and try again!n" % ip_file #Checking octets for ip in ip_list: a = ip.split('.') if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) != 127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255 and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255): check = True break else:
  • 23. Page 23 of 185 23 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu print 'n* There was an INVALID IP address! Please check and try again!n' check = False continue #Evaluating the 'check' flag if check == False: continue elif check == True: break #Checking IP reachability print "nChecking IP reachability...n" check2 = False while True: for ip in ip_list: ping_reply = subprocess.call(['ping', '-c', '3', '-w', '3', '- q', '-n', ip]) if ping_reply == 0: check2 = True continue elif ping_reply == 2: print "nNo response from device %s." % ip check2 = False break else: print "nPing to the following device has FAILED:", ip check2 = False break #Evaluating the 'check' flag if check2 == False: print "Please re-check IP address list or device.n" ip_is_valid() elif check2 == True: print 'nAll devices are reachable. Waiting for command file...n' break #Checking command file validity def cmd_is_valid(): global cmd_file while True: cmd_file = raw_input("Enter command file name and extension: ") #Changing exception message
  • 24. Page 24 of 185 24 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu if os.path.isfile(cmd_file) == True: print "nSending command(s) to device(s)...n" break else: print "nFile %s does not exist! Please check and try again!n" % cmd_file continue #Change exception message try: #Calling IP validity function ip_is_valid() except KeyboardInterrupt: print "nnProgram aborted by user. Exiting...n" sys.exit() #Change exception message try: #Calling command file validity function cmd_is_valid() except KeyboardInterrupt: print "nnProgram aborted by user. Exiting...n" sys.exit() #Open telnet connection to devices def open_telnet_conn(ip): #Change exception message try: #Define telnet parameters username = 'teopy' password = 'python' #Specify the Telnet port (default is 23, anyway) port = 23 #Specify the connection timeout in seconds for blocking operations, like the connection attempt connection_timeout = 5 #Specify a timeout in seconds. Read until the string is found or until the timout has passed reading_timeout = 5 #Logging into device connection = telnetlib.Telnet(ip, port, connection_timeout) #Waiting to be asked for an username router_output = connection.read_until("Username:", reading_timeout) #Enter the username when asked and a "n" for Enter
  • 25. Page 25 of 185 25 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu connection.write(username + "n") #Waiting to be asked for a password router_output = connection.read_until("Password:", reading_timeout) #Enter the password when asked and a "n" for Enter connection.write(password + "n") time.sleep(1) #Setting terminal length for the entire output - disabling pagination connection.write("terminal length 0n") time.sleep(1) #Entering global config mode connection.write("n") connection.write("configure terminaln") time.sleep(1) #Open user selected file for reading selected_cmd_file = open(cmd_file, 'r') #Starting from the beginning of the file selected_cmd_file.seek(0) #Writing each line in the file to the device for each_line in selected_cmd_file.readlines(): connection.write(each_line + 'n') time.sleep(1) #Closing the file selected_cmd_file.close() #Test for reading command output #router_output = connection.read_very_eager() #print router_output #Closing the connection connection.close() except IOError: print "Input parameter error! Please check username, password and file name." #Creating threads def create_threads(): threads = [] for ip in ip_list: th = threading.Thread(target = open_telnet_conn, args = (ip,)) #args is a tuple with a single element th.start() threads.append(th)
  • 26. Page 26 of 185 26 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu for th in threads: th.join() #Calling threads creation function create_threads() #End of program
  • 27. Page 27 of 185 27 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.6. Application #3 - DHCP client simulator (full code, reference: Section 15. Application #3 - DHCP client simulator) Logical flow diagram
  • 28. Page 28 of 185 28 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ############# Application #3 - Part #1 ############# #DHCP client simulator #In scapy interactive mode - DHCP packets: ''' 'Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP' DHCP DISCOVER: 'Ether(src='08:00:27:f9:51:87', dst='ff:ff:ff:ff:ff:ff', type=2048)/IP(frag=0L, src='0.0.0.0', proto=17, tos=16, dst='255.255.255.255', chksum=14742, len=328, options=[], version=4L, flags=0L, ihl=5L, ttl=128, id=0)/UDP(dport=67, sport=68, len=308, chksum=47898)/BOOTP(hlen=6, sname='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0', hops=0, giaddr='0.0.0.0', chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x 00x00", yiaddr='0.0.0.0', secs=0, flags=0L, htype=1, file='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00', siaddr='0.0.0.0', options='cx82Sc', op=1)/DHCP(options=[('message- type', 1), ('hostname', 'kali-teo'), ('param_req_list', 'x01x1cx02x03x0fx06wx0c,/x1ay*'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad'])' DHCP OFFER: 'Ether(src='c0:04:1a:5c:00:01', dst='08:00:27:f9:51:87', type=2048)/IP(frag=0L, src='192.168.2.111', proto=17, tos=0, dst='192.168.2.1', chksum=13540, len=328, options=[], version=4L, flags=0L, ihl=5L, ttl=255, id=0)/UDP(dport=68, sport=67, len=308, chksum=19350)/BOOTP(hlen=6, sname='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0', hops=0, giaddr='0.0.0.0', chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x 00x00", yiaddr='192.168.2.1', secs=0, flags=0L, htype=1, file='x00x00x00x00x00x00x00x00x00x00x00x00x00
  • 29. Page 29 of 185 29 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00', siaddr='0.0.0.0', options='cx82Sc', op=2)/DHCP(options=[('message- type', 2), ('server_id', '192.168.2.111'), ('lease_time', 86400), ('renewal_time', 43200), ('rebinding_time', 75600), ('subnet_mask', '255.255.255.0'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad'])' DHCP OFFER (more options): 'Ether(src='ca:04:15:ec:00:08', dst='00:00:5e:4a:a3:fe', type=2048)/IP(frag=0L, src='192.168.2.111', proto=17, tos=0, dst='192.168.2.236', chksum=9573, len=328, options=[], version=4L, flags=0L, ihl=5L, ttl=255, id=3732)/UDP(dport=68, sport=67, len=308, chksum=3558)/BOOTP(hlen=6, sname='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00', xid=868370, ciaddr='0.0.0.0', hops=0, giaddr='0.0.0.0', chaddr='x00x00^Jxa3xfex00x00x00x00x00x00x00x00x0 0x00', yiaddr='192.168.2.236', secs=0, flags=0L, htype=1, file='x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00', siaddr='0.0.0.0', options='cx82Sc', op=2)/DHCP(options=[('message-type', 2), ('server_id', '192.168.2.111'), ('lease_time', 86400), ('renewal_time', 43200), ('rebinding_time', 75600), ('subnet_mask', '255.255.255.0'), ('router', '192.168.2.254'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad'])' DHCP REQUEST: 'Ether(src='08:00:27:f9:51:87', dst='ff:ff:ff:ff:ff:ff', type=2048)/IP(frag=0L, src='0.0.0.0', proto=17, tos=16, dst='255.255.255.255', chksum=14742, len=328, options=[], version=4L, flags=0L, ihl=5L, ttl=128, id=0)/UDP(dport=67, sport=68, len=308, chksum=61228)/BOOTP(hlen=6, sname='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00
  • 30. Page 30 of 185 30 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0', hops=0, giaddr='0.0.0.0', chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x 00x00", yiaddr='0.0.0.0', secs=0, flags=0L, htype=1, file='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00', siaddr='0.0.0.0', options='cx82Sc', op=1)/DHCP(options=[('message- type', 3), ('server_id', '192.168.2.111'), ('requested_addr', '192.168.2.1'), ('hostname', 'kali-teo'), ('param_req_list', 'x01x1cx02x03x0fx06wx0c,/x1ay*'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad'])' DHCP ACK: 'Ether(src='c0:04:1a:5c:00:01', dst='08:00:27:f9:51:87', type=2048)/IP(frag=0L, src='192.168.2.111', proto=17, tos=0, dst='192.168.2.1', chksum=13539, len=328, options=[], version=4L, flags=0L, ihl=5L, ttl=255, id=1)/UDP(dport=68, sport=67, len=308, chksum=18582)/BOOTP(hlen=6, sname='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00', xid=398202904, ciaddr='0.0.0.0', hops=0, giaddr='0.0.0.0', chaddr="x08x00'xf9Qx87x00x00x00x00x00x00x00x00x 00x00", yiaddr='192.168.2.1', secs=0, flags=0L, htype=1, file='x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00', siaddr='0.0.0.0', options='cx82Sc', op=2)/DHCP(options=[('message- type', 5), ('server_id', '192.168.2.111'), ('lease_time', 86400), ('renewal_time', 43200), ('rebinding_time', 75600), ('subnet_mask', '255.255.255.0'), 'end', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad', 'pad'])' '''
  • 31. Page 31 of 185 31 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu import subprocess import logging import random import sys #This will suppress all messages that have a lower level of seriousness than error messages, while running or loading Scapy logging.getLogger("scapy.runtime").setLevel(logging.ERROR) logging.getLogger("scapy.interactive").setLevel(logging.ERROR) logging.getLogger("scapy.loading").setLevel(logging.ERROR) try: from scapy.all import * except ImportError: print "Scapy package for Python is not installed on your system." print "Get it from https://pypi.python.org/pypi/scapy and try again." sys.exit() #To see a list of what commands Scapy has available, run the lsc() function. #Run the ls() command to see ALL the supported protocols. #Run the ls(protocol) command to see the fields and default values for any protocol. #See packet layers with the .summary() function. #See packet contents with the .show() function. #Dig into a specific packet layer using a list index: pkts[3][2].summary()... #...the first index chooses the packet out of the pkts list, the second index chooses the layer for that specific packet. #Using the .command() packet method will return a string of the command necessary to recreate that sniffed packet. print "n! Make sure to run this program as ROOT !n" #Setting network interface in promiscuous mode net_iface = raw_input("Enter the interface to the target network: ") subprocess.call(["ifconfig", net_iface, "promisc"], stdout=None, stderr=None, shell=False) print "nInterface %s was set to PROMISC mode." % net_iface
  • 32. Page 32 of 185 32 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Scapy normally makes sure that replies come from the same IP address the stimulus was sent to. #But our DHCP packet is sent to the IP broadcast address (255.255.255.255) and any answer packet will have the IP address of the replying DHCP server as its source IP address (e.g. 192.168.2.101). #Because these IP addresses don't match, we have to disable Scapy's check with conf.checkIPaddr = False before sending the stimulus. #Source: https://bitbucket.org/pbi/test/wiki/doc/IdentifyingRogueDHCPServers conf.checkIPaddr = False ############# Application #3 - Part #2 ############# ################## DHCP SEQUENCE ################# all_given_leases = [] server_id = [] client_mac = [] #Generate entire DHCP sequence def generate_dhcp_seq(): global all_given_leases #Defining some DHCP parameters x_id = random.randrange(1, 1000000) hw = "00:00:5e" + str(RandMAC())[8:] hw_str = mac2str(hw) #print hw #Assigning the .command() output of a captured DHCP DISCOVER packet to a variable dhcp_dis_pkt = Ether(dst="ff:ff:ff:ff:ff:ff", src=hw)/IP(src="0.0.0.0",dst="255.255.255.255") / UDP(sport=68,dport=67)/BOOTP(op=1, xid=x_id, chaddr=hw_str)/DHCP(options=[("message-type","discover"),("end")]) #Sending the DISCOVER packet and catching the OFFER reply #Generates two lists (answ and unansw). answd is a list containg a tuple: the first element is the DISCOVER packet, the second is the OFFER packet answd, unanswd = srp(dhcp_dis_pkt, iface=pkt_inf, timeout = 2.5, verbose=0) #print answd #print unanswd #print answd.summary() #print unanswd.summary() #print answd[0][1][BOOTP].yiaddr #The IP offered by the DHCP server to the client is extracted from the received answer offered_ip = answd[0][1][BOOTP].yiaddr #print offered_ip
  • 33. Page 33 of 185 33 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Assigning the .command() output of a captured DHCP REQUEST packet to a variable dhcp_req_pkt = Ether(dst="ff:ff:ff:ff:ff:ff", src=hw)/IP(src="0.0.0.0",dst="255.255.255.255") / UDP(sport=68,dport=67)/BOOTP(op=1, xid=x_id, chaddr=hw_str)/DHCP(options=[("message-type","request"),("requested_addr", offered_ip),("end")]) #Sending the REQUEST for the offered IP address #Capturing the ACK from the server answr, unanswr = srp(dhcp_req_pkt, iface=pkt_inf, timeout = 2.5, verbose=0) #print answr #print unanswr #print answr[0][1][IP].src #print answr[0][1][BOOTP].yiaddr #The IP offered by the DHCP server to the client is extracted from the received answer offered_ip_ack = answr[0][1][BOOTP].yiaddr #DHCP Server IP/ID server_ip = answr[0][1][IP].src #print server_ip #Adding each leased IP to the list of leases all_given_leases.append(offered_ip_ack) #Adding the server IP to a list server_id.append(server_ip) client_mac.append(hw) return all_given_leases, server_id, client_mac ############# Application #3 - Part #3 ############# ################## DHCP RELEASE ################# def generate_dhcp_release(ip, hw, server): #Defining DHCP Transaction ID x_id = random.randrange(1, 1000000) hw_str = mac2str(hw) #Creating the RELEASE packet dhcp_rls_pkt = IP(src=ip,dst=server) / UDP(sport=68,dport=67)/BOOTP(chaddr=hw_str, ciaddr=ip, xid=x_id)/DHCP(options=[("message-type","release"),("server_id", server),("end")])
  • 34. Page 34 of 185 34 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Sending the RELEASE packet send(dhcp_rls_pkt, verbose=0) ############# Application #3 - Part #4 ############# ################## USER MENU ################# try: #Enter option for the first screen while True: print "nUse this tool to:ns - Simulate DHCP Clientsnr - Simulate DHCP Releasene - Exit programn" user_option_sim = raw_input("Enter your choice: ") if user_option_sim == "s": print "nObtained leases will be exported to 'DHCP_Leases.txt'!" pkt_no = raw_input("nNumber of DHCP clients to simulate: ") pkt_inf = raw_input("Interface on which to send packets: ") print "nWaiting for clients to obtain IP addresses...n" try: #Calling the function for the required number of times (pkt_no) for iterate in range(0, int(pkt_no)): all_leased_ips = generate_dhcp_seq()[0] #print all_leased_ips except IndexError: print "No DHCP Server detected or connection is broken." print "Check your network settings and try again.n" sys.exit() #List of all leased IPs dhcp_leases = open("DHCP_Leases.txt", "w") #print all_leased_ips #print server_id #print client_mac #Print each leased IP to the file for index, each_ip in enumerate(all_leased_ips): print >>dhcp_leases, each_ip + "," + server_id[index] + "," + client_mac[index] dhcp_leases.close()
  • 35. Page 35 of 185 35 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu continue elif user_option_sim == "r": while True: print "ns - Release a single addressna - Release all addressesne - Exit to the previous screenn" user_option_release = raw_input("Enter your choice: ") if user_option_release == "s": print "n" user_option_address = raw_input("Enter IP address to release: ") #print all_leased_ips #print server_id #print client_mac try: #Check if required IP is in the list and run the release function for it if user_option_address in all_leased_ips: index = all_leased_ips.index(user_option_address) generate_dhcp_release(user_option_address, client_mac[index], server_id[index]) print "nSending RELEASE packet...n" else: print "IP Address not in list.n" continue except (NameError, IndexError): print "nSimulating DHCP RELEASES cannot be done separately, without prior DHCP Client simulation." print "Restart the program and simulate DHCP Clients and RELEASES in the same program session.n" sys.exit() elif user_option_release == "a": #print all_leased_ips #print server_id #print client_mac try: #Check if required IP is in the list and run the release function for it for user_option_address in all_leased_ips:
  • 36. Page 36 of 185 36 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu index = all_leased_ips.index(user_option_address) generate_dhcp_release(user_option_address, client_mac[index], server_id[index]) except (NameError, IndexError): print "nSimulating DHCP RELEASES cannot be done separately, without prior DHCP Client simulation." print "Restart the program and simulate DHCP Clients and RELEASES in the same program session.n" sys.exit() print "nThe RELEASE packets have been sent.n" #Erasing all leases from the file open("DHCP_Leases.txt", "w").close() print "File 'DHCP_Leases.txt' has been cleared." continue else: break else: print "Exiting... See ya...nn" sys.exit() except KeyboardInterrupt: print "nnProgram aborted by user. Exiting...n" sys.exit() #End of program
  • 37. Page 37 of 185 37 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.7. Application #4 - Network parameters extraction (full code, reference: Section 16. Application #4 - Network parameters extraction) Logical flow diagram
  • 38. Page 38 of 185 38 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ############# Application #4 - Part #1 ############# #Configure the permissions on the script first! 'chmod 755 script.py" #Make sure to have SSHv2 enabled and RSA 1024 bit key generated on every device! import MySQLdb as mdb import paramiko import threading import os.path import subprocess import datetime import time import sys import re #Module for output coloring from colorama import init, deinit, Fore, Style # Procedure for configuring Linux scheduler: # root@kali:/# crontab -l view scheduled tasks # root@kali:/# crontab -e edit scheduler # Add the following line to run the script every 5 minutes, every hour, every day, every month: # */5 * * * * /path_to_file/NetMon_SQL_v1.py /path_to_file/NETWORK_IP /path_to_file/SSH_USERPASS.txt /path_to_file/SQL_CONN.txt # For more info about configuring scheduler: http://kvz.io/blog/2007/07/29/schedule-tasks-on-linux-using-crontab/ # Before scheduling this task, run the script in the console to check for errors: # Go to the folder containing the script and all files, using cd /netmon_folder_path # Enter this command: python NetMon_SQL_v1.py NETWORK_IP.txt SSH_USERPASS.txt SQL_CONN.txt # Check the console output and SQL_Error_Log.txt file for any errors. # Running the script is recommended at intervals of at least 5 minutes. #Initialize colorama init() #Checking number of arguments passed into the script if len(sys.argv) == 4: ip_file = sys.argv[1] user_file = sys.argv[2] sql_file = sys.argv[3] print Fore.BLUE + Style.BRIGHT + "nn* The script will be executed using files:n" print Fore.BLUE + "Cisco network IP file is: " + Fore.YELLOW + "%s" % ip_file
  • 39. Page 39 of 185 39 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu print Fore.BLUE + "SSHv2 connection file is: " + Fore.YELLOW + "%s" % user_file print Fore.BLUE + "MySQL connection file is: " + Fore.YELLOW + "%s" % sql_file print Fore.BLUE + Style.BRIGHT + "n" else: print Fore.RED + Style.BRIGHT + "nIncorrect number of arguments (files) passed into the script." print Fore.RED + "Please try again.n" sys.exit() #Checking IP address file and content validity def ip_is_valid(): check = False global ip_list while True: #Changing exception message try: #Open user selected file for reading (IP addresses file) selected_ip_file = open(ip_file, 'r') #Starting from the beginning of the file selected_ip_file.seek(0) #Reading each line (IP address) in the file ip_list = selected_ip_file.readlines() #Closing the file selected_ip_file.close() except IOError: print Fore.RED + "n* File %s does not exist! Please check and try again!n" % ip_file sys.exit() #Checking octets for ip in ip_list: a = ip.split('.') if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) != 127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255 and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255): check = True break else: print 'n* There was an INVALID IP address! Please check and try again!n' check = False continue
  • 40. Page 40 of 185 40 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Evaluating the 'check' flag if check == False: sys.exit() elif check == True: break #Checking IP reachability print "* Checking IP reachability... Please wait...n" check2 = False while True: for ip in ip_list: ping_reply = subprocess.call(['ping', '-c', '3', '-w', '3', '- q', '-n', ip], stdout = subprocess.PIPE) if ping_reply == 0: check2 = True continue elif ping_reply == 2: print Fore.RED + "n* No response from device %s." % ip check2 = False break else: print Fore.RED + "n* Ping to the following device has FAILED:", ip check2 = False break #Evaluating the 'check' flag if check2 == False: print Fore.RED + "* Please re-check IP address list or device.n" sys.exit() elif check2 == True: print 'n* All devices are reachable. Checking SSHv2 connection file...n' break #Checking user file validity def user_is_valid(): global user_file while True: #Changing output messages if os.path.isfile(user_file) == True: print "n* SSHv2 connection file has been validated. Checking MySQL connection file...n" break
  • 41. Page 41 of 185 41 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu else: print Fore.RED + "n* File %s does not exist! Please check and try again!n" % user_file sys.exit() #Checking SQL connection command file validity def sql_is_valid(): global sql_file while True: #Changing output messages if os.path.isfile(sql_file) == True: print "n* MySQL connection file has been validated...n" print "n* Any MySQL errors will be logged to: " + Fore.YELLOW + "SQL_Error_Log.txtn" + Fore.BLUE print "n* Reading network data and writing to MySQL...n" break else: print Fore.RED + "n* File %s does not exist! Please check and try again!n" % sql_file sys.exit() #Change exception message try: #Calling IP validity function ip_is_valid() except KeyboardInterrupt: print Fore.RED + "nn* Program aborted by user. Exiting...n" sys.exit() #Change exception message try: #Calling user file validity function user_is_valid() except KeyboardInterrupt: print Fore.RED + "nn* Program aborted by user. Exiting...n" sys.exit() #Change exception message try: #Calling MySQL file validity function sql_is_valid() except KeyboardInterrupt: print Fore.RED + "nn* Program aborted by user. Exiting...n" sys.exit() ############# Application #4 - Part #2 ############# check_sql = True def sql_connection(command, values):
  • 42. Page 42 of 185 42 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu global check_sql #Define SQL connection parameters selected_sql_file = open(sql_file, 'r') #Starting from the beginning of the file selected_sql_file.seek(0) sql_host = selected_sql_file.readlines()[0].split(',')[0] #Starting from the beginning of the file selected_sql_file.seek(0) sql_username = selected_sql_file.readlines()[0].split(',')[1] #Starting from the beginning of the file selected_sql_file.seek(0) sql_password = selected_sql_file.readlines()[0].split(',')[2] #Starting from the beginning of the file selected_sql_file.seek(0) sql_database = selected_sql_file.readlines()[0].split(',')[3].rstrip("n") #Connecting and writing to database try: sql_conn = mdb.connect(sql_host, sql_username, sql_password, sql_database) cursor = sql_conn.cursor() cursor.execute("USE NetMon") cursor.execute(command, values) #Commit changes sql_conn.commit() except mdb.Error, e: sql_log_file = open("SQL_Error_Log.txt", "a") #Print any SQL errors to the error log file print >>sql_log_file, str(datetime.datetime.now()) + ": Error %d: %s" % (e.args[0],e.args[1]) #Closing sql log file: sql_log_file.close() #Setting check_sql flag to False if any sql error occurs check_sql = False #Closing the sql file
  • 43. Page 43 of 185 43 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu selected_sql_file.close() #Initialize the necessary lists and dictionaries cpu_values = [] io_mem_values = [] proc_mem_values = [] upint_values = [] top3_cpu = {} top3_io_mem = {} top3_proc_mem = {} top3_upint = {} #Open SSHv2 connection to devices def open_ssh_conn(ip): global check_sql #Change exception message try: #Define SSH parameters selected_user_file = open(user_file, 'r') #Starting from the beginning of the file selected_user_file.seek(0) #Reading the username from the file username = selected_user_file.readlines()[0].split(',')[0] #Starting from the beginning of the file selected_user_file.seek(0) #Reading the password from the file password = selected_user_file.readlines()[0].split(',')[1].rstrip("n") #Logging into device session = paramiko.SSHClient() #For testing purposes, this allows auto-accepting unknown host keys #Do not use in production! The default would be RejectPolicy session.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #Connect to the device using username and password session.connect(ip, username = username, password = password) #Start an interactive shell session on the router connection = session.invoke_shell() #Setting terminal length for entire output - disable pagination connection.send("terminal length 0n") time.sleep(1)
  • 44. Page 44 of 185 44 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Entering global config mode #connection.send("n") #connection.send("configure terminaln") #time.sleep(1) #Reading commands from within the script #Using the "" line continuation character for better readability of the commands to be sent selected_cisco_commands = '''show version | include (, Version|uptime is|bytes of memory|Hz)& show inventory& show interfaces | include bia& show processes cpu | include CPU utilization& show memory statistics& show ip int brief | include (Ethernet|Serial)& show cdp neighbors detail | include Device ID& show ip protocols | include Routing Protocol''' #Splitting commands by the "&" character command_list = selected_cisco_commands.split("&") #Writing each line in the command string to the device for each_line in command_list: connection.send(each_line + 'n') time.sleep(3) #Closing the user file selected_user_file.close() #Checking command output for IOS syntax errors output = connection.recv(65535) if re.search(r"% Invalid input detected at", output): print Fore.RED + "* There was at least one IOS syntax error on device %s" % ip else: print Fore.GREEN + "* All parameters were extracted from device %s" % ip, #Test for reading command output #print output + "n" ############# Application #4 - Part #3 ############# #Extracting device parameters #...starting with the ones destined to the NetworkDevices table in MySQL dev_hostname = re.search(r"(.+) uptime is", output)
  • 45. Page 45 of 185 45 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu hostname = dev_hostname.group(1) #print hostname dev_mac = re.findall(r"(bia (.+?))", output) #print dev_mac mac = dev_mac[0] #print mac dev_vendor = re.search(r"(.+?) (.+) bytes of memory", output) vendor = dev_vendor.group(1) #print vendor dev_model = re.search(r"(.+?) (.+?) (.+) bytes of memory", output) model = dev_model.group(2) #print model dev_image_name = re.search(r" ((.+)), Version", output) image_name = dev_image_name.group(1) #print image_name dev_os = re.search(r"), Version (.+),", output) os = dev_os.group(1) #print os serial_no = "" if len(re.findall(r"(.+), SN: (.+?)rn", output)) == 0: serial_no = "unknown" else: serial_no = re.findall(r"(.+), SN: (.+?)rn", output)[0][1].strip() #print serial_no dev_uptime = re.search(r" uptime is (.+)n", output) uptime = dev_uptime.group(1) uptime_value_list = uptime.split(', ') #Getting the device uptime in seconds y_sec = 0 w_sec = 0 d_sec = 0 h_sec = 0 m_sec = 0 for j in uptime_value_list: if 'year' in j: y_sec = int(j.split(' ')[0]) * 31449600 elif 'week' in j: w_sec = int(j.split(' ')[0]) * 604800 elif 'day' in j: d_sec = int(j.split(' ')[0]) * 86400
  • 46. Page 46 of 185 46 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu elif 'hour' in j: h_sec = int(j.split(' ')[0]) * 3600 elif 'minute' in j: m_sec = int(j.split(' ')[0]) * 60 total_uptime_sec = y_sec + w_sec + d_sec + h_sec + m_sec #print total_uptime_sec cpu_model = "" if re.search(r".isco (.+?) ((.+)) processor(.+)n", output) == None: cpu_model = "unknown" else: cpu_model = re.search(r".isco (.+?) ((.+)) processor(.+)n", output).group(2) #print cpu_model cpu_speed = "" if re.search(r"(.+?)at (.+?)MHz(.+)n", output) == None: cpu_speed = "unknown" else: cpu_speed = re.search(r"(.+?)at (.+?)MHz(.+)n", output).group(2) #print cpu_speed serial_int = "" if re.findall(r"Serial([0-9]*)/([0-9]*) (.+)n", output) == None: serial_int = "no serial" else: serial_int = len(re.findall(r"Serial([0-9]*)/([0-9]*) (.+)n", output)) #print serial_int dev_cdp_neighbors = re.findall(r"Device ID: (.+)rn", output) all_cdp_neighbors = ','.join(dev_cdp_neighbors) #print all_cdp_neighbors dev_routing_pro = re.findall(r"Routing Protocol is "(.+)"rn", output) #print dev_routing_pro is_internal = [] is_external = [] for protocol in dev_routing_pro: if 'bgp' in protocol: is_external.append(protocol) else: is_internal.append(protocol) internal_pro = ','.join(is_internal) external_pro = ','.join(is_external) #print internal_pro #print external_pro
  • 47. Page 47 of 185 47 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ############# Application #4 - Part #4 ############# ### CPU ### dev_cpu_util_per5min = re.search(r"CPU utilization for five seconds: (.+) five minutes: (.+?)%", output) cpu_util_per5min = dev_cpu_util_per5min.group(2) #print cpu_util_per5min #Append CPU value for each device to the cpu_values list cpu_values.append(int(cpu_util_per5min)) #Get top 3 CPU devices top3_cpu[hostname] = cpu_util_per5min ### Processor Memory ### dev_used_proc_mem = re.search(r"Processor(.+)n ", output) dev_used_proc_mem = dev_used_proc_mem.group(1) #print dev_used_proc_mem total_proc_mem = dev_used_proc_mem.split(' ')[2].strip() used_proc_mem = dev_used_proc_mem.split(' ')[3].strip() #print total_proc_mem #print used_proc_mem #Get percentage of used proc mem proc_mem_percent = format(int(used_proc_mem) * 100 / float(total_proc_mem), ".2f") #print proc_mem_percent #Append used proc memory values for each device to the mem_values list proc_mem_values.append(float(proc_mem_percent)) #Get top 3 proc memory devices top3_proc_mem[hostname] = proc_mem_percent ### I/O Memory ### dev_used_io_mem = re.search(r" I/O(.+)n", output) dev_used_io_mem = dev_used_io_mem.group(1) #print dev_used_io_mem total_io_mem = dev_used_io_mem.split(' ')[2].strip() used_io_mem = dev_used_io_mem.split(' ')[3].strip() #print total_io_mem #print used_io_mem #Get percentage of used proc mem io_mem_percent = format(int(used_io_mem) * 100 / float(total_io_mem), ".2f") #print io_mem_percent
  • 48. Page 48 of 185 48 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Append used I/O memory values for each device to the mem_values list io_mem_values.append(float(io_mem_percent)) #Get top 3 I/O memory devices top3_io_mem[hostname] = io_mem_percent ### UP Interfaces ### dev_total_int = re.findall(r"([A-Za-z]*)Ethernet([0- 9]*)(.+)YES(.+)n", output) total_int = len(dev_total_int) #print total_int dev_total_up_int = re.findall(r"(.+)Ethernet([0-9]*)/([0- 9]*)[s]*(.+)up[s]*up", output) total_up_int = len(dev_total_up_int) #print total_up_int #Get percentage of Eth UP interfaces out of the total number of Eth interfaces intf_percent = format(total_up_int * 100 / float(total_int), ".2f") #print intf_percent #Append percentage of UP interfaces for each device to the upint_values list upint_values.append(float(intf_percent)) #Get top 3 UP Eth interfaces density devices top3_upint[hostname] = intf_percent #Insert/Update if exists all network devices data into the MySQL database table NetworkDevices. Calling sql_connection function sql_connection("REPLACE INTO NetworkDevices(Hostname,MACAddr,Vendor,Model,Image,IOSVersion,SerialNo,Upt ime,CPUModel,CPUSpeed,SerialIntfNo,CiscoNeighbors,IntRoutingPro,ExtRouting Pro) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (hostname, mac, vendor, model, image_name, os, serial_no, total_uptime_sec, cpu_model, cpu_speed, serial_int, all_cdp_neighbors, internal_pro, external_pro)) #Closing the SSH connection session.close() except paramiko.AuthenticationException: print Fore.RED + "* Invalid SSH username or password. n* Please check the username/password file or the device configuration!n" check_sql = False #Creating threads def create_threads(): threads = []
  • 49. Page 49 of 185 49 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu for ip in ip_list: th = threading.Thread(target = open_ssh_conn, args = (ip,)) #args is a tuple with a single element th.start() threads.append(th) for th in threads: th.join() #Calling threads creation function create_threads() ############# Application #4 - Part #5 ############# #Poll date and time are based on the system clock poll_timestamp = datetime.datetime.now() #print poll_timestamp ###Testing code### #print cpu_values #print proc_mem_values #print io_mem_values #print upint_values #print top3_cpu #print top3_proc_mem #print top3_io_mem #print top3_upint ### #Defining a function to get top 3 devices in CPU/mem/intf usage def top3(each_dict): global top3_list top3 = [] for host, usage in sorted(each_dict.items(), key = lambda x: x[1], reverse = True)[:3]: top3.append(host) top3_list = ",".join(top3) #print top3_list #CPU average function def cpu_average(): try: cpu = sum(cpu_values) / float(len(cpu_values)) #Calling the top3 function for the CPU dictionary top3(top3_cpu) #Write values to the MySQL database CPUUtilization table sql_connection("INSERT INTO CPUUtilization(NetworkCPUUtilizationPercent,Top3CPUDevices,PollTimestamp) VALUES(%s, %s, %s)", (cpu, top3_list, poll_timestamp))
  • 50. Page 50 of 185 50 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu except ZeroDivisionError: print "* There was an error while computing a network parameter. No record has been added to MySQL. Please retry." cpu_average() #Used proc memory average function def mem_proc_average(): try: mem_proc = sum(proc_mem_values) / float(len(proc_mem_values)) #Calling the top3 function for the mem proc dictionary top3(top3_proc_mem) #Write values to the MySQL database ProcMemUtilization table sql_connection("INSERT INTO ProcMemUtilization(NetworkProcMemUtilizationPercent,Top3ProcMemDevices,Pol lTimestamp) VALUES(%s, %s, %s)", (mem_proc, top3_list, poll_timestamp)) except ZeroDivisionError: print "* There was an error while computing a network parameter. No record has been added to MySQL. Please retry." mem_proc_average() #Used I/O memory average function def mem_io_average(): try: mem_io = sum(io_mem_values) / float(len(io_mem_values)) #Calling the top3 function for the mem I/O dictionary top3(top3_io_mem) #Write values to the MySQL database IOMemUtilization table sql_connection("INSERT INTO IOMemUtilization(NetworkIOMemUtilizationPercent,Top3IOMemDevices,PollTimes tamp) VALUES(%s, %s, %s)", (mem_io, top3_list, poll_timestamp)) except ZeroDivisionError: print "* There was an error while computing a network parameter. No record has been added to MySQL. Please retry." mem_io_average() #Total UP Eth interfaces function def upint_total(): try: upint = sum(upint_values) / float(len(upint_values)) #Calling the top3 function for the UP intf dictionary top3(top3_upint) #Write values to the MySQL database UPEthInterfaces table
  • 51. Page 51 of 185 51 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu sql_connection("INSERT INTO UPEthInterfaces(NetworkUPEthIntfPercent,Top3UPEthIntf,PollTimestamp) VALUES(%s, %s, %s)", (upint, top3_list, poll_timestamp)) except ZeroDivisionError: print "* There was an error while computing a network parameter. No record has been added to MySQL. Please retry." upint_total() #print check_sql if check_sql == True: print "n* All parameters were successfully exported to MySQL." else: print Fore.RED + "n* There was a problem exporting data to MySQL.n* Check the files, database and SQL_Error_Log.txt.n" #De-initialize colorama deinit() #End of program
  • 52. Page 52 of 185 52 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.8. Application #5 - OSPF network discovery via SNMP (full code, reference: Section 17. Application #5 - OSPF network discovery via SNMP) Logical flow diagram
  • 53. Page 53 of 185 53 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ############# Application #5 - Part #1 ############# ''' Make the following configuration on each router in the network: configure terminal snmp-server community public RO ''' # Open a regular Linux terminal # Go to the folder containing the script, using cd /folder_path # Enter "sudo python OSPF_SNMP.py" and the password for the account # You may also need to configure the permissions on the script first! "chmod 755 script.py" # Check the console output for any errors #Necessary Python packages (they are already installed on the Debian VM) #https://pypi.python.org/pypi/setuptools #https://pypi.python.org/pypi/networkx #https://pypi.python.org/pypi/matplotlib #https://pypi.python.org/pypi/pysnmp #https://pypi.python.org/pypi/colorama import pprint import subprocess import binascii import sys try: import matplotlib.pyplot as matp except ImportError: print Fore.RED + Style.BRIGHT + "n* Module matplotlib needs to be installed on your system." print "* Download it from: https://pypi.python.org/pypi/matplotlibn" + Fore.WHITE + Style.BRIGHT sys.exit() try: import networkx as nx except ImportError: print Fore.RED + Style.BRIGHT + "n* Module networkx needs to be installed on your system." print "* Download it from: https://pypi.python.org/pypi/networkx" print "* You should also install decorator: https://pypi.python.org/pypi/decoratorn" + Fore.WHITE + Style.BRIGHT sys.exit() try: #Module for output coloring from colorama import init, deinit, Fore, Style except ImportError:
  • 54. Page 54 of 185 54 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu print Fore.RED + Style.BRIGHT + "n* Module colorama needs to be installed on your system." print "* Download it from: https://pypi.python.org/pypi/coloraman" + Fore.WHITE + Style.BRIGHT sys.exit() try: #Module for SNMP from pysnmp.entity.rfc3413.oneliner import cmdgen except ImportError: print Fore.RED + Style.BRIGHT + "n* Module pysnmp needs to be installed on your system." print "* Download it from: https://pypi.python.org/pypi/pysnmpn" + Fore.WHITE + Style.BRIGHT sys.exit() #Initialize colorama init() #Prompting user for input try: print Style.BRIGHT + "n######################## OSPF DISCOVERY TOOL ########################" print "Make sure to connect to a device already running OSPF in the network!" print "SNMP community string should be the same on all devices running OSPF!n" ip = raw_input(Fore.BLUE + Style.BRIGHT + "n* Please enter root device IP: ") comm = raw_input("n* Please enter community string: ") except KeyboardInterrupt: print Fore.RED + Style.BRIGHT + "nn* Program aborted by user. Exiting...n" sys.exit() ############# Application #5 - Part #2 ############# #Checking IP address validity def ip_is_valid(): while True: #Checking octets a = ip.split('.') if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) != 127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255 and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255): break
  • 55. Page 55 of 185 55 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu else: print 'n* There was an INVALID IP address! Please check and try again!n' sys.exit() #Checking IP reachability print Fore.GREEN + Style.BRIGHT + "n* Valid IP address. Checking IP reachability...n" while True: ping_reply = subprocess.call(['ping', '-c', '3', '-w', '3', '-q', '-n', ip], stdout = subprocess.PIPE) if ping_reply == 0: print Fore.GREEN + Style.BRIGHT + "* Device is reachable. Performing SNMP extraction...n" print Fore.GREEN + Style.BRIGHT + "* This may take a few moments...n" break elif ping_reply == 2: print Fore.RED + Style.BRIGHT + "n* No response from device %s." % ip sys.exit() else: print Fore.RED + Style.BRIGHT + "n* Ping to the following device has FAILED:", ip print "n" sys.exit() #Change exception message try: #Calling IP validity function ip_is_valid() except KeyboardInterrupt: print Fore.RED + Style.BRIGHT + "nn* Program aborted by user. Exiting...n" sys.exit() ospf = [] #SNMP function def snmp_get(ip): nbridlist = [] nbriplist = [] ospf_devices = {} #Creating command generator object cmdGen = cmdgen.CommandGenerator()
  • 56. Page 56 of 185 56 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Performing SNMP GETNEXT operations on the OSPF OIDs #The basic syntax of nextCmd: nextCmd(authData, transportTarget, *varNames) #The nextCmd method returns a tuple of (errorIndication, errorStatus, errorIndex, varBindTable) errorIndication, errorStatus, errorIndex, varBindNbrTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.2.1.14.10.1.3') #print cmdGen.nextCmd(cmdgen.CommunityData(comm),cmdgen.UdpTransportTarget((ip, 161)),'1.3.6.1.2.1.14.10.1.3') #print varBindNbrTable errorIndication, errorStatus, errorIndex, varBindNbrIpTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.2.1.14.10.1.1') #print varBindNbrIpTable errorIndication, errorStatus, errorIndex, varBindHostTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.4.1.9.2.1.3') #print varBindHostTable errorIndication, errorStatus, errorIndex, varBindHostIdTable = cmdGen.nextCmd(cmdgen.CommunityData(comm), cmdgen.UdpTransportTarget((ip, 161)), '1.3.6.1.2.1.14.1.1') #print varBindHostIdTable #Extract and print out the results for varBindNbrTableRow in varBindNbrTable: for oid, nbrid in varBindNbrTableRow: hex_string = binascii.hexlify(str(nbrid)) #print hex_string octets = [hex_string[i:i+2] for i in range(0, len(hex_string), 2)] #print octets ip = [int(i, 16) for i in octets]
  • 57. Page 57 of 185 57 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #print ip nbr_r_id = '.'.join(str(i) for i in ip) #print nbr_r_id nbridlist.append(nbr_r_id) #print('%s = %s' % (oid, nbr_r_id)) for varBindNbrIpTableRow in varBindNbrIpTable: for oid, nbrip in varBindNbrIpTableRow: hex_string = binascii.hexlify(str(nbrip)) octets = [hex_string[i:i+2] for i in range(0, len(hex_string), 2)] ip = [int(i, 16) for i in octets] nbr_ip = '.'.join(str(i) for i in ip) nbriplist.append(nbr_ip) #print('%s = %s' % (oid, nbr_ip)) for varBindHostTableRow in varBindHostTable: for oid, host in varBindHostTableRow: ospf_host = str(host) #print('%s = %s' % (oid, host)) for varBindHostIdTableRow in varBindHostIdTable: for oid, hostid in varBindHostIdTableRow: hex_string = binascii.hexlify(str(hostid)) octets = [hex_string[i:i+2] for i in range(0, len(hex_string), 2)] ip = [int(i, 16) for i in octets] ospf_host_id = '.'.join(str(i) for i in ip) #print('%s = %s' % (oid, hostid)) #Adding OSPF data by device in the ospf_device dictionary ospf_devices["Host"] = ospf_host ospf_devices["HostId"] = ospf_host_id ospf_devices["NbrRtrId"] = nbridlist ospf_devices["NbrRtrIp"] = nbriplist ospf.append(ospf_devices) return ospf #Calling the function for the user specified IP address ospf = snmp_get(ip) #pprint.pprint(ospf) ############# Application #5 - Part #3 ############# def find_unqueried_neighbors(): #Host OSPF Router IDs all_host_ids = [] for n in range(0, len(ospf)): hid = ospf[n]["HostId"] all_host_ids.append(hid)
  • 58. Page 58 of 185 58 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #print "HID" #print all_host_ids #print "n" #Neighbor OSPF Router IDs all_nbr_ids = [] for n in range(0, len(ospf)): for each_nid in ospf[n]["NbrRtrId"]: if each_nid == "0.0.0.0": pass else: all_nbr_ids.append(each_nid) #print "NBR" #print all_nbr_ids #print list(set(all_nbr_ids)) #print "n" #Determining which neighbors were not queried and adding them to a list all_outsiders = [] for p in all_nbr_ids: if p not in all_host_ids: all_outsiders.append(p) #print "OUT" #print all_outsiders #print "n" #Running the snmp_get() function for each unqueried neighbor for q in all_outsiders: for r in range(0, len(ospf)): for index, s in enumerate(ospf[r]["NbrRtrId"]): #print index, s if q == s: new_ip = ospf[r]["NbrRtrIp"][index] snmp_get(new_ip) else: pass return all_host_ids, all_nbr_ids, ospf ############# Application #5 - Part #4 ############# #Calling the function above while True:
  • 59. Page 59 of 185 59 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu if (len(list(set(find_unqueried_neighbors()[0]))) == len(list(set(find_unqueried_neighbors()[1])))): break final_devices_list = find_unqueried_neighbors()[2] #pprint.pprint(final_devices_list) #Creating list of neighborships neighborship_dict = {} for each_dictionary in final_devices_list: for index, each_neighbor in enumerate(each_dictionary["NbrRtrId"]): each_tuple = (each_dictionary["HostId"], each_neighbor) neighborship_dict[each_tuple] = each_dictionary["NbrRtrIp"][index] #pprint.pprint(neighborship_dict) ############# Application #5 - Part #5 ############# while True: try: #User defined actions print Fore.BLUE + Style.BRIGHT + "* Please choose an action:nn1 - Display OSPF devices on the screenn2 - Export OSPF devices to CSV filen3 - Generate OSPF network topologyne - Exit" user_choice = raw_input("n* Enter your choice: ") print "n" #Defining actions if user_choice == "1": for each_dict in final_devices_list: print "Hostname: " + Fore.YELLOW + Style.BRIGHT + "%s" % each_dict["Host"] + Fore.BLUE + Style.BRIGHT print "OSFP RID: " + Fore.YELLOW + Style.BRIGHT + "%s" % each_dict["HostId"] + Fore.BLUE + Style.BRIGHT print "OSPF Neighbors by ID: " + Fore.YELLOW + Style.BRIGHT + "%s" % ', '.join(each_dict["NbrRtrId"]) + Fore.BLUE + Style.BRIGHT print "OSPF Neighbors by IP: " + Fore.YELLOW + Style.BRIGHT + "%s" % ', '.join(each_dict["NbrRtrIp"]) + Fore.BLUE + Style.BRIGHT print "n" continue #Printing devices to CSV file elif user_choice == "2": print Fore.CYAN + Style.BRIGHT + "* Generating " + Fore.YELLOW + Style.BRIGHT + "OSPF_DEVICES" + Fore.CYAN + Style.BRIGHT + " file...n"
  • 60. Page 60 of 185 60 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu print Fore.CYAN + Style.BRIGHT + "* Check the script folder. Import the file into Excel for a better view of the devices.n" csv_file = open("OSPF_DEVICES.txt", "w") print >>csv_file, "Hostname" + ";" + "OSPFRouterID" + ";" + "OSPFNeighborRouterID" + ";" + "OSPFNeighborIP" for each_dict in final_devices_list: print >>csv_file, each_dict["Host"] + ";" + each_dict["HostId"] + ";" + ', '.join(each_dict["NbrRtrId"]) + ";" + ', '.join(each_dict["NbrRtrIp"]) csv_file.close() continue ############# Application #5 - Part #6 ############# #Generating OSPF network topology elif user_choice == "3": print Fore.CYAN + Style.BRIGHT + "* Generating OSPF network topology...n" + Fore.BLUE + Style.BRIGHT #Drawing the topology using the list of neighborships G = nx.Graph() G.add_edges_from(neighborship_dict.keys()) pos = nx.spring_layout(G, k = 0.1, iterations = 70) nx.draw_networkx_labels(G, pos, font_size = 9, font_family = "sans-serif", font_weight = "bold") nx.draw_networkx_edges(G, pos, width = 4, alpha = 0.4, edge_color = 'black') nx.draw_networkx_edge_labels(G, pos, neighborship_dict, label_pos = 0.3, font_size = 6) nx.draw(G, pos, node_size = 700, with_labels = False) matp.show() continue elif user_choice == "e": print Fore.RED + Style.BRIGHT + "* Exiting... Bye!n" sys.exit() else: print Fore.RED + Style.BRIGHT + "* Invalid option. Please retry.n" continue except KeyboardInterrupt: print Fore.RED + Style.BRIGHT + "nn* Program aborted by user. Exiting...n" sys.exit() #De-initialize colorama
  • 61. Page 61 of 185 61 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu deinit() #End of program
  • 62. Page 62 of 185 62 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.9. Application #6 - Basic network sniffer (full code, reference: Section 18. Application #6 - Basic network sniffer) This application is a basic network sniffer, which captures some predefined protocols and saves info about each network packet in an external file. As with the other applications in this course, the full code is available for download. Based on what you have learned so far in the course, it’s your job now to study, understand and test the code against a network device, as you’ve seen me doing with the previous applications. Feel free to alter the code in any way you want, add new protocols to be captured, more data to be exported in the external file and so on. New functionality of any kind is welcome. Just make sure to adapt your code to the contents of the packet in Scapy. Also, please read the first 33 lines in the code carefully, as they are a good introduction to the code that follows. As you’ve probably guessed, I used Scapy to build this sniffer, because this tool allows packet handling, decoding and analysis in a very intuitive way. Also, pay special attention to the recommendations and settings that I made before starting to build the user menu and so on. I am referring to these lines and the ones above them: net_iface = raw_input("* Enter the interface on which to run the sniffer (like 'eth1'): ") subprocess.call(["ifconfig", net_iface, "promisc"], stdout=None, stderr=None, shell=False) Further more, please read the comments before every code block, as they are good guidelines to what functionality is covered by that piece of code. As you can see at line 72, the program asks the user what network interface is the capture process going to be executed on. A good example is entering “eth1”. net_iface = raw_input("* Enter the interface on which to run the sniffer (like 'eth1'): ") Then, at line 80, the user is asked to enter the number of packets he wishes to be captured by the sniffer:
  • 63. Page 63 of 185 63 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu pkt_to_sniff = raw_input("* Enter the number of packets to capture (0 is infinity): ") At line 92, the program requires the number of seconds to run the capture: time_to_sniff = raw_input("* Enter the number of seconds to run the capture: ") At line 103, the program asks the user for the protocol to filter the packets by: proto_sniff = raw_input("* Enter the protocol to filter by (arp|bootp|icmp|0 is all): ") Lines 115 and 116 are dedicated to choosing the file name and creating the file, by opening it for writing (“w”): file_name = raw_input("* Please give a name to the log file: ") sniffer_log = open(file_name, "w") At line 124, you can find the function that takes care of the parameter extraction from each packet and logging the packet info to the file: def packet_log(pkt) The program implements a counter for each packet, then records the source MAC address and destination MAC address to the file, on a single row. Finally, the sniffing process is initialized by the sniff() function in Scapy, at line 138, passing the values collected from the user as arguments to this function. pkt = sniff(iface=net_iface, count=int(pkt_to_sniff), timeout=int(time_to_sniff), prn=packet_log) Now, to test the program, first you should have direct connectivity from the Debian VM to the router in GNS3 (R1 - 192.168.2.101 was my test device): root@debian:/home/debian/workingdir# ping 192.168.2.101 PING 192.168.2.101 (192.168.2.101) 56(84) bytes of data. 64 bytes from 192.168.2.101: icmp_req=1 ttl=255 time=429 ms Let’s choose ICMP packets for capturing purposes and after the capture is started, I am going to ping the VM (192.168.2.100) from R1. Please see the following way to use the program menu as an example: root@debian:/home/debian/workingdir# python Sniffer.py ! Make sure to run this program as ROOT ! * Enter the interface on which to run the sniffer (like 'eth1'): eth1
  • 64. Page 64 of 185 64 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu Interface eth1 was set to PROMISC mode. Enter the number of packets to capture (0 is infinity): 0 The program will capture packets until the timeout expires. * Enter the number of seconds to run the capture: 10 The program will capture packets for 10 seconds. * Enter the protocol to filter by (arp|bootp|icmp|0 is all): icmp The program will capture only ICMP packets. * Please give a name to the log file: udemy.txt * Starting the capture... Waiting for 10 seconds... At this point, the program listens for all the ICMP packets it receives in the next 10 seconds on eth1 (ping from R1 now!). The results will be exported to the udemy.txt file. And these are the results in this case: root@debian:/home/debian/workingdir# cat udemy.txt Packet 1: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 2: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 3: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 4: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 5: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 6: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 7: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 8: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 9: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 10: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 11: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 12: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 13: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 14: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 15: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 16: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 17: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 18: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00 Packet 19: SMAC: c0:01:24:c0:00:00 DMAC: 08:00:27:f2:9b:7c Packet 20: SMAC: 08:00:27:f2:9b:7c DMAC: c0:01:24:c0:00:00
  • 65. Page 65 of 185 65 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu Logical flow diagram ############# Application #6 - Basic Network Sniffer ############# #In Scapy, we will use the sniff() function to capture network packets. #To see a list of what commands Scapy has available, run the lsc() function. #Run the ls() command to see ALL the supported protocols. #Run the ls(protocol) command to see the fields and default values for any protocol. #See packet layers with the .summary() function. #See packet contents with the .show() function. #Dig into a specific packet layer using a list index: pkts[3][2].summary()...
  • 66. Page 66 of 185 66 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #...the first index chooses the packet out of the pkts list, the second index chooses the layer for that specific packet. #Using the .command() packet method will return a string of the command necessary to recreate that sniffed packet. #To see the list of optional arguments for the sniff() function: ''' >>> print sniff.__doc__ Sniff packets sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets count: number of packets to capture. 0 means infinity store: wether to store sniffed packets or discard them prn: function to apply to each packet. If something is returned, it is displayed. Ex: ex: prn = lambda x: x.summary() lfilter: python function applied to each packet to determine if further action may be done ex: lfilter = lambda x: x.haslayer(Padding) offline: pcap file to read packets from, instead of sniffing them timeout: stop sniffing after a given time (default: None) L2socket: use the provided L2socket opened_socket: provide an object ready to use .recv() on stop_filter: python function applied to each packet to determine if we have to stop the capture after this packet ex: stop_filter = lambda x: x.haslayer(TCP) ''' #Importing the necessary modules import logging import subprocess #This will suppress all messages that have a lower level of seriousness than error messages, while running or loading Scapy logging.getLogger("scapy.runtime").setLevel(logging.ERROR) logging.getLogger("scapy.interactive").setLevel(logging.ERROR) logging.getLogger("scapy.loading").setLevel(logging.ERROR) try: from scapy.all import * except ImportError: print "Scapy package for Python is not installed on your system." print "Get it from https://pypi.python.org/pypi/scapy and try again." sys.exit()
  • 67. Page 67 of 185 67 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Asking the user for some parameters: interface on which to sniff, the number of packets to sniff, the time interval to sniff, the protocol #Making the necessary configurations print "n! Make sure to run this program as ROOT !n" #Setting network interface in promiscuous mode #Wikipedia: In computer networking, promiscuous mode or "promisc mode"[1] is a mode for a wired network interface controller (NIC) or wireless network interface controller (WNIC)... #...that causes the controller to pass all traffic it receives to the central processing unit (CPU) rather than passing only the frames that the controller is intended to receive. #This mode is normally used for packet sniffing that takes place on a router or on a computer connected to a hub. #Also, when using our setup (VirtualBox-to-GNS3), you should go to the Settings section for the virtual machine you are using... #...select the adapter that connects to the GNS3 network and set Promiscuous Mode: Allow All net_iface = raw_input("* Enter the interface on which to run the sniffer (like 'eth1'): ") subprocess.call(["ifconfig", net_iface, "promisc"], stdout=None, stderr=None, shell=False) print "nInterface %s was set to PROMISC mode." % net_iface print #Asking the user for the number of packets to sniff (the "count" parameter) pkt_to_sniff = raw_input("Enter the number of packets to capture (0 is infinity): ") #Considering the case when the user enters 0 (infinity) if int(pkt_to_sniff) != 0: print "nThe program will capture %d packets." % int(pkt_to_sniff) print elif int(pkt_to_sniff) == 0: print "nThe program will capture packets until the timeout expires." print #Asking the user for the time interval to sniff (the "timeout" parameter) time_to_sniff = raw_input("* Enter the number of seconds to run the capture: ") #Handling the value entered by the user if int(time_to_sniff) != 0: print "nThe program will capture packets for %d seconds." % int(time_to_sniff) print
  • 68. Page 68 of 185 68 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu #Asking the user for any protocol filter he might want to apply to the sniffing process #For this example I chose three protocols: ARP, BOOTP, ICMP #You can customize this to add your own desired protocols proto_sniff = raw_input("* Enter the protocol to filter by (arp|bootp|icmp|0 is all): ") #Considering the case when the user enters 0 (all) if (proto_sniff == "arp") or (proto_sniff == "bootp") or (proto_sniff == "icmp"): print "nThe program will capture only %s packets." % proto_sniff.upper() print elif int(proto_sniff) == 0: print "nThe program will capture all protocols." print #Creating an external file for packet logging file_name = raw_input("* Please give a name to the log file: ") sniffer_log = open(file_name, "w") #Initializing the packet counter packet_no = 0 #This is the function that will be applied to each captured packet #The function will extract some parameters from the packet and then log each packet to an external file def packet_log(pkt): #The packet index global packet_no #Filtering the packets based on the protocol. Using the lower() method to ignore the case when searching for the protocol in the packet. if proto_sniff.lower() in pkt[0][1].summary().lower(): packet_no = packet_no + 1 #Writing the data for each packet to the external file print >>sniffer_log, "Packet " + str(packet_no) + ": " + "SMAC: " + pkt[0].src + " DMAC: " + pkt[0].dst print "n* Starting the capture... Waiting for %s seconds..." % time_to_sniff #Running the sniffing process pkt = sniff(iface=net_iface, count=int(pkt_to_sniff), timeout=int(time_to_sniff), prn=packet_log) #print pkt.show() #Printing the closing message print "n* The timeout of %s seconds has passed." % time_to_sniff
  • 69. Page 69 of 185 69 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu print "* Please check the %s file to see the captured packets.n" % file_name #Closing the log file sniffer_log.close() #End of program. Feel free to modify it, test it, add new protocols to sniff and improve de code whenever you feel the need to.
  • 70. Page 70 of 185 70 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu 2.10. Application #7 - Configuration file comparator (full code, reference: Section 19. Application #7 - Configuration file comparator) This application connects to a router in the network via Telnet, extracts the output of “show running-config” and “show startup-config”, filters the irrelevant lines and finally compares the configurations. Now, I know this can be accomplished using the “show archive config differences”command in Cisco CLI, but I wanted you to know how can this task be accomplished using Python. As with the other applications in this course, the full code is available for download. Based on what you have learned so far in the course, it’s your job now to study, understand and test the code against a network device, as you’ve seen me doing with the previous applications. Feel free to alter the code in any way you want. New functionality of any kind is welcome, enhancements as well. Just make sure to adapt your code to the command output format. Also, please read the first 13 lines in the code carefully, as they are a good introduction to the code that follows. As you can see, the first thing you should do is configure Telnet access on the router and the username and password: username teopy privilege 15 password 0 python line vty 0 4 privilege level 15 login local transport input telnet ssh At line 27, I have defined the ip_validity() function, which takes care of checking whether the IP address of the router, which the user enters at the prompt, is valid or not. You have already seen this kind of validity check in action in the previous applications, so there is nothing new here. The same comment is valid for the file_validity() function (line 46). Both functions are defined at this point and will be called later in the code. At line 61, the telnet() function is defined, which takes a single parameter:command. The value of this parameter will be passed to theconnection.write() method at line 96. Starting with line 108, I defined the user menu, which will accept 3 options, except e - Exit program: 1 - Compare running-config with startup-config 2 - Compare running-config with local file 3 - Compare startup-config with local file I had treated only the first option, comparing the running-config with the startup-config -
  • 71. Page 71 of 185 71 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu lines 115-196, leaving you with the job of coding and testing the other two options, having my code from option 1 as a guideline. Now, let’s look at option 1 for a bit. First, I called the ip_validity() function to get this out of the way. Next, a very important step, I called the telnet()function for each of the two commands I am interested in, and saved the returned output to a separate variable: output_run for the running-config and output_start for the startup-config. Then, I have created (opened for writing) two files, each of them storing the output of the corresponding command. The file names are intuitively chosen. Don’t forget to close the files after writing the contents of those variables, to save the information. Next, I opened the files for reading and used the readlines() method on each file object to store the lines in each file as elements of a list. Of course, then I closed the files. Then, using a for loop, I have filtered the lines in each file which were of no interest to our goal. We are only interested in the lines starting with the one defining the IOS version: “version 12.4” for example. That is actually the first relevant line in each file. Now, after “cleaning” the files, we are left with only the pure router configurations. It’s time to create a new file (file_diff.txt), in which all the config differences are going to be stored. Actually, we are going to compare the two lists obtained with the readlines() method. Finally, using list comprehensions, we are going to find the lines in the running-config which are not present in the startup-config and vice versa. In case there are multiple differences, we use a for loop to iterate over the lists and then print those differences directly into the file_diff.txt file., one per line As stated in the code, the rule is: A "+" sign means the line is present in the RUNNING-CONFIG but not in the STARTUP-CONFIG A "-" sign means the line is present in the STARTUP-CONFIG but not in the RUNNING-CONFIG Now, let’s make a quick test. If you have just started the router and made no config yet, then the startup-config and running-config are the same. No surprise here. But, to make the test more relevant, let’s configure a few things before starting the comparison, without saving the changes to the startup-config. So, let’s go to router R1: R1(config)#username udemy1 password udemy R1(config)#username udemy2 password udemy R1(config)#username udemy3 password udemy Now, these three configurations are the differences between the startup-config and the running-config. We should see them after running our program, saved in the file_diff.txt file. Let’s test this:
  • 72. Page 72 of 185 72 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu root@debian:/home/debian/workingdir# python ConfigFileComp.py Use this tool to: 1 - Compare running-config with startup-config 2 - Compare running-config with local file 3 - Compare startup-config with local file e - Exit program Enter your choice: 1 Enter an IP address: 192.168.2.101 Please wait while the config file is being analyzed... Use this tool to: 1 - Compare running-config with startup-config 2 - Compare running-config with local file 3 - Compare startup-config with local file e - Exit program Enter your choice: e Exiting... See ya... Now let’s check the results. We should see all three commands with a “+”sign, right? root@debian:/home/debian/workingdir# cat file_diff.txt +username udemy1 password 0 udemy +username udemy2 password 0 udemy +username udemy3 password 0 udemy root@debian:/home/debian/workingdir# ...and success! As expected, the three commands are marked as differences, in the file.
  • 73. Page 73 of 185 73 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu Logical flow diagram
  • 74. Page 74 of 185 74 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu ############# Application #7 - Config File Comparator ############# #This program will: # * Connect to a router via Telnet and it will compare the running-config file to the startup-config file on that device (this can be usually done with: show archive config differences) # * Compare a locally stored config file (.txt) with the running-config file or startup-config file running on a router. #Please see the "Python File Operations" section in the course for a recap of the necessary concepts. #Don't forget to configure Telnet access on the router! #username teopy privilege 15 password 0 python #line vty 0 4 # privilege level 15 # login local # transport input telnet ssh #The first part of the program is very similar to Application #2 in the course. import telnetlib import os.path import subprocess import time import sys def ip_validity(): global ip_address #Checking IP validity while True: ip_address = raw_input("Enter an IP address: ") #Checking octets a = ip_address.split('.') if (len(a) == 4) and (1 <= int(a[0]) <= 223) and (int(a[0]) != 127) and (int(a[0]) != 169 or int(a[1]) != 254) and (0 <= int(a[1]) <= 255 and 0 <= int(a[2]) <= 255 and 0 <= int(a[3]) <= 255): break else: print "nThe IP address is INVALID! Please retry!n" continue def file_validity(): while True:
  • 75. Page 75 of 185 75 Python Network Programming – Course Applications Guide by Mihai Cătălin Teodosiu cfg_file = raw_input("Enter config file name and extension: ") #Changing exception message if os.path.isfile(cfg_file) == True: print "nFile was found...n" break else: print "nFile %s does not exist! Please check and try again!n" % cfg_file continue def telnet(command): #Connecting to router via Telnet #Define telnet parameters username = 'teopy' password = 'python' #Specify the Telnet port (default is 23, anyway) port = 23 #Specify the connection timeout in seconds for blocking operations, like the connection attempt connection_timeout = 5 #Specify a timeout in seconds. Read until the string is found or until the timout has passed reading_timeout = 5 #Logging into device connection = telnetlib.Telnet(ip_address, port, connection_timeout) #Waiting to be asked for an username router_output = connection.read_until("Username:", reading_timeout) #Enter the username when asked and a "n" for Enter connection.write(username + "n") #Waiting to be asked for a password router_output = connection.read_until("Password:", reading_timeout) #Enter the password when asked and a "n" for Enter connection.write(password + "n") time.sleep(1) #Setting terminal length for the entire output - disabling pagination connection.write("terminal length 0n") time.sleep(1) #Entering global config mode connection.write("n") connection.write(command + "n") time.sleep(5)