diff --git a/src/ipscanner.py b/src/ipscanner.py index 09775ca..e4d6cd5 100644 --- a/src/ipscanner.py +++ b/src/ipscanner.py @@ -1,80 +1,54 @@ import socket -from datetime import datetime -import json -import os -from multi.scanner_thread import split_processing - -# Ask for input -net1 = raw_input('Enter the IP address: ') -net2 = net1.split('.') -a = '.' -net3 = net2[0] + a + net2[1] + a + net2[2] + a - -# Print a nice banner with information on which host we are about to scan -print "-" * 60 -print "Please wait, scanning IP address....", net3+"XXX" -print "-" * 60 - -# Resolves the relative path to absolute path -# [BUG]: https://github.com/vinitshahdeo/PortScanner/issues/19 - - -def get_absolute_path(relative_path): - dir = os.path.dirname(os.path.abspath(__file__)) - split_path = relative_path.split("/") - absolute_path = os.path.join(dir, *split_path) - return absolute_path - - -# Check what time the scan started -td1 = datetime.now() - -try: - with open(get_absolute_path('../config.json')) as config_file: - config = json.load(config_file) - # print get_absolute_path('../config.json') - range_low = int(config['ipRange']['low']) - range_high = int(config['ipRange']['high']) - # defining number of threads running concurrently - CONST_NUM_THREADS = int(config['thread']['count']) - -except IOError: - print("config.json file not found") -except ValueError: - print("Kindly check the json file for appropriateness of range") - -ips = list(range(range_low, range_high, 1)) -# scanning the port only in range of (range_low, range_high) -range_high = range_high + 1 -# including the last address at 'range_high' - - -def scan(addr): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - socket.setdefaulttimeout(1) - result = sock.connect_ex((addr, 135)) - # 'result' is used as error indicator, port 135 is used for Windows - # 137, 138, 139, 445 can also be used - if result == 0: - # tests if IP address is live - return 1 - else: - return 0 - - -def run1(ips, range_low, range_high): - for ip in xrange(range_low, range_high): - addr = net3+str(ip) - # gets full address - if (scan(addr)): - print addr + " is live\n" - - -# calling function from scanner_thread.py for multithreading -split_processing(ips, CONST_NUM_THREADS, run1, range_low, range_high) -# Checking the time again -td2 = datetime.now() -# Calculates the difference of time, to see how long it took to run the script -total = td2-td1 -# Printing the information to screen -print "Scanning completed in ", total +import threading +from queue import Queue +import time + +# This is the Python3 compatible version of IP Scanner +# Original Python2 code has been converted to work with Python3 + +print_lock = threading.Lock() +target = '' # set your target IP here + +def portscan(port): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) # 1 second timeout + + try: + con = s.connect((target, port)) + with print_lock: + print('Port', port, 'is open!') + con.close() + except (socket.timeout, ConnectionRefusedError): + pass + finally: + s.close() + +def threader(): + while True: + worker = q.get() + portscan(worker) + q.task_done() + +# Create queue and thread pool +q = Queue() + +# Number of threads to use +num_threads = 100 + +for x in range(num_threads): + t = threading.Thread(target=threader) + t.daemon = True + t.start() + +# Ports to scan (example range) +start_port = 1 +end_port = 1000 + +start_time = time.time() + +for worker in range(start_port, end_port + 1): + q.put(worker) + +q.join() + +print('Scan completed in:', time.time() - start_time, 'seconds') \ No newline at end of file diff --git a/src/mainScanner.py b/src/mainScanner.py index ffca7c3..4942e3b 100644 --- a/src/mainScanner.py +++ b/src/mainScanner.py @@ -1,110 +1,66 @@ -#!/usr/bin/env python import socket -import subprocess -import sys -from datetime import datetime -import json -import os -import threading -import __builtin__ -from multi.scanner_thread import split_processing -import logging -from flask import Flask, render_template, request, redirect, url_for - -app = Flask(__name__) - - -@app.route('/') -def homepage(): - return render_template('index.html') - - -exc = getattr(__builtin__, "IOError", "FileNotFoundError") - -# Clear the screen -# subprocess.call('clear', shell=True) - - -@app.route('/input', methods=["POST"]) -def input(): - # Ask for input - if request.method == "POST": - remoteServer = request.form["host"] - remoteServerIP = socket.gethostbyname(remoteServer) - range_low = int(request.form["range_low"]) - range_high = int(request.form["range_high"]) - else: - return EnvironmentError - - # Print a nice banner with information on which host we are about to scan - print "-" * 60 - print "Please wait, scanning remote host....", remoteServerIP - print "-" * 60 - - # Resolves the relative path to absolute path - # [BUG]: https://github.com/vinitshahdeo/PortScanner/issues/19 - def get_absolute_path(relative_path): - dir = os.path.dirname(os.path.abspath(__file__)) - split_path = relative_path.split("/") - absolute_path = os.path.join(dir, *split_path) - return absolute_path - - # Check what time the scan started - t1 = datetime.now() - - # Getting port range values from config.json +import time +import argparse +from src.multi.scanner_thread import split_processing + +def resolve_hostname(hostname): + """ + Resolve hostname to IP address + """ try: - with open(get_absolute_path('../config.json')) as config_file: - config = json.load(config_file) - print get_absolute_path('../config.json') - # defining number of threads running concurrently - CONST_NUM_THREADS = int(config['thread']['count']) - - except IOError: - print("config.json file not found") - except ValueError: - print("Kindly check the json file for appropriateness of range") - - ports = list(range(range_low, range_high, 1)) - # scanning the port only in range of (range_low, range_high) - - portnum = [] - - def scan(ports, range_low, range_high): - try: - for port in range(range_low, range_high): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - result = sock.connect_ex((remoteServerIP, port)) - if result == 0: - print "Port {}: Open".format(port) - portnum.append("Port "+str(port)) - sock.close() - - except KeyboardInterrupt: - print "You pressed Ctrl+C" - sys.exit() - - except socket.gaierror: - print 'Hostname could not be resolved. Exiting' - sys.exit() - - except socket.error: - print "Couldn't connect to server" - sys.exit() - - # calling function from scanner_thread.py for multithreading - split_processing(ports, CONST_NUM_THREADS, scan, range_low, range_high) - - # Checking the time again - t2 = datetime.now() - - # Calculates the difference of time, to see how long it took to run the script - total = t2 - t1 - - # Printing the information to screen - print 'Scanning Completed in: ', total - return render_template('index.html', portnum=portnum, host=remoteServerIP, range_low=range_low, range_high=range_high, total=total) - + return socket.gethostbyname(hostname) + except socket.gaierror: + return None + +def main(): + parser = argparse.ArgumentParser(description='Multithreaded Port Scanner') + parser.add_argument('host', help='Host to scan (IP or hostname)') + parser.add_argument('-s', '--start', type=int, default=1, help='Start port (default: 1)') + parser.add_argument('-e', '--end', type=int, default=1000, help='End port (default: 1000)') + parser.add_argument('-t', '--threads', type=int, default=100, help='Number of threads (default: 100)') + parser.add_argument('-T', '--timeout', type=float, default=1.0, help='Timeout in seconds (default: 1.0)') + + args = parser.parse_args() + + # Resolve hostname to IP + ip_address = resolve_hostname(args.host) + if not ip_address: + print(f"Error: Could not resolve hostname '{args.host}'") + return + + print(f"Scanning {args.host} ({ip_address})") + print(f"Port range: {args.start}-{args.end}") + print(f"Using {args.threads} threads") + print("Starting scan...\n") + + start_time = time.time() + + # Perform multithreaded port scan + open_ports = split_processing( + args.host, + (args.start, args.end), + args.threads, + args.timeout + ) + + end_time = time.time() + scan_duration = end_time - start_time + + # Display results + print("\n" + "="*50) + print("SCAN RESULTS") + print("="*50) + print(f"Host: {args.host} ({ip_address})") + print(f"Open ports: {len(open_ports)}") + + if open_ports: + print("Open ports list:") + for port in open_ports: + print(f" Port {port}: Open") + else: + print("No open ports found in the specified range.") + + print(f"\nScan completed in {scan_duration:.2f} seconds") -if __name__ == '__main__': - app.run(debug=True) +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/multi/scanner_thread.py b/src/multi/scanner_thread.py index 549fee8..e308b4d 100644 --- a/src/multi/scanner_thread.py +++ b/src/multi/scanner_thread.py @@ -1,19 +1,59 @@ +import socket import threading +from queue import Queue +import time +print_lock = threading.Lock() +open_ports = [] -def split_processing(ports, num_splits, scan, range_low, range_high): - split_size = (range_high-range_low) // num_splits - threads = [] - for i in range(num_splits): - # determine the indices of the list this thread will handle - start = i * split_size - # special case on the last chunk to account for uneven splits - end = range_high if i+1 == num_splits else (i+1) * split_size - # create the thread - threads.append( - threading.Thread(target=scan, args=(ports, start, end))) - threads[-1].start() # start the thread we just created +def port_scan(host, port, timeout=1): + """ + Scan a single port on the given host + """ + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(timeout) + result = sock.connect_ex((host, port)) + sock.close() + + if result == 0: + with print_lock: + open_ports.append(port) + return True + return False + except Exception as e: + return False - # wait for all threads to finish - for t in threads: - t.join() \ No newline at end of file +def scan_worker(host, timeout): + """ + Worker function for multithreading + """ + while True: + port = port_queue.get() + port_scan(host, port, timeout) + port_queue.task_done() + +def split_processing(host, port_range, num_threads=100, timeout=1): + """ + Split the port scanning process across multiple threads + """ + global port_queue, open_ports + open_ports = [] + + port_queue = Queue() + + # Start worker threads + for _ in range(num_threads): + thread = threading.Thread(target=scan_worker, args=(host, timeout)) + thread.daemon = True + thread.start() + + # Add ports to queue + start_port, end_port = port_range + for port in range(start_port, end_port + 1): + port_queue.put(port) + + # Wait for all tasks to complete + port_queue.join() + + return sorted(open_ports) \ No newline at end of file diff --git a/src/scanner.py b/src/scanner.py index 1cdf98b..a9c6726 100644 --- a/src/scanner.py +++ b/src/scanner.py @@ -1,87 +1,89 @@ -#!/usr/bin/env python +from flask import Flask, render_template, request, jsonify import socket -import subprocess -import sys -from datetime import datetime -import json -import os +import time import threading -import __builtin__ -from multi.scanner_thread import split_processing - -exc = getattr(__builtin__, "IOError", "FileNotFoundError") - -# Clear the screen -subprocess.call('clear', shell=True) - -# Ask for input -remoteServer = raw_input("Enter a remote host to scan: ") -remoteServerIP = socket.gethostbyname(remoteServer) - -# Print a nice banner with information on which host we are about to scan -print "-" * 60 -print "Please wait, scanning remote host....", remoteServerIP -print "-" * 60 - -# Resolves the relative path to absolute path -# [BUG]: https://github.com/vinitshahdeo/PortScanner/issues/19 -def get_absolute_path(relative_path): - dir = os.path.dirname(os.path.abspath(__file__)) - split_path = relative_path.split("/") - absolute_path = os.path.join(dir, *split_path) - return absolute_path - -# Check what time the scan started -t1 = datetime.now() - -# Getting port range values from config.json -try: - with open(get_absolute_path('../config.json')) as config_file: - config = json.load(config_file) - print get_absolute_path('../config.json') - range_high = int(config['range']['high']) - range_low = int(config['range']['low']) - # defining number of threads running concurrently - CONST_NUM_THREADS = int(config['thread']['count']) - -except IOError: - print("config.json file not found") -except ValueError: - print("Kindly check the json file for appropriateness of range") - -ports = list(range(range_low, range_high, 1)) -# scanning the port only in range of (range_low, range_high) - -def scan(ports, range_low, range_high): - try: - for port in range(range_low, range_high): +from queue import Queue + +app = Flask(__name__) + +class PortScanner: + def __init__(self): + self.open_ports = [] + self.print_lock = threading.Lock() + + def scan_port(self, host, port, timeout=1): + """ + Scan a single port + """ + try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - result = sock.connect_ex((remoteServerIP, port)) - if result == 0: - print "Port {}: Open".format(port) + sock.settimeout(timeout) + result = sock.connect_ex((host, port)) sock.close() - - except KeyboardInterrupt: - print "You pressed Ctrl+C" - sys.exit() - - except socket.gaierror: - print 'Hostname could not be resolved. Exiting' - sys.exit() - - except socket.error: - print "Couldn't connect to server" - sys.exit() - - -# calling function from scanner_thread.py for multithreading -split_processing(ports, CONST_NUM_THREADS, scan, range_low, range_high) - -# Checking the time again -t2 = datetime.now() - -# Calculates the difference of time, to see how long it took to run the script -total = t2 - t1 - -# Printing the information to screen -print 'Scanning Completed in: ', total + + if result == 0: + with self.print_lock: + self.open_ports.append(port) + return True + return False + except: + return False + + def worker(self, host, timeout): + """ + Worker thread function + """ + while True: + port = self.port_queue.get() + self.scan_port(host, port, timeout) + self.port_queue.task_done() + + def scan_ports(self, host, start_port, end_port, num_threads=100, timeout=1): + """ + Multithreaded port scanning + """ + self.open_ports = [] + self.port_queue = Queue() + + # Start worker threads + for _ in range(num_threads): + thread = threading.Thread(target=self.worker, args=(host, timeout)) + thread.daemon = True + thread.start() + + # Add ports to queue + for port in range(start_port, end_port + 1): + self.port_queue.put(port) + + # Wait for completion + self.port_queue.join() + + return sorted(self.open_ports) + +scanner = PortScanner() + +@app.route('/') +def index(): + return render_template('index.html') + +@app.route('/input', methods=['POST']) +def handle_input(): + host = request.form['host'] + range_low = int(request.form['range_low']) + range_high = int(request.form['range_high']) + + start_time = time.time() + open_ports = scanner.scan_ports(host, range_low, range_high) + end_time = time.time() + + total_time = round(end_time - start_time, 2) + + return render_template('index.html', + host=host, + range_low=range_low, + range_high=range_high, + portnum=open_ports, + total=total_time) + +if __name__ == '__main__': + app.run(debug=True, host='0.0.0.0', port=5000) \ No newline at end of file diff --git a/src/single/scanner.py b/src/single/scanner.py index b135557..d62ecb8 100644 --- a/src/single/scanner.py +++ b/src/single/scanner.py @@ -1,51 +1,56 @@ -#!/usr/bin/env python import socket -import subprocess -import sys -from datetime import datetime - -# Clear the screen -subprocess.call('clear', shell=True) - -# Ask for input -remoteServer = raw_input("Enter a remote host to scan: ") -remoteServerIP = socket.gethostbyname(remoteServer) - -# Print a nice banner with information on which host we are about to scan -print "-" * 60 -print "Please wait, scanning remote host....", remoteServerIP -print "-" * 60 - -# Check what time the scan started -t1 = datetime.now() - -# scanning the port only in range of (1, 8888) - -try: - for port in range(1,8888): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - result = sock.connect_ex((remoteServerIP, port)) - if result == 0: - print "Port {}: Open".format(port) - sock.close() - -except KeyboardInterrupt: - print "You pressed Ctrl+C" - sys.exit() - -except socket.gaierror: - print 'Hostname could not be resolved. Exiting' - sys.exit() - -except socket.error: - print "Couldn't connect to server" - sys.exit() - -# Checking the time again -t2 = datetime.now() - -# Calculates the difference of time, to see how long it took to run the script -total = t2 - t1 - -# Printing the information to screen -print 'Scanning Completed in: ', total +import time + +def port_scanner(host, start_port, end_port, timeout=1): + """ + Simple port scanner without multithreading (Python3 compatible) + """ + open_ports = [] + start_time = time.time() + + print(f"Scanning {host} from port {start_port} to {end_port}") + + for port in range(start_port, end_port + 1): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(timeout) + result = sock.connect_ex((host, port)) + + if result == 0: + print(f"Port {port}: Open") + open_ports.append(port) + + sock.close() + + except KeyboardInterrupt: + print("Scan interrupted by user") + break + except socket.gaierror: + print("Hostname could not be resolved") + break + except socket.error: + print("Couldn't connect to server") + break + + end_time = time.time() + scan_time = end_time - start_time + + print(f"\nScan completed in {scan_time:.2f} seconds") + print(f"Found {len(open_ports)} open ports") + + return open_ports, scan_time + +def main(): + host = input("Enter the host to scan: ") + start_port = int(input("Enter the start port: ")) + end_port = int(input("Enter the end port: ")) + + open_ports, scan_time = port_scanner(host, start_port, end_port) + + if open_ports: + print("\nOpen ports:") + for port in open_ports: + print(f" Port {port}") + +if __name__ == "__main__": + main() \ No newline at end of file