Python Netmiko OSError: Search pattern never detected in send_command_expect: - python

I recently started programming with Python. I work as a network engineer and am currently building a program to pull "state dumps" from Ciena devices. I use netmiko to connect to the device.
Now I always get the following error:
OSError: Search pattern never detected in send_command_expect: 5160_1>
"5160_1>" is the hostname / prompt on the switch. I have read that I can give "expect_string" to a "send_command". Unfortunately, this has no effect and I still get this error.
This is the function with which I create the state dump and call the function for the file download.
def create_sd():
for ip in sw_connect_ips:
try:
sw_connection = ConnectHandler(device_type=sw_dev_type, host=ip, username=sw_usr, password=sw_pw)
try:
print('\nconnnected to host > ' + ip + '\n')
hostname = sw_connection.find_prompt()
print('hostname of device > ' + hostname)
sw_connection.send_command('system server sftp enable', expect_string=hostname)
sw_connection.send_command('configuration save', expect_string=hostname)
sw_output = sw_connection.send_command('system state-dump file-name ' + ip + '_sd_timestamp_' + str(date.hour) + '_' + str(date.minute) + '_' + str(date.second), expect_string=hostname + ' ')
filename = ip + '_sd_timestamp_' + str(date.hour) + '_' + str(date.minute) + '_' + str(date.second)
print('got state-dump ' + filename + ' from host > ' + ip)
logging.debug(sw_output)
logging.debug(sw_connection)
sw_connection.disconnect()
try:
sftp_get(filename, ip)
except:
raise Exception('scp failed')
except:
raise Exception('command does not exist on switch > ' + ip)
except:
raise SSHException('unable to connect to switch check username, password and ip address')
I don't know whether all exceptions make so much sense. Maybe someone has a tip for me.
Thanks in advance.
Edit: What is strange in my opinion is that it only occurs with some switches.

in the command with which the state dump is created, I have increased the "send_command" delay factor to 5.
sw_output = sw_connection.send_command ('system state-dump file-name' + ip + '_sd_timestamp_' + str (date.hour) + '_' + str (date.minute) + '_' + str (date.second) , expect_string = hostname, delay_factor = 5)
As a result, I no longer get a netmiko exception and the program runs without problems.

Related

Python - how to make decision based on a failed command (netmiko and try-except-else)

I am trying to create a test program which will log to Cisco ASA firewalls and collect some data.
I run into a challenge. Some firewalls are single context some are multi-context, but connection is made on admin IP address to all of them. Once connected there is a command "changeto system" which will only be successful on multi-context firewalls. I was thinking to use try-except-else ....
conn = ConnectHandler(device_type= "cisco_asa", ip=host[1], username=u[host[3]], password=p[host[3]], secret=p[host[3]])
print(conn.find_prompt())
try:
output4 = conn.send_command(cmd_system)
except:
# not a multi-context firewall
for cmd in cmd_list_asa:
CONTEXT_OUTPUT = open(chgnr + '__' + host[0] + '_' + d[cmd]+ '_' + testtype , "a")
info = ("running .... " + host[0] + "......." + cmd)
runcommand(info, cmd, CONTEXT_OUTPUT)
CONTEXT_OUTPUT.close()
else:
#multi-context firewall
#collect SYSTEM context data
for cmd in cmd_list_asa:
CONTEXT_OUTPUT = open(chgnr + '__' + host[0] + '_system_' + d[cmd]+ '_' + testtype , "a")
info = ("running .... " + host[0] + "_system......." + cmd)
runcommand(info, cmd, CONTEXT_OUTPUT)
CONTEXT_OUTPUT.close()
#create context list and collect data
output3 = conn.send_command(cmd_contextlist)
list = re.findall("\"(.*?)\"",output3)
for fw in list:
cmd_change = ("changeto context " + fw)
output = conn.send_command(cmd_change)
for cmd in cmd_list_asa:
CONTEXT_OUTPUT = open(chgnr + '__' + host[0] + '_' + fw + '__' + d[cmd]+ '_' + testtype , "a")
info = ("running .... " + host[0] + "_" + fw + "......." + cmd)
runcommand(info, cmd, CONTEXT_OUTPUT)
CONTEXT_OUTPUT.close()
the CONTEXT_OUTPUT is just a fancy way of dynamically generating filename. testype to differentiate between multiple runs and finally all what runcommand does it sends the command...conn.send_command(cmd).
As per my expectation if output4 command fails the except section should be executed if is successful should jump to the else section, but apparently even those firewalls which are not multicontext will run through the else section and skip except.
After talking with my colleague I realized my mistake. Try-expect is for python error handling. When the command fails it still returns an output
...admin> changeto system
^
ERROR: % Invalid input detected at '^' marker.
ERROR: Command authorization failed
...that output has to be assessed so instead of try-expect-else it should be a if-else...
....
output4 = conn.send_command(cmd_system)
if "ERROR" in output4:
# not a multi-context firewall
for cmd in cmd_list_asa:
CONTEXT_OUTPUT = open(chgnr + '__' + host[0] + '_' + d[cmd]+ '_' + testtype , "a")
info = ("running .... " + host[0] + "......." + cmd)
runcommand(info, cmd, CONTEXT_OUTPUT)
CONTEXT_OUTPUT.close()
else:
#multi-context firewall
#collect SYSTEM context data
for cmd in cmd_list_asa:
....

Remove Duplicate IP Addresses with Scapy

I have a script to listen for incoming traffic and print out only the string “IP 1.1.1.1 53" when a packet hits the line. But now that I’m doing IP resolve on the IPs, I need to access the “ip_src” variable and only do the geolocation once on each ip, rather than resolve the same IP over and over as they come in. My current code is:
#!/usr/bin/python3
from scapy.all import *
import ipinfo
def print_summary(pkt):
if IP in pkt:
ip_src=pkt[IP].src
if UDP in pkt:
udp_sport=pkt[UDP].sport
access_token = ''
handler = ipinfo.getHandler(access_token)
match = handler.getDetails(ip_src)
c = match.details.get('city')
s = match.details.get('region')
strang = ("IP " + str(ip_src) + " " + str(udp_sport) + " " + str(c) + ", " + str(s))
print(strang)
sniff(filter="",prn=print_summary)
As you can see the “print_summary” function is called by “prn” which is called for each pkt. I basically want to mimic the functionality of uniq and sort, since they can successfully filter out duplicates from a file, but I’d like to have it all in one script.
EDIT - Trying Set():
So using the code:
from scapy.all import *
def print_summary(pkt):
if IP in pkt:
ip_src=pkt[IP].src
if UDP in pkt:
udp_sport=pkt[UDP].sport
lines_set = set(ip_src)
strang = ("IP " + str(ip_src) + " " + str(udp_sport))
if ip_src not in lines_set:
for line in lines_set:
print(line)
sniff(filter="",prn=print_summary)
I get the output: (in the terminal each character has a trailing newline)
2 . 3 5 8 0 1 2 . 4 8 0 1 . 6
This adds a set variable to keep track of which addresses you have already seen.
#!/usr/bin/python3
from scapy.all import *
import ipinfo
seen = set()
def print_summary(pkt):
if IP in pkt:
ip_src=pkt[IP].src
if UDP in pkt and ip_src not in seen:
seen.add(ip_src)
udp_sport=pkt[UDP].sport
access_token = ''
handler = ipinfo.getHandler(access_token)
match = handler.getDetails(ip_src)
c = match.details.get('city')
s = match.details.get('region')
strang = ("IP " + str(ip_src) + " " + str(udp_sport) + " " + str(c) + ", " + str(s))
print(strang)
sniff(filter="ip",prn=print_summary)
I also changed the indentation of the second if to avoid getting a traceback if somehow you would receive a packet which doesn't have the IP member; though I also updated the filter expression to hopefully prevent that from ever happening in the first place.

Trying To Scan IP For Getting Domain Name In Python With Socket

I am trying to scan domain name from ip address.
That's why i took a input from file and split that, amd changing the last 3digit with loop . and checking all random ip. But It Shows Nothing. And there is a valid ip with domain.
f = open('ip.txt', 'r')
r = f.readline()
f.close()
ips = r.split(".")
ipc = ips[0] + "." + ips[1] + "." + ips[2] + "."
for i in range(0, 256):
ipm = ipc + str(i)
ip = str('"' + ipm + '"')
try:
socket.gethostbyaddr(ip)
except:
pass
Your indentation here is wrong, try this:
for i in range(0,256):
ipm=ipc+str(i)
ip=str('"'+ipm+'"')
try:
socket.gethostbyaddr(ip)
except:
pass
Edit: I also suspect that you can simply do ip = str(ipm), without needing to add the extra double quotes.

Using Python 3.4 to Ping a network then report address, dns name, etc.

I wanted to create a Python program that does several things. Ping all addresses in a predefined network, gather the DNS information, write a file with IP address, DNS name, ping fail or pass, date. Then run and email the resulting file to myself once a week, every Friday. I have created this program and will post my own answer. I am new to Python and was able to get this written with the help from other answers posted on this site. Thanks to all those who contributed answers on this site. Hope the answer I post will help someone else.
#!/usr/bin/python3.4
#Above statement makes sure you are using version 3.4
#when multiple versions are installed. has to be the 1st line.
# Import modules
import subprocess
import socket
import errno
import time
import datetime
import ipaddress
today = datetime.date.today()
# define DNS lookup and error handling
# return none,none,none needed otherwise if no DNS record
# the routine errors out and the program stops
def lookup(addr):
try:
return socket.gethostbyaddr(addr)
except socket.herror:
return None, None, None
# Prompt the user to input a network address
# commented out the prompt for input so it can run unattended
# net_addr = input("Enter a network address in CIDR
format(ex.192.168.1.0/24): ")
net_addr = ('192.168.1.0/24')
# Create the network
ip_net = ipaddress.ip_network(net_addr)
# Get all hosts on that network
all_hosts = list(ip_net.hosts())
# Configure subprocess to hide the console window
# removed code due to errors not windows linux
# setup online and offline count variables
offCnt = 0
onCnt = 0
# Open file and or create if it doesn't exist.
# file to be overwritten each time the program is run.
file = open("lab-ip.doc","w")
# For each IP address in the subnet,
# run the ping command with subprocess.popen interface
# Grab the DNS information for each IP address
# Print to console add counters and write to file.
for i in range(len(all_hosts)):
output = subprocess.Popen(['ping', '-c', '2', str(all_hosts[i])],
stdout=subprocess.PIPE).communicate()[0]
name,alias,addresslist = lookup(str(all_hosts[i]))
if "Destination Host Unreachable" in output.decode('utf-8'):
print(str(all_hosts[i]), " Ping Fail", str(name), today)
file.write(str(all_hosts[i]) + " Ping Fail - " + str(name) + " " + str(today) + "\n")
offCnt = offCnt + 1
elif "Request timed out" in output.decode('utf-8'):
print(str(all_hosts[i]), " Ping Fail", str(name), today)
file.write(str(all_hosts[i]) + " Ping Fail - " + str(name) + " " + str(today) + "\n")
offCnt = offCnt + 1
else:
print(str(all_hosts[i]), " Ping Pass", str(name), today)
file.write(str(all_hosts[i]) + " Ping Pass - " + str(name) + " " + str(today) + "\n")
onCnt = onCnt + 1
print ("Pass count = ", str(onCnt))
file.write("Pass count = " + str(onCnt))
print ("Fail count = ", str(offCnt))
file.write(" Fail count = " + str(offCnt))
file.close()
# Import yagmail for the actual sending function
import yagmail
yag = yagmail.SMTP('Gmail-id', 'gmail-pswd')
yag.send('email#email.com', subject = "Lab-ip List",contents = 'lab-ip.doc')
yag.send('email2#email2.com', subject = "Lab-ip List",contents = 'lab-ip.doc')
#end

Detect ARP poisoning using scapy

I have captured some traffic and stored on a .pcap file. In there, an ARP poisoning attack occured.
Is there a way of detecting the attacker's IP and MAC adress and victim's IP and MAC adress using scapy in a python script?
I believe a script like this one would do the job
#! /usr/bin/python
from scapy.all import *
pkts = rdpcap('capture2.pcap')
#these are from wireshark
ipadr=['192.168.0.1','192.168.0.2','192.168.0.3','192.168.0.30']
macadr['00:03:ff:98:98:01','00:03:ff:98:98:02','00:03:ff:98:98:03','00:03:ff:98:98:30']
c=-1
for p in pkts:
c=c+1
if p.haslayer(ARP):
#find a packet where p.dst and p.pdst isn't a valid pair
if p.dst != 'ff:ff:ff:ff:ff:ff':
if not(( ipadr[0]==p.pdst and macadr[0]==p.dst ) or ( ipadr[1]==p.pdst and macadr[1]==p.dst) or ( ipadr[2]==p.pdst and macadr[2]==p.dst ) or ( ipadr[3]==p.pdst and macadr[3]==p.dst )) :
print 'packet data ' +p.psrc +" "+p.src+" " + p.pdst + " " + p.dst +" "+str(c)
print 'packet number = ' + str(c)
print 'MAC of attacker = ' + p.dst
print 'IP of attacker = ' + ipadr[macadr.index(p.dst)]
print 'MAC of target = ' + p.src
print 'IP of target = ' + p.psrc

Categories

Resources