Python IP range checker

Often you find yourself checking a network to see if what IP’s are free. It’s made more complicated with blocking/firewalls. MicroSoft defender blocks ICMP by default for example.

./ip-check -h
Purpose:
      Check a network range, optionally storing the output
      It's only checking for ICMP and port windows RDP
Usage: 
      ./ip-check.py [-h] [[-o ] -n ]
Example:
      ./ip-check.py -o 192.168.1.txt -n 192.168.1.0/23
Further:
     It will put the output to the screen and will put the result
     in a file called result.txt even if no output file is specified.
     It also lists out the non-answering machines to the screen after
     it completes the range.


#!/usr/bin/env python3
import ipaddress
import socket
import sys
import subprocess
import shutil
import os
import getopt

try:
    opts, args = getopt.getopt(sys.argv[1:], "ho:n:v", ["help", "network="])
except getopt.GetoptError as err:
    print(err)
    sys.exit()


def usage():
    print("Purpose:")
    print("      Check a network range, optionally storing the output")
    print("      It\'s only checking for ICMP and port windows RDP")
    print("Usage: ")
    print("      %s [-h] [[-o ] -n ]" % sys.argv[0])
    print("Example:")
    print("      %s -o 192.168.1.txt -n 192.168.1.0/23" % sys.argv[0])
    print("Further:")
    print("     It will put the output to the screen and will put the result")
    print("     in a file called result.txt even if no output file is specified.")
    print("     It also lists out the non-answering machines to the screen after")
    print("     it completes the range.")


outfile = "result.txt"
ranges = "x"
for name, value in opts:
    if name in ["-h", "--help"]:
        usage()
        sys.exit()
    elif name in ["-o", "--output"]:
        outfile = str(value)
    elif name in ["-n", "--network"]:
        ranges = [str(value)]
    else:
        usage()
        sys.exit()

if ranges == "x":
    print("Must specify a LAN eg. -n 192.168.0.0/24")
    sys.exit()

# ranges  = ["147.197.131.31/32", "147.197.131.33"]
# ranges = ["147.197.108.0/24", "147.197.131.0/24"]


def pscan(ip, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    check_this = (ip, port)
    s.settimeout(0.25)
    con = s.connect_ex(check_this)
    s.close()
    if con == 0:
        return True
    else:
        return False


def check_host(ip):
    status = ""
    bad_result = "100% packet loss"
    p = subprocess.Popen(
        ["timeout", "5", "ping", "-c", "1", "-w", "1", ip],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    result = str(p.communicate()).strip("\\\n")
    ptr, alias, sock = lookup(ip)
    if bad_result in result:
        if pscan(ip, 3389):
            status = status + "OKwin"
        else:
            status = status + "NOANSWER"
    else:
        status = status + "OKicmp"
    return ptr, status, ip


def lookup(addr):
    try:
        return socket.gethostbyaddr(addr)
    except socket.herror:
        return "NoDnsEntry", None, addr


dict = {}
if os.path.exists(outfile):
    shutil.move(outfile, outfile + ".bak")
f = open(outfile, "a")
for range in ranges:
    for ip in ipaddress.IPv4Network(range):
        ptr, status, ip = check_host(str(ip))
        dict[ip] = status
        print(ip.ljust(16), status.ljust(15), ptr.ljust(40))
        f.write(
            "%s%s%s\n" % (ip.ljust(16, " "), status.ljust(15, " "), ptr.ljust(40, " "))
        )

for i, s in dict.items():
    if s != "OK":
        print(i.ljust(15), s.ljust(15), lookup(i)[0])

f.close()

Leave a Reply

Your email address will not be published. Required fields are marked *