Python quick dirty ping scan subnet

This script will automatically ping scan the subnet your host is connected to. To do this it does the following:

  • Determines you primary IP address (By trying to open a socket and then printing out which interface is used to get to the internet),This is the interface that has the default route to the internet. It will work even if you do not have internet connectivity)

  • It then determines the interface name (for example eth0) of the primary IP

  • It then gets the subnet mask of the primary interface (usually eth0 but it doesn’t assume that it automatically determines that)

  • Prints out the CIDR notation of the network address of the primary interface.

  • It then creates a list of all usable IP addresses in that network

  • Then it does the magic you came here for: A very fast ping scan of all usable IPs in that network using subprocesses so its as fast as it can be.

  • Once complete it will simply print only addresses that responded to the ping

Only tested on linux (Ubuntu 16.0.4)

I wanted a pure bash script, but need to use python which is unfortunate because some of the systems don’t have it.

Module dependency which can be installed using easy_install (you should have this command on your system if you have python) like so:

easy_install netaddr

Here is the python script that will ping scan the current subnet very quickly. It is no artwork.

#!/usr/bin/env python
import subprocess
"""Ping all usable IP address of the currently attached subet."""
from netaddr import *
from netaddr import IPNetwork
import os
import socket
import multiprocessing
def get_ip_address():
   s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   s.connect(("255.255.255.1", 80))
   return s.getsockname()[0]

def pinger( job_q, results_q ):
   DEVNULL = open(os.devnull,'w')
   while True:
      ip = job_q.get()
      if ip is None: break

      try:
            #print "ping", ip
            subprocess.check_call(['ping','-c1', '-W', '1', str(ip)],
                                 stdout=DEVNULL )
            results_q.put(ip)
      except:
            #print "ping failed", ip
            pass

jobs = multiprocessing.Queue()
results = multiprocessing.Queue()

ip = get_ip_address()
proc = subprocess.Popen('ifconfig',stdout=subprocess.PIPE)
while True:
   line = proc.stdout.readline()
   if ip.encode() in line:
      break
mask = line.rstrip().split(b':')[-1].replace(b' ',b'').decode()
#print mask
cidrnet = ip + "/" +  mask
#print cidrnet

netaddress = str(IPNetwork(cidrnet).cidr)
print "Ping sweeping: ", netaddress
#netbits = sum([bin(int(x)).count("1") for x in mask.split(".")])
#print netbits
l = list(IPNetwork(netaddress).iter_hosts())
#All the IP Adresses
#print l

pool = [ multiprocessing.Process(target=pinger, args=(jobs,results)) for i in l ]


for p in pool:
   p.start()

for i in l:
   jobs.put(str(i))

for p in pool:
   jobs.put(None)


for p in pool:
   p.join()

while not results.empty():
   ip = results.get()
   print ip

Comments

comments powered by Disqus