0

I have been at this for hours and I cannot figure it out. The script is supposed to scan servers for port 22. However, the very last line of the code errors out with "KeyError". What is confusing is that this only happens when I use a FOR loop or I create a function and pass it the value.

If the code is out of a loop the last line works, no matter if it is a hard coded IP or a variable.

If at the last line I enter loop_1 with out the single quotes I get the following error: Wrong type for [host], should be a string was class 'netaddr.ip.IPAddress'

I converted it to a string by adding just before the last line of the code.

value = str(loop_1)

That in turns gives an error of: KeyError: '10.0.0.0'

Here is the script.

import nmap
from netaddr import *

nm = nmap.PortScanner()

for loop_1 in IPNetwork('10.0.0.0/26'):
    print nm.scan('loop_1', '22')
    print nm['loop_1']['tcp'][22]['state']

2 Answers2

3

If the address is not up and reachable you will get a keyerror from nmap:

import nmap
from netaddr import IPNetwork

nm = nmap.PortScanner()

for loop_1 in IPNetwork('10.0.0.0/26'):
    print(nm.scan(loop_1.format(), '22'))
    try:
       print(nm[loop_1.format()]['tcp'][22]['state'])
    except KeyError as e:
        pass

working in ipython:

In [5]: paste
import nmap
from netaddr import IPNetwork

nm = nmap.PortScanner()

for loop_1 in IPNetwork('192.168.43.65/30'):
    print(loop_1)
    print(nm.scan(loop_1.format(), '22'))
    try:
       print(nm[loop_1.format()]['tcp'][22]['state'])
    except KeyError as e:
        pass

    ## -- End pasted text --
    192.168.43.64
    {'nmap': {'scanstats': {'uphosts': u'0', 'timestr': u'Wed Dec 24 02:41:51 2014', 'downhosts': u'1', 'totalhosts': u'1', 'elapsed': u'3.06'}, 'scaninfo': {u'tcp': {'services': u'22', 'method': u'connect'}}, 'command_line': u'nmap -oX - -p 22 -sV 192.168.43.64'}, 'scan': {}}
    192.168.43.65
    {'nmap': {'scanstats': {'uphosts': u'0', 'timestr': u'Wed Dec 24 02:41:55 2014', 'downhosts': u'1', 'totalhosts': u'1', 'elapsed': u'3.05'}, 'scaninfo': {u'tcp': {'services': u'22', 'method': u'connect'}}, 'command_line': u'nmap -oX - -p 22 -sV 192.168.43.65'}, 'scan': {}}
    192.168.43.66
    {'nmap': {'scanstats': {'uphosts': u'1', 'timestr': u'Wed Dec 24 02:42:01 2014', 'downhosts': u'0', 'totalhosts': u'1', 'elapsed': u'6.14'}, 'scaninfo': {u'tcp': {'services': u'22', 'method': u'connect'}}, 'command_line': u'nmap -oX - -p 22 -sV 192.168.43.66'}, 'scan': {u'192.168.43.66': {'status': {'state': u'up', 'reason': u'syn-ack'}, 'hostname': u'lab', 'vendor': {}, 'addresses': {u'ipv4': u'192.168.43.66'}, u'tcp': {22: {'product': '', 'state': u'open', 'version': '', 'name': u'ssh', 'conf': u'10', 'extrainfo': u'protocol 2.0', 'reason': u'syn-ack', 'cpe': ''}}}}}
    open # only address up so only open or closed received

If you want a list of ips and whether the port is open or not up can use nmap exclusively:

nm = nmap.PortScanner()

nm.scan(hosts='10.0.0.0/26',ports="22")
results = [[ip, nm[ip]['tcp'][22]['state']] for ip in nm.all_hosts()]

print("ip {}".format(" ".join(*results)))
ip 10.0.0.1 open
....
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Right. I can reach up to that point but it still does not solve the issue with line print nm['loop_1']['tcp'][22]['state'] This line, if not part of a loop or a function will print the state of port 22. – George Mastrokostas Dec 24 '14 at 02:17
  • I was using 'loop_1' but it just prints the key "scan". The same goes if I use print print(nm[loop_1.format()]['tcp'][22]['state']) – George Mastrokostas Dec 24 '14 at 02:27
  • it prints open or closed for me `open`, don't use nm['loop_1'] that is simply using the string `'loop_1'`, are you using the code exactly as posted? – Padraic Cunningham Dec 24 '14 at 02:29
  • Right. What I am trying to do, which I am not able to do in my original code, is to just have it return "Open" or "Close" while ignoring all the other info. That is the main problem that I have. I do not know how to isolate it. I just want that particular information nothing else. – George Mastrokostas Dec 24 '14 at 02:32
  • I will add the code running and working on my machine, it works exactly as you want but you will only see open or closed when you have an ip that is **up** emphasis on the up – Padraic Cunningham Dec 24 '14 at 02:33
  • to see an example, pass your local ip as a string like `"192.168.43.65"` in place of `loop_1.format()` an you will see what I mean – Padraic Cunningham Dec 24 '14 at 02:35
  • I am playing around with and I am starting to understand what you originally said. My original code craps out when it cannot reach a specific IP. What I am trying to do now is to isolate the OPEN only. Right now it is giving me results in the format of: None '10.0.0.27' None '10.0.0.28' None open None '10.0.0.30' Thank you for your help. I have been trying for several hours to figure this out :( I really appreciate it. – George Mastrokostas Dec 24 '14 at 02:42
  • so the first print is returning None sometimes? – Padraic Cunningham Dec 24 '14 at 02:48
  • Yes. I modified how it outputs the format a bit by doing the following: 'code' import nmap from netaddr import IPNetwork nm = nmap.PortScanner() for loop_1 in IPNetwork('10.0.0.1/26'): (nm.scan(loop_1.format(), '22')).get('state') try: state = (nm[loop_1.format()]['tcp'][22]['state']) if state == "open": print loop_1, " IS ", state elif state == "closed": pass except KeyError as e: print(e) 'code' I really appreciate your help. This is my second month doing Python and there are so many things to learn. – George Mastrokostas Dec 24 '14 at 05:18
0

Your loop code is broken:

for loop_1 in IPNetwork('10.0.0.0/26'):
    print nm.scan('loop_1', '22')
    print nm['loop_1']['tcp'][22]['state']

loop_1 at the top is a variable which is the address to scan. But then you later use a literal string 'loop_1' which is not the variable. You said if you use loop_1 without quotes you get an error saying a string is needed instead of an IPAddress...so you must simply read the documentation for the IPAddress class to find how to convert it to a string (perhaps just str(loop_1)?) before putting it in the brackets.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • that is not the problem – Padraic Cunningham Dec 24 '14 at 01:55
  • I tried to convert to a string and then it gives me a "KeyError: 10.0.0.0" – George Mastrokostas Dec 24 '14 at 02:01
  • @PadraicCunningham: it's interesting how you say this is not the problem, yet your answer includes my proposed fixes. I see you found additional things to fix, but claiming that use of a string where a variable was intended is "not the problem" seems a stretch. – John Zwinck Dec 24 '14 at 02:20
  • the problem is namp will throw a keyerror for any ip that does not return any result so that is the real issue, the OP had also already had tried `str(loop_1)` which works the same as loop_1.format(). – Padraic Cunningham Dec 24 '14 at 02:24