+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Part 458 of 541

๐Ÿš€ Port Scanning: Network Discovery

Master port scanning and network discovery in Python with practical examples, best practices, and real-world applications ๐Ÿš€

๐Ÿ’ŽAdvanced
25 min read

Prerequisites

  • Basic understanding of programming concepts ๐Ÿ“
  • Python installation (3.8+) ๐Ÿ
  • VS Code or preferred IDE ๐Ÿ’ป

What you'll learn

  • Understand port scanning fundamentals ๐ŸŽฏ
  • Apply network discovery in real projects ๐Ÿ—๏ธ
  • Debug common networking issues ๐Ÿ›
  • Write clean, Pythonic network code โœจ

๐ŸŽฏ Introduction

Welcome to this exciting tutorial on port scanning and network discovery! ๐ŸŽ‰ In this guide, weโ€™ll explore how to discover services and open ports on network hosts using Python.

Youโ€™ll discover how port scanning can transform your network administration and security testing capabilities. Whether youโ€™re monitoring network infrastructure ๐Ÿ–ฅ๏ธ, performing security audits ๐Ÿ”’, or troubleshooting connectivity issues ๐Ÿ”ง, understanding port scanning is essential for network professionals.

By the end of this tutorial, youโ€™ll feel confident implementing network discovery tools in your own projects! Letโ€™s dive in! ๐ŸŠโ€โ™‚๏ธ

๐Ÿ“š Understanding Port Scanning

๐Ÿค” What is Port Scanning?

Port scanning is like checking which doors and windows are open in a building ๐Ÿข. Think of it as a network reconnaissance technique that helps you discover which services are available on a host.

In networking terms, port scanning involves systematically probing a server or host for open ports ๐Ÿ”. This means you can:

  • โœจ Discover running services
  • ๐Ÿš€ Map network topology
  • ๐Ÿ›ก๏ธ Identify potential vulnerabilities

๐Ÿ’ก Why Use Port Scanning?

Hereโ€™s why network professionals love port scanning:

  1. Network Discovery ๐Ÿ”: Find active hosts and services
  2. Security Auditing ๐Ÿ”’: Identify exposed services
  3. Troubleshooting ๐Ÿ”ง: Diagnose connectivity issues
  4. Service Monitoring ๐Ÿ“Š: Track service availability

Real-world example: Imagine managing a corporate network ๐Ÿข. With port scanning, you can quickly identify unauthorized services or verify that critical services are accessible.

๐Ÿ”ง Basic Syntax and Usage

๐Ÿ“ Simple Port Check

Letโ€™s start with a friendly example:

# ๐Ÿ‘‹ Hello, Network Discovery!
import socket
import sys

def check_port(host, port):
    """
    Check if a port is open on a host
    """
    # ๐ŸŽจ Create a socket object
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(1)  # โฑ๏ธ 1 second timeout
    
    try:
        # ๐Ÿ”Œ Attempt to connect
        result = sock.connect_ex((host, port))
        sock.close()
        
        # โœ… Port is open!
        if result == 0:
            return True
        else:
            return False
    except socket.gaierror:
        # ๐Ÿšซ Hostname couldn't be resolved
        print(f"โŒ Hostname {host} could not be resolved")
        return False
    except socket.error:
        # ๐Ÿ’ฅ Couldn't connect to server
        print(f"โŒ Could not connect to {host}")
        return False

# ๐ŸŽฎ Let's test it!
if check_port("google.com", 80):
    print("โœ… Port 80 is open on google.com!")
else:
    print("โŒ Port 80 is closed on google.com")

๐Ÿ’ก Explanation: Notice how we use socket programming to attempt connections! The connect_ex() method returns 0 if the connection succeeds.

๐ŸŽฏ Common Port Scanning Patterns

Here are patterns youโ€™ll use frequently:

# ๐Ÿ—๏ธ Pattern 1: Multiple port scanning
import concurrent.futures
import socket

def scan_port(host, port):
    """Scan a single port"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(0.5)
    result = sock.connect_ex((host, port))
    sock.close()
    return port if result == 0 else None

def scan_ports(host, start_port, end_port, max_threads=100):
    """
    # ๐Ÿš€ Scan multiple ports concurrently
    """
    open_ports = []
    
    # ๐ŸŽฏ Use thread pool for concurrent scanning
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_threads) as executor:
        # ๐Ÿ“Š Submit all port scans
        futures = {
            executor.submit(scan_port, host, port): port 
            for port in range(start_port, end_port + 1)
        }
        
        # ๐Ÿ”„ Collect results
        for future in concurrent.futures.as_completed(futures):
            port = future.result()
            if port:
                open_ports.append(port)
                print(f"โœจ Found open port: {port}")
    
    return sorted(open_ports)

# ๐ŸŽจ Pattern 2: Service identification
def identify_service(port):
    """Identify common services by port number"""
    services = {
        21: "FTP ๐Ÿ“",
        22: "SSH ๐Ÿ”",
        23: "Telnet ๐Ÿ“Ÿ",
        25: "SMTP ๐Ÿ“ง",
        53: "DNS ๐ŸŒ",
        80: "HTTP ๐ŸŒ",
        110: "POP3 ๐Ÿ“ฎ",
        443: "HTTPS ๐Ÿ”’",
        3306: "MySQL ๐Ÿ—„๏ธ",
        3389: "RDP ๐Ÿ–ฅ๏ธ",
        8080: "HTTP-Proxy ๐Ÿ”„"
    }
    return services.get(port, "Unknown โ“")

๐Ÿ’ก Practical Examples

๐Ÿ›ก๏ธ Example 1: Network Service Scanner

Letโ€™s build a comprehensive network scanner:

# ๐Ÿ›ก๏ธ Advanced network service scanner
import socket
import threading
from datetime import datetime
import queue

class NetworkScanner:
    def __init__(self, host, port_range=(1, 1000), threads=50):
        self.host = host
        self.port_range = port_range
        self.threads = threads
        self.open_ports = []
        self.lock = threading.Lock()
        
    def scan_port(self, port):
        """
        # ๐Ÿ” Scan a single port
        """
        try:
            # ๐ŸŽฏ Create socket with timeout
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(1)
            
            # ๐Ÿ”Œ Try to connect
            result = sock.connect_ex((self.host, port))
            sock.close()
            
            if result == 0:
                # โœ… Port is open!
                service = self.get_service_banner(port)
                with self.lock:
                    self.open_ports.append({
                        'port': port,
                        'service': identify_service(port),
                        'banner': service
                    })
                    print(f"โœจ Port {port}: OPEN - {identify_service(port)}")
                    
        except Exception as e:
            pass  # ๐Ÿคซ Silently skip errors
    
    def get_service_banner(self, port):
        """
        # ๐Ÿ“‹ Try to grab service banner
        """
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2)
            sock.connect((self.host, port))
            
            # ๐Ÿ‘‹ Send a probe
            sock.send(b'Hello\r\n')
            banner = sock.recv(1024).decode('utf-8', errors='ignore').strip()
            sock.close()
            
            return banner[:50] if banner else ""
        except:
            return ""
    
    def worker(self, port_queue):
        """
        # ๐Ÿ”„ Worker thread for scanning
        """
        while True:
            port = port_queue.get()
            if port is None:
                break
            self.scan_port(port)
            port_queue.task_done()
    
    def scan(self):
        """
        # ๐Ÿš€ Start the scanning process
        """
        print(f"๐ŸŽฏ Starting scan on {self.host}")
        print(f"๐Ÿ“Š Port range: {self.port_range[0]}-{self.port_range[1]}")
        print(f"โšก Using {self.threads} threads\n")
        
        start_time = datetime.now()
        
        # ๐Ÿ“ฆ Create work queue
        port_queue = queue.Queue()
        
        # ๐ŸŽจ Create and start threads
        threads = []
        for _ in range(self.threads):
            t = threading.Thread(target=self.worker, args=(port_queue,))
            t.start()
            threads.append(t)
        
        # ๐Ÿ“ Add ports to queue
        for port in range(self.port_range[0], self.port_range[1] + 1):
            port_queue.put(port)
        
        # ๐Ÿ Wait for completion
        port_queue.join()
        
        # ๐Ÿ›‘ Stop workers
        for _ in range(self.threads):
            port_queue.put(None)
        for t in threads:
            t.join()
        
        # ๐Ÿ“Š Display results
        duration = datetime.now() - start_time
        self.display_results(duration)
    
    def display_results(self, duration):
        """
        # ๐Ÿ“‹ Display scan results
        """
        print(f"\n{'='*50}")
        print(f"๐ŸŽ‰ Scan Complete!")
        print(f"โฑ๏ธ Duration: {duration}")
        print(f"๐ŸŽฏ Host: {self.host}")
        print(f"โœ… Open ports found: {len(self.open_ports)}")
        print(f"{'='*50}\n")
        
        if self.open_ports:
            print("๐Ÿ“Š Open Ports Summary:")
            print(f"{'Port':<10} {'Service':<20} {'Banner':<30}")
            print("-" * 60)
            for port_info in sorted(self.open_ports, key=lambda x: x['port']):
                print(f"{port_info['port']:<10} {port_info['service']:<20} {port_info['banner']:<30}")
        else:
            print("โŒ No open ports found in the specified range")

# ๐ŸŽฎ Let's use it!
scanner = NetworkScanner("scanme.nmap.org", port_range=(1, 100))
scanner.scan()

๐ŸŽฏ Try it yourself: Add UDP port scanning capability and OS fingerprinting features!

๐ŸŒ Example 2: Subnet Discovery Tool

Letโ€™s scan an entire subnet:

# ๐ŸŒ Subnet discovery tool
import ipaddress
import concurrent.futures
import socket
import platform
import subprocess

class SubnetScanner:
    def __init__(self, subnet):
        self.subnet = ipaddress.ip_network(subnet, strict=False)
        self.active_hosts = []
        
    def ping_host(self, ip):
        """
        # ๐Ÿ“ Ping a host to check if it's alive
        """
        ip_str = str(ip)
        
        # ๐Ÿ–ฅ๏ธ Platform-specific ping command
        if platform.system().lower() == "windows":
            command = ["ping", "-n", "1", "-w", "1000", ip_str]
        else:
            command = ["ping", "-c", "1", "-W", "1", ip_str]
        
        try:
            # ๐Ÿš€ Execute ping
            result = subprocess.run(
                command, 
                stdout=subprocess.DEVNULL, 
                stderr=subprocess.DEVNULL
            )
            
            if result.returncode == 0:
                return ip_str
        except:
            pass
        
        return None
    
    def tcp_scan_host(self, ip):
        """
        # ๐Ÿ”Œ TCP scan to check if host is alive
        """
        common_ports = [80, 443, 22, 21, 25, 3389, 445, 139]
        ip_str = str(ip)
        
        for port in common_ports:
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(0.5)
                result = sock.connect_ex((ip_str, port))
                sock.close()
                
                if result == 0:
                    return ip_str
            except:
                continue
        
        return None
    
    def scan_subnet(self, method="tcp"):
        """
        # ๐ŸŒ Scan entire subnet for active hosts
        """
        print(f"๐ŸŽฏ Scanning subnet: {self.subnet}")
        print(f"๐Ÿ“Š Total hosts to scan: {self.subnet.num_addresses - 2}")
        print(f"โšก Method: {method.upper()}\n")
        
        # ๐ŸŽจ Choose scanning method
        scan_func = self.ping_host if method == "ping" else self.tcp_scan_host
        
        # ๐Ÿš€ Concurrent scanning
        with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor:
            # ๐Ÿ“ Submit all scans
            future_to_ip = {
                executor.submit(scan_func, ip): ip 
                for ip in self.subnet.hosts()
            }
            
            # ๐Ÿ”„ Process results
            for future in concurrent.futures.as_completed(future_to_ip):
                result = future.result()
                if result:
                    self.active_hosts.append(result)
                    print(f"โœ… Found active host: {result}")
        
        # ๐Ÿ“Š Display summary
        self.display_summary()
    
    def display_summary(self):
        """
        # ๐Ÿ“‹ Display scanning summary
        """
        print(f"\n{'='*50}")
        print(f"๐ŸŽ‰ Subnet Scan Complete!")
        print(f"๐ŸŒ Subnet: {self.subnet}")
        print(f"โœ… Active hosts: {len(self.active_hosts)}")
        print(f"โŒ Inactive hosts: {self.subnet.num_addresses - 2 - len(self.active_hosts)}")
        print(f"{'='*50}\n")
        
        if self.active_hosts:
            print("๐Ÿ“Š Active Hosts:")
            for host in sorted(self.active_hosts, key=ipaddress.ip_address):
                print(f"  ๐Ÿ–ฅ๏ธ {host}")

# ๐ŸŽฎ Let's discover a network!
scanner = SubnetScanner("192.168.1.0/24")
scanner.scan_subnet(method="tcp")

๐Ÿš€ Advanced Concepts

๐Ÿง™โ€โ™‚๏ธ SYN Stealth Scanning

When youโ€™re ready to level up, try stealth scanning:

# ๐ŸŽฏ Advanced SYN stealth scanner (requires root/admin)
from scapy.all import *
import logging

# ๐Ÿคซ Suppress scapy warnings
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

class StealthScanner:
    def __init__(self, target, ports):
        self.target = target
        self.ports = ports
        self.open_ports = []
        
    def syn_scan(self, port):
        """
        # ๐Ÿฅท Perform SYN stealth scan
        """
        # ๐ŸŽจ Craft SYN packet
        syn_packet = IP(dst=self.target) / TCP(dport=port, flags="S")
        
        # ๐Ÿš€ Send packet and wait for response
        response = sr1(syn_packet, timeout=1, verbose=0)
        
        if response and response.haslayer(TCP):
            if response[TCP].flags == 18:  # SYN-ACK
                # โœ… Port is open!
                self.open_ports.append(port)
                # ๐Ÿ›‘ Send RST to close connection
                rst_packet = IP(dst=self.target) / TCP(dport=port, flags="R")
                send(rst_packet, verbose=0)
                return True
        
        return False
    
    def scan(self):
        """
        # ๐Ÿš€ Execute stealth scan
        """
        print(f"๐Ÿฅท Starting SYN stealth scan on {self.target}")
        
        for port in self.ports:
            if self.syn_scan(port):
                print(f"โœจ Port {port}: OPEN (Stealth)")
        
        print(f"\n๐ŸŽฏ Stealth scan complete!")
        print(f"โœ… Open ports: {self.open_ports}")

# โš ๏ธ Note: Requires root/admin privileges!
# scanner = StealthScanner("scanme.nmap.org", [80, 443, 22, 21])
# scanner.scan()

๐Ÿ—๏ธ Advanced Service Detection

For the brave network explorers:

# ๐Ÿš€ Advanced service fingerprinting
import struct
import ssl

class ServiceDetector:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        
    def detect_http(self):
        """
        # ๐ŸŒ Detect HTTP/HTTPS service
        """
        try:
            # ๐Ÿ”’ Try HTTPS first
            context = ssl.create_default_context()
            with socket.create_connection((self.host, self.port), timeout=3) as sock:
                with context.wrap_socket(sock, server_hostname=self.host) as ssock:
                    ssock.send(b"HEAD / HTTP/1.1\r\nHost: " + self.host.encode() + b"\r\n\r\n")
                    response = ssock.recv(1024).decode('utf-8', errors='ignore')
                    if "HTTP" in response:
                        return f"HTTPS ๐Ÿ”’ - {response.split('\r\n')[0]}"
        except:
            # ๐ŸŒ Try plain HTTP
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(3)
                sock.connect((self.host, self.port))
                sock.send(b"HEAD / HTTP/1.1\r\nHost: " + self.host.encode() + b"\r\n\r\n")
                response = sock.recv(1024).decode('utf-8', errors='ignore')
                sock.close()
                if "HTTP" in response:
                    return f"HTTP ๐ŸŒ - {response.split('\r\n')[0]}"
            except:
                pass
        
        return None
    
    def detect_ssh(self):
        """
        # ๐Ÿ” Detect SSH service
        """
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(3)
            sock.connect((self.host, self.port))
            banner = sock.recv(1024).decode('utf-8', errors='ignore')
            sock.close()
            
            if "SSH" in banner:
                return f"SSH ๐Ÿ” - {banner.strip()}"
        except:
            pass
        
        return None
    
    def detect_smtp(self):
        """
        # ๐Ÿ“ง Detect SMTP service
        """
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(3)
            sock.connect((self.host, self.port))
            banner = sock.recv(1024).decode('utf-8', errors='ignore')
            
            if "220" in banner or "SMTP" in banner.upper():
                sock.send(b"EHLO test\r\n")
                response = sock.recv(1024).decode('utf-8', errors='ignore')
                sock.close()
                return f"SMTP ๐Ÿ“ง - {banner.split('\r\n')[0]}"
        except:
            pass
        
        return None
    
    def detect_service(self):
        """
        # ๐ŸŽฏ Auto-detect service type
        """
        detectors = [
            self.detect_http,
            self.detect_ssh,
            self.detect_smtp
        ]
        
        for detector in detectors:
            result = detector()
            if result:
                return result
        
        return "Unknown Service โ“"

# ๐ŸŽฎ Test service detection
detector = ServiceDetector("scanme.nmap.org", 22)
print(f"๐Ÿ” Service detected: {detector.detect_service()}")

โš ๏ธ Common Pitfalls and Solutions

๐Ÿ˜ฑ Pitfall 1: Too Aggressive Scanning

# โŒ Wrong way - too fast, might trigger IDS!
def bad_scanner(host):
    for port in range(1, 65536):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(0.1)  # ๐Ÿ’ฅ Too short!
        sock.connect_ex((host, port))  # ๐Ÿ’ฅ No delay!
        sock.close()

# โœ… Correct way - controlled scanning!
def good_scanner(host, delay=0.1):
    import time
    import random
    
    for port in range(1, 1025):  # ๐ŸŽฏ Reasonable range
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)  # โœ… Reasonable timeout
        sock.connect_ex((host, port))
        sock.close()
        
        # โฑ๏ธ Add random delay
        time.sleep(delay + random.uniform(0, 0.1))

๐Ÿคฏ Pitfall 2: Ignoring Legal/Ethical Concerns

# โŒ Dangerous - scanning without permission!
def unethical_scan(random_ip):
    scan_ports(random_ip, 1, 65535)  # ๐Ÿ’ฅ Illegal!

# โœ… Safe - always get permission!
def ethical_scan(host):
    """
    โš ๏ธ IMPORTANT: Only scan systems you own or have 
    written permission to test!
    """
    print("๐Ÿ”’ Security Notice:")
    print("- Only scan your own systems")
    print("- Get written permission for others")
    print("- Respect rate limits")
    print("- Follow responsible disclosure")
    
    # โœ… Use designated test hosts
    safe_hosts = [
        "scanme.nmap.org",  # Public test host
        "localhost",         # Your machine
        "192.168.1.1"       # Your router (if you own it)
    ]
    
    if host in safe_hosts or host.startswith("192.168."):
        return True
    else:
        print("โš ๏ธ Please ensure you have permission!")
        return False

๐Ÿ› ๏ธ Best Practices

  1. ๐ŸŽฏ Always Get Permission: Only scan systems you own or have written authorization to test!
  2. ๐Ÿ“ Log Everything: Keep detailed logs of your scanning activities
  3. ๐Ÿ›ก๏ธ Use Rate Limiting: Donโ€™t overwhelm target systems with requests
  4. ๐ŸŽจ Be Stealthy When Needed: Use SYN scanning for minimal footprint
  5. โœจ Verify Results: Double-check findings with different methods

๐Ÿงช Hands-On Exercise

๐ŸŽฏ Challenge: Build a Network Mapper

Create a comprehensive network mapping tool:

๐Ÿ“‹ Requirements:

  • โœ… Discover active hosts in a subnet
  • ๐Ÿท๏ธ Identify open ports on each host
  • ๐Ÿ‘ค Detect running services
  • ๐Ÿ“… Generate a network map report
  • ๐ŸŽจ Support different scanning techniques!

๐Ÿš€ Bonus Points:

  • Add OS fingerprinting
  • Implement vulnerability detection
  • Create a GUI interface

๐Ÿ’ก Solution

๐Ÿ” Click to see solution
# ๐ŸŽฏ Comprehensive network mapper!
import socket
import threading
import ipaddress
from datetime import datetime
import json

class NetworkMapper:
    def __init__(self, network):
        self.network = ipaddress.ip_network(network, strict=False)
        self.results = {}
        self.lock = threading.Lock()
        
    def scan_host(self, ip):
        """
        # ๐Ÿ–ฅ๏ธ Scan individual host
        """
        ip_str = str(ip)
        host_info = {
            'ip': ip_str,
            'hostname': None,
            'open_ports': [],
            'services': {},
            'scan_time': datetime.now().isoformat()
        }
        
        # ๐Ÿท๏ธ Try to get hostname
        try:
            host_info['hostname'] = socket.gethostbyaddr(ip_str)[0]
        except:
            host_info['hostname'] = 'Unknown'
        
        # ๐Ÿ” Scan common ports
        common_ports = [21, 22, 23, 25, 53, 80, 110, 443, 445, 3306, 3389, 8080]
        
        for port in common_ports:
            if self.check_port(ip_str, port):
                host_info['open_ports'].append(port)
                # ๐ŸŽจ Identify service
                service_info = self.identify_service_advanced(ip_str, port)
                host_info['services'][port] = service_info
        
        # ๐Ÿ“ Store results
        if host_info['open_ports']:
            with self.lock:
                self.results[ip_str] = host_info
                print(f"โœ… Mapped: {ip_str} ({host_info['hostname']})")
                print(f"   ๐Ÿ“Š Open ports: {host_info['open_ports']}")
    
    def check_port(self, host, port):
        """
        # ๐Ÿ”Œ Check if port is open
        """
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(1)
            result = sock.connect_ex((host, port))
            sock.close()
            return result == 0
        except:
            return False
    
    def identify_service_advanced(self, host, port):
        """
        # ๐Ÿ” Advanced service identification
        """
        service_info = {
            'name': identify_service(port),
            'banner': '',
            'version': ''
        }
        
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2)
            sock.connect((host, port))
            
            # ๐Ÿ‘‹ Send probe based on port
            if port == 80 or port == 8080:
                sock.send(b"GET / HTTP/1.0\r\n\r\n")
            elif port == 22:
                pass  # SSH sends banner automatically
            else:
                sock.send(b"\r\n")
            
            # ๐Ÿ“‹ Receive response
            banner = sock.recv(1024).decode('utf-8', errors='ignore')
            sock.close()
            
            service_info['banner'] = banner[:100].strip()
            
            # ๐ŸŽฏ Extract version info
            if "SSH" in banner:
                service_info['version'] = banner.split()[0]
            elif "HTTP" in banner:
                for line in banner.split('\r\n'):
                    if 'Server:' in line:
                        service_info['version'] = line.split(':', 1)[1].strip()
                        break
        except:
            pass
        
        return service_info
    
    def map_network(self, max_threads=50):
        """
        # ๐ŸŒ Map entire network
        """
        print(f"๐Ÿ—บ๏ธ Starting network mapping for {self.network}")
        print(f"๐Ÿ“Š Hosts to scan: {self.network.num_addresses - 2}\n")
        
        start_time = datetime.now()
        
        # ๐Ÿš€ Thread pool for concurrent scanning
        threads = []
        hosts = list(self.network.hosts())
        
        for i in range(0, len(hosts), max_threads):
            batch = hosts[i:i + max_threads]
            batch_threads = []
            
            for host in batch:
                t = threading.Thread(target=self.scan_host, args=(host,))
                t.start()
                batch_threads.append(t)
            
            # โณ Wait for batch to complete
            for t in batch_threads:
                t.join()
        
        # ๐Ÿ“Š Generate report
        duration = datetime.now() - start_time
        self.generate_report(duration)
    
    def generate_report(self, duration):
        """
        # ๐Ÿ“‹ Generate network map report
        """
        print(f"\n{'='*60}")
        print(f"๐Ÿ—บ๏ธ Network Mapping Complete!")
        print(f"โฑ๏ธ Duration: {duration}")
        print(f"๐ŸŒ Network: {self.network}")
        print(f"โœ… Active hosts: {len(self.results)}")
        print(f"{'='*60}\n")
        
        # ๐Ÿ“Š Summary by service
        service_count = {}
        for host_info in self.results.values():
            for port, service in host_info['services'].items():
                service_name = service['name']
                service_count[service_name] = service_count.get(service_name, 0) + 1
        
        print("๐Ÿ“Š Services Summary:")
        for service, count in sorted(service_count.items(), key=lambda x: x[1], reverse=True):
            print(f"  {service}: {count} host(s)")
        
        # ๐Ÿ’พ Save detailed report
        report_file = f"network_map_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(report_file, 'w') as f:
            json.dump(self.results, f, indent=2)
        
        print(f"\n๐Ÿ’พ Detailed report saved to: {report_file}")

# ๐ŸŽฎ Map your network!
mapper = NetworkMapper("192.168.1.0/24")
mapper.map_network()

๐ŸŽ“ Key Takeaways

Youโ€™ve learned so much! Hereโ€™s what you can now do:

  • โœ… Perform port scanning with confidence ๐Ÿ’ช
  • โœ… Discover network services like a pro ๐Ÿ›ก๏ธ
  • โœ… Apply security best practices in your scans ๐ŸŽฏ
  • โœ… Debug network issues efficiently ๐Ÿ›
  • โœ… Build network discovery tools with Python! ๐Ÿš€

Remember: With great power comes great responsibility! Always scan ethically and legally. ๐Ÿค

๐Ÿค Next Steps

Congratulations! ๐ŸŽ‰ Youโ€™ve mastered port scanning and network discovery!

Hereโ€™s what to do next:

  1. ๐Ÿ’ป Practice with the exercises above on authorized systems
  2. ๐Ÿ—๏ธ Build a network monitoring dashboard
  3. ๐Ÿ“š Move on to our next tutorial: UDP Sockets and Connectionless Communication
  4. ๐ŸŒŸ Share your network discoveries responsibly!

Remember: Every network security expert started by learning the fundamentals. Keep exploring, keep learning, and most importantly, stay ethical! ๐Ÿš€


Happy network discovering! ๐ŸŽ‰๐Ÿš€โœจ