Complete Guide to Cyber Security Network Mapping & Port Scanning

Introduction to Network Mapping and Port Scanning

Network mapping and port scanning are fundamental reconnaissance techniques in cybersecurity. They allow security professionals to discover devices on a network, identify open ports, detect running services, and understand the attack surface of an organization. These techniques are used both by security teams to assess vulnerabilities and by attackers to identify potential entry points.

Key Concepts

  • Network Discovery: Identifying live hosts on a network
  • Port Scanning: Determining which ports are open on a target
  • Service Detection: Identifying running services and their versions
  • OS Fingerprinting: Determining the operating system of target hosts
  • Network Topology: Mapping the structure and relationships between network devices

1. Network Discovery Fundamentals

Understanding Network Topology

import ipaddress
import subprocess
import socket
import threading
import queue
import time
from dataclasses import dataclass
from typing import List, Dict, Optional
import concurrent.futures
@dataclass
class NetworkHost:
"""Represents a discovered network host"""
ip: str
hostname: Optional[str] = None
status: str = "unknown"
open_ports: List[int] = None
services: Dict[int, str] = None
os: Optional[str] = None
def __post_init__(self):
if self.open_ports is None:
self.open_ports = []
if self.services is None:
self.services = {}
class NetworkDiscovery:
"""Network discovery and host enumeration"""
def __init__(self):
self.hosts = []
self.network = None
def parse_network(self, network_cidr):
"""Parse network CIDR notation"""
try:
self.network = ipaddress.ip_network(network_cidr, strict=False)
print(f"Target network: {self.network}")
return True
except ValueError as e:
print(f"Invalid network: {e}")
return False
def ping_host(self, ip):
"""Ping a single host to check if it's alive"""
# Different ping commands for different OS
param = '-n' if 'win' in subprocess.getoutput('uname -s').lower() else '-c'
command = ['ping', param, '1', '-W', '1', str(ip)]
try:
result = subprocess.run(command, stdout=subprocess.DEVNULL, 
stderr=subprocess.DEVNULL, timeout=2)
return result.returncode == 0
except subprocess.TimeoutExpired:
return False
except Exception:
return False
def discover_hosts(self, timeout=2, max_workers=100):
"""Discover live hosts using ping sweep"""
if not self.network:
print("No network specified")
return
print(f"\nDiscovering live hosts on {self.network}...")
print("=" * 50)
live_hosts = []
hosts = list(self.network.hosts())
def check_host(ip):
if self.ping_host(ip):
return ip
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(check_host, ip) for ip in hosts]
for future in concurrent.futures.as_completed(futures):
result = future.result()
if result:
live_hosts.append(result)
print(f"  ✓ Host: {result}")
print(f"\nFound {len(live_hosts)} live hosts")
# Create host objects
for ip in live_hosts:
host = NetworkHost(ip=str(ip), status="up")
self.hosts.append(host)
return self.hosts
def reverse_dns_lookup(self, host):
"""Perform reverse DNS lookup"""
try:
hostname = socket.gethostbyaddr(host.ip)
host.hostname = hostname[0]
return True
except socket.herror:
return False
def resolve_all_hostnames(self):
"""Resolve hostnames for all discovered hosts"""
print("\nResolving hostnames...")
for host in self.hosts:
if self.reverse_dns_lookup(host):
print(f"  {host.ip} → {host.hostname}")
else:
print(f"  {host.ip} → (no PTR record)")
# Example usage
discovery = NetworkDiscovery()
discovery.parse_network("192.168.1.0/24")
discovery.discover_hosts()
discovery.resolve_all_hostnames()

ICMP Techniques

class ICMPTechniques:
"""Advanced ICMP discovery techniques"""
@staticmethod
def explain_icmp_types():
"""Explain different ICMP types used in network discovery"""
icmp_types = {
"Echo Request (Type 8)": "Standard ping - most common but often blocked",
"Echo Reply (Type 0)": "Response to ping, indicates host is up",
"Timestamp Request (Type 13)": "Alternative ICMP probe, sometimes allowed",
"Address Mask Request (Type 17)": "Less commonly filtered",
"Information Request (Type 15)": "Legacy, sometimes allowed through firewalls"
}
print("ICMP Discovery Techniques")
print("=" * 50)
for probe, description in icmp_types.items():
print(f"  • {probe}: {description}")
print("\nICMP Bypass Techniques:")
print("  • Use alternative ICMP types that firewalls may allow")
print("  • Combine with TCP/UDP probes for more reliable detection")
print("  • Use ICMP echo with large packet sizes for MTU discovery")
@staticmethod
def icmp_timestamp_scan():
"""Conceptual ICMP timestamp scan"""
print("\nICMP Timestamp Scan Concept:")
print("  • Sends ICMP Timestamp Request (type 13)")
print("  • Some networks allow this when standard ICMP is blocked")
print("  • Can reveal host time and sometimes OS information")
@staticmethod
def icmp_address_mask_scan():
"""Conceptual ICMP address mask scan"""
print("\nICMP Address Mask Scan Concept:")
print("  • Sends ICMP Address Mask Request (type 17)")
print("  • Often allowed through firewalls")
print("  • Can reveal subnet mask information")
ICMPTechniques.explain_icmp_types()

2. Port Scanning Techniques

TCP Connect Scan

class TCPScanner:
"""TCP port scanning implementation"""
def __init__(self):
self.common_ports = {
20: "FTP-data",
21: "FTP",
22: "SSH",
23: "Telnet",
25: "SMTP",
53: "DNS",
80: "HTTP",
110: "POP3",
111: "RPC",
135: "MSRPC",
139: "NetBIOS",
143: "IMAP",
443: "HTTPS",
445: "SMB",
993: "IMAPS",
995: "POP3S",
1433: "MSSQL",
3306: "MySQL",
3389: "RDP",
5432: "PostgreSQL",
5900: "VNC",
8080: "HTTP-Alt",
8443: "HTTPS-Alt"
}
def tcp_connect_scan(self, host, ports, timeout=2):
"""Perform TCP connect scan (full handshake)"""
print(f"\nTCP Connect Scan on {host}")
print("=" * 50)
print("Port\tState\tService")
print("-" * 40)
open_ports = []
for port in ports:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((host, port))
if result == 0:
service = self.common_ports.get(port, "unknown")
print(f"{port}\topen\t{service}")
open_ports.append(port)
sock.close()
except Exception as e:
continue
return open_ports
def tcp_syn_scan_concept(self):
"""Explain SYN scan (half-open)"""
print("\nSYN Scan (Half-Open) Technique")
print("=" * 40)
print("""
Normal TCP handshake:
Client → SYN → Server
Server → SYN-ACK → Client
Client → ACK → Server
[Connection established]
SYN Scan:
Client → SYN → Server
Server → SYN-ACK → Client
Client → RST → Server
[Connection never fully established]
Advantages:
• Faster (no full handshake)
• Stealthier (no application layer logs)
• Can bypass some firewalls
Disadvantages:
• Requires raw packet privileges (root)
• May be detected by IDS
""")
def udp_scan(self, host, ports, timeout=2):
"""Perform UDP port scan"""
print(f"\nUDP Scan on {host}")
print("=" * 50)
print("Port\tState\tService")
print("-" * 40)
open_ports = []
for port in ports:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(timeout)
# Send empty UDP packet
sock.sendto(b'', (host, port))
# Try to receive response
try:
data, addr = sock.recvfrom(1024)
service = self.common_ports.get(port, "unknown")
print(f"{port}\topen\t{service}")
open_ports.append(port)
except socket.timeout:
# No response doesn't necessarily mean closed
# Could be open but not responding
pass
except ConnectionRefusedError:
# ICMP port unreachable - port is closed
pass
sock.close()
except Exception as e:
continue
print("\nNote: UDP scan is less reliable than TCP scan")
print("  • Many services don't respond to empty UDP packets")
print("  • Rate limiting may affect results")
return open_ports
# Example usage
scanner = TCPScanner()
scanner.tcp_syn_scan_concept()
# Scan common ports
common_ports = [21, 22, 23, 25, 80, 443, 3306, 3389, 8080]
# scanner.tcp_connect_scan("192.168.1.1", common_ports)

Port Scanning Techniques Comparison

class ScanningTechniques:
"""Comparison of different port scanning techniques"""
techniques = {
"TCP Connect": {
"description": "Complete TCP handshake",
"stealth": "Low - full connection logged",
"speed": "Medium",
"privileges": "User",
"detection": "Easy to detect",
"reliability": "High"
},
"SYN Scan": {
"description": "Half-open, no final ACK",
"stealth": "Medium - connection not completed",
"speed": "Fast",
"privileges": "Root",
"detection": "Moderate",
"reliability": "High"
},
"FIN Scan": {
"description": "Send FIN packet",
"stealth": "High - may bypass firewalls",
"speed": "Fast",
"privileges": "Root",
"detection": "Low",
"reliability": "Medium (OS dependent)"
},
"NULL Scan": {
"description": "No flags set",
"stealth": "High",
"speed": "Fast",
"privileges": "Root",
"detection": "Low",
"reliability": "Medium"
},
"XMAS Scan": {
"description": "FIN, URG, PUSH flags set",
"stealth": "High",
"speed": "Fast",
"privileges": "Root",
"detection": "Low",
"reliability": "Medium"
},
"UDP Scan": {
"description": "Send UDP packets",
"stealth": "Medium",
"speed": "Slow",
"privileges": "User",
"detection": "Moderate",
"reliability": "Low (many false positives)"
},
"ACK Scan": {
"description": "Send ACK packet",
"stealth": "Medium",
"speed": "Fast",
"privileges": "Root",
"detection": "Moderate",
"reliability": "High for firewall detection"
}
}
@classmethod
def compare_techniques(cls):
"""Display comparison of scanning techniques"""
print("Port Scanning Techniques Comparison")
print("=" * 80)
print(f"{'Technique':<12} {'Description':<20} {'Stealth':<8} {'Speed':<8} {'Privileges':<10} {'Reliability':<10}")
print("-" * 80)
for name, details in cls.techniques.items():
print(f"{name:<12} {details['description'][:18]:<20} "
f"{details['stealth']:<8} {details['speed']:<8} "
f"{details['privileges']:<10} {details['reliability']:<10}")
@classmethod
def scan_type_recommendations(cls):
"""Provide recommendations for different scenarios"""
print("\n" + "="*80)
print("Recommended Scan Types by Scenario")
print("="*80)
scenarios = {
"Standard Penetration Test": "SYN scan (fast, reliable)",
"Firewall Testing": "ACK scan, FIN scan, NULL scan",
"UDP Service Discovery": "UDP scan combined with service-specific probes",
"Stealth Assessment": "FIN/NULL/XMAS scans",
"Internal Network Audit": "TCP Connect (full logging for audit)",
"Quick Discovery": "SYN scan on common ports",
"Comprehensive Audit": "Full port scan with service version detection"
}
for scenario, recommendation in scenarios.items():
print(f"  • {scenario}: {recommendation}")
ScanningTechniques.compare_techniques()
ScanningTechniques.scan_type_recommendations()

3. Service and Version Detection

class ServiceDetection:
"""Service and version fingerprinting"""
def __init__(self):
self.service_signatures = {
# Web servers
"HTTP": [
(b"Server: Apache", "Apache HTTP Server"),
(b"Server: nginx", "nginx"),
(b"Server: Microsoft-IIS", "Microsoft IIS"),
(b"Server: lighttpd", "lighttpd"),
(b"Server: Caddy", "Caddy"),
],
# SSH
"SSH": [
(b"SSH-2.0-OpenSSH", "OpenSSH"),
(b"SSH-2.0-OpenSSH_", "OpenSSH (with version)"),
(b"SSH-2.0-dropbear", "Dropbear SSH"),
],
# FTP
"FTP": [
(b"220 ", "FTP Service Ready"),
(b"vsFTPd", "vsFTPd"),
(b"ProFTPD", "ProFTPD"),
(b"Microsoft FTP", "Microsoft FTP Service"),
],
# SMTP
"SMTP": [
(b"220 ", "SMTP Ready"),
(b"ESMTP Postfix", "Postfix"),
(b"ESMTP Sendmail", "Sendmail"),
(b"Exchange", "Microsoft Exchange"),
]
}
def banner_grab(self, host, port, timeout=3):
"""Attempt to grab service banner"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
sock.connect((host, port))
# Send common probes
probes = [
b"\r\n",  # CRLF
b"HEAD / HTTP/1.0\r\n\r\n",  # HTTP probe
b"QUIT\r\n",  # FTP/SMTP probe
b"\n",  # Simple newline
]
for probe in probes:
try:
sock.send(probe)
data = sock.recv(1024)
if data:
return self.identify_service(port, data)
except:
continue
sock.close()
return None
except Exception as e:
return None
def identify_service(self, port, banner):
"""Identify service from banner"""
service_name = None
# Determine likely service based on port
service_by_port = {
80: "HTTP",
443: "HTTPS",
22: "SSH",
21: "FTP",
25: "SMTP",
53: "DNS",
3306: "MySQL",
5432: "PostgreSQL"
}
service_type = service_by_port.get(port, "Unknown")
# Check signatures for this service type
if service_type in self.service_signatures:
for signature, name in self.service_signatures[service_type]:
if signature in banner:
service_name = name
break
if not service_name:
# Try to identify from banner content
if b"SSH" in banner:
service_name = "SSH"
elif b"HTTP" in banner or b"Server:" in banner:
service_name = "HTTP"
elif b"220" in banner and b"FTP" in banner:
service_name = "FTP"
else:
service_name = service_type
return {
'port': port,
'service': service_name,
'banner': banner[:200].decode('utf-8', errors='ignore'),
'version': self.extract_version(banner)
}
def extract_version(self, banner):
"""Extract version information from banner"""
import re
# Common version patterns
patterns = [
r'(\d+\.\d+\.\d+)',
r'(\d+\.\d+)',
r'version[^\d]*(\d+\.\d+\.?\d*)',
]
banner_str = banner.decode('utf-8', errors='ignore')
for pattern in patterns:
match = re.search(pattern, banner_str, re.IGNORECASE)
if match:
return match.group(1)
return "unknown"
def scan_services(self, host, ports):
"""Scan multiple ports for service identification"""
results = []
print(f"\nService Detection on {host}")
print("=" * 60)
print("Port\tService\t\tVersion\t\tBanner Preview")
print("-" * 60)
for port in ports:
banner = self.banner_grab(host, port)
if banner:
results.append(banner)
print(f"{port}\t{banner['service']:<15} {banner['version']:<12} "
f"{banner['banner'][:40]}...")
else:
print(f"{port}\t(no response)")
return results
# Example usage
detector = ServiceDetection()
# results = detector.scan_services("192.168.1.1", [80, 22, 443, 3306])

4. OS Fingerprinting

class OSFingerprinting:
"""Operating system detection techniques"""
def __init__(self):
self.os_signatures = {
"Linux": {
"ttl": [64, 255],
"window_size": [5840, 5792],
"tcp_options": ["mss", "nop", "wscale", "sackOK"],
"fingerprints": [
b"Linux", b"Ubuntu", b"Debian", b"Red Hat", b"CentOS"
]
},
"Windows": {
"ttl": [128],
"window_size": [8192, 16384, 64240],
"tcp_options": ["mss", "nop", "nop", "sackOK"],
"fingerprints": [
b"Windows", b"Microsoft", b"Windows NT", b"Server"
]
},
"MacOS": {
"ttl": [64],
"window_size": [65535],
"tcp_options": ["mss", "nop", "wscale", "sackOK"],
"fingerprints": [b"Darwin", b"Mac OS", b"macOS"]
},
"FreeBSD": {
"ttl": [64],
"window_size": [65535],
"tcp_options": ["mss", "nop", "sackOK"],
"fingerprints": [b"FreeBSD", b"BSD"]
}
}
def tcp_os_fingerprint(self, host, port=80):
"""Perform TCP OS fingerprinting"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3)
sock.connect((host, port))
# Get socket options to infer OS
# This is simplified - real OS fingerprinting uses more sophisticated techniques
ttl = self._get_ttl(host)
window_size = self._get_tcp_window(host, port)
# Attempt banner grab for OS identification
banner = self._get_banner(host, port)
sock.close()
return self._match_os(ttl, window_size, banner)
except Exception as e:
return {"os": "Unknown", "confidence": "low", "error": str(e)}
def _get_ttl(self, host):
"""Get TTL value using ping"""
param = '-n' if 'win' in subprocess.getoutput('uname -s').lower() else '-c'
try:
result = subprocess.run(['ping', param, '1', host], 
capture_output=True, text=True, timeout=2)
# Parse TTL from output
import re
match = re.search(r'ttl[= ](\d+)', result.stdout.lower())
if match:
return int(match.group(1))
except:
pass
return None
def _get_tcp_window(self, host, port):
"""Get TCP window size"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
window = sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
sock.close()
return window
except:
return None
def _get_banner(self, host, port):
"""Get service banner"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
sock.connect((host, port))
sock.send(b"\r\n")
banner = sock.recv(1024)
sock.close()
return banner
except:
return b""
def _match_os(self, ttl, window, banner):
"""Match collected data to OS signatures"""
matches = []
for os_name, signature in self.os_signatures.items():
score = 0
if ttl in signature.get('ttl', []):
score += 30
if window in signature.get('window_size', []):
score += 30
if any(fingerprint in banner for fingerprint in signature.get('fingerprints', [])):
score += 40
if score > 0:
matches.append((os_name, score))
if matches:
matches.sort(key=lambda x: x[1], reverse=True)
best_match = matches[0]
return {
"os": best_match[0],
"confidence": "high" if best_match[1] > 70 else "medium",
"score": best_match[1]
}
return {"os": "Unknown", "confidence": "low", "score": 0}
def passive_os_fingerprint(self, capture_data):
"""Passive OS fingerprinting from captured traffic"""
# Analyze packet characteristics
# This is a simplified version
print("\nPassive OS Fingerprinting Analysis:")
indicators = {
"Initial TTL": "64 = Linux/Unix, 128 = Windows",
"TCP Window Size": "5840 = Linux, 8192/16384 = Windows",
"TCP Options": "Order and values indicate OS",
"DF Flag": "Don't Fragment flag behavior",
"IP ID": "Increment patterns"
}
for indicator, description in indicators.items():
print(f"  • {indicator}: {description}")
# Example usage
fingerprinter = OSFingerprinting()
result = fingerprinter.tcp_os_fingerprint("scanme.nmap.org", 80)
print(f"\nOS Fingerprint Result: {result}")

5. Advanced Scanning Techniques

Stealth Scanning

class StealthScanning:
"""Advanced stealth scanning techniques"""
@staticmethod
def explain_stealth_techniques():
"""Explain stealth scanning methods"""
print("Stealth Scanning Techniques")
print("=" * 50)
techniques = {
"Decoy Scanning": {
"description": "Use multiple decoy IPs to hide real source",
"command": "nmap -D RND:10,ME target",
"effect": "Makes attribution difficult"
},
"Idle Scan": {
"description": "Use a zombie host to bounce scan",
"command": "nmap -sI zombie target",
"effect": "Extremely stealthy, no packets from attacker"
},
"Fragmentation": {
"description": "Split packets into fragments",
"command": "nmap -f target",
"effect": "Bypass simple packet filters"
},
"Source Port Manipulation": {
"description": "Spoof source port",
"command": "nmap -g 53 target",
"effect": "Bypass port-based filtering"
},
"Timing Manipulation": {
"description": "Slow down scan rate",
"command": "nmap -T0 (Paranoid), -T1 (Sneaky)",
"effect": "Avoid IDS detection"
}
}
for name, details in techniques.items():
print(f"\n• {name}:")
print(f"    {details['description']}")
print(f"    Command: {details['command']}")
print(f"    Effect: {details['effect']}")
@staticmethod
def timing_templates():
"""Explain Nmap timing templates"""
print("\nNmap Timing Templates")
print("-" * 40)
templates = {
"T0 (Paranoid)": "0.33 seconds between probes, very slow",
"T1 (Sneaky)": "1.5 seconds between probes, stealthy",
"T2 (Polite)": "0.4 seconds between probes, polite scanning",
"T3 (Normal)": "Default timing, normal speed",
"T4 (Aggressive)": "Faster, assumes good network",
"T5 (Insane)": "Very fast, may drop packets"
}
for name, description in templates.items():
print(f"  {name:<15}: {description}")
StealthScanning.explain_stealth_techniques()
StealthScanning.timing_templates()

Firewall Evasion

class FirewallEvasion:
"""Firewall evasion techniques"""
@staticmethod
def explain_evasion():
"""Explain firewall evasion techniques"""
print("Firewall Evasion Techniques")
print("=" * 50)
techniques = {
"ACK Scan": {
"method": "Send ACK packets to probe firewall rules",
"purpose": "Determine which ports are filtered",
"response": "RST for unfiltered, no response for filtered"
},
"Window Scan": {
"method": "Examine TCP window field in RST packets",
"purpose": "Determine open vs closed ports",
"response": "Non-zero window = open, zero = closed"
},
"Maimon Scan": {
"method": "Send FIN/ACK packet",
"purpose": "Some systems respond differently",
"response": "RST for open ports (non-standard)"
},
"Idle Scan": {
"method": "Use zombie host to bounce scan",
"purpose": "Complete stealth, no packets from attacker",
"response": "Analyze IP ID changes on zombie"
},
"FTP Bounce": {
"method": "Use FTP server as proxy",
"purpose": "Obscure source, bypass firewalls",
"response": "Limited to FTP port"
}
}
for name, details in techniques.items():
print(f"\n• {name}:")
print(f"    Method: {details['method']}")
print(f"    Purpose: {details['purpose']}")
print(f"    Response: {details['response']}")
FirewallEvasion.explain_evasion()

6. Network Mapping Visualization

class NetworkMapper:
"""Network topology mapping and visualization"""
def __init__(self):
self.nodes = {}
self.edges = []
def add_host(self, ip, hostname=None, os=None, services=None):
"""Add host to network map"""
self.nodes[ip] = {
'ip': ip,
'hostname': hostname,
'os': os,
'services': services or [],
'type': self._classify_host(ip, services)
}
def _classify_host(self, ip, services):
"""Classify host type based on IP and services"""
# Check for common service patterns
if not services:
return "unknown"
service_ports = [s.get('port', 0) for s in services]
if 80 in service_ports or 443 in service_ports:
return "web_server"
if 3306 in service_ports or 5432 in service_ports:
return "database"
if 22 in service_ports:
return "ssh_server"
if 445 in service_ports or 139 in service_ports:
return "file_server"
if 53 in service_ports:
return "dns_server"
return "workstation"
def add_connection(self, source, destination, protocol="unknown"):
"""Add network connection between hosts"""
self.edges.append({
'source': source,
'destination': destination,
'protocol': protocol
})
def generate_graphviz(self, filename="network_map.dot"):
"""Generate Graphviz DOT file for visualization"""
with open(filename, 'w') as f:
f.write('graph NetworkMap {\n')
f.write('  rankdir=TB;\n')
f.write('  node [shape=box];\n\n')
# Add nodes
for ip, data in self.nodes.items():
label = f"{ip}"
if data['hostname']:
label = f"{data['hostname']}\\n{ip}"
if data['os']:
label += f"\\n{data['os']}"
# Node styling based on type
node_type = data['type']
if node_type == 'web_server':
f.write(f'  "{ip}" [shape=ellipse, fillcolor=lightblue, style=filled, label="{label}"];\n')
elif node_type == 'database':
f.write(f'  "{ip}" [shape=cylinder, fillcolor=lightgreen, style=filled, label="{label}"];\n')
elif node_type == 'file_server':
f.write(f'  "{ip}" [shape=folder, fillcolor=yellow, style=filled, label="{label}"];\n')
else:
f.write(f'  "{ip}" [label="{label}"];\n')
# Add edges
for edge in self.edges:
f.write(f'  "{edge["source"]}" -- "{edge["destination"]}" [label="{edge["protocol"]}"];\n')
f.write('}\n')
print(f"Graphviz file generated: {filename}")
print("To render: dot -Tpng network_map.dot -o network_map.png")
def generate_ascii_map(self):
"""Generate simple ASCII representation of network"""
print("\nNetwork Map (ASCII)")
print("=" * 50)
# Group by IP class
by_class = {}
for ip in self.nodes:
first_octet = ip.split('.')[0]
if first_octet not in by_class:
by_class[first_octet] = []
by_class[first_octet].append(ip)
for net_class, ips in sorted(by_class.items()):
print(f"\nNetwork {net_class}.0.0.0/8:")
for ip in sorted(ips):
data = self.nodes[ip]
host_str = f"  ├─ {ip}"
if data['hostname']:
host_str += f" ({data['hostname']})"
if data['services']:
services_str = ", ".join([s.get('service', 'unknown') for s in data['services']])
host_str += f" [{services_str}]"
print(host_str)
# Show connections
connections = [e for e in self.edges if e['source'] == ip or e['destination'] == ip]
for conn in connections:
other = conn['destination'] if conn['source'] == ip else conn['source']
print(f"      └─ connects to {other} ({conn['protocol']})")
# Example network mapping
mapper = NetworkMapper()
# Add hosts
mapper.add_host("192.168.1.1", "router.local", "Linux", [{"port": 80, "service": "http"}])
mapper.add_host("192.168.1.10", "web01.local", "Ubuntu", [{"port": 80, "service": "nginx"}, {"port": 22, "service": "ssh"}])
mapper.add_host("192.168.1.20", "db01.local", "CentOS", [{"port": 3306, "service": "mysql"}])
mapper.add_host("192.168.1.100", "workstation", "Windows", [{"port": 3389, "service": "rdp"}])
# Add connections
mapper.add_connection("192.168.1.1", "192.168.1.10", "gateway")
mapper.add_connection("192.168.1.10", "192.168.1.20", "database")
mapper.add_connection("192.168.1.100", "192.168.1.10", "http")
# Generate maps
mapper.generate_ascii_map()
# mapper.generate_graphviz()

7. Practical Scanning with Nmap

class NmapWrapper:
"""Python wrapper for Nmap scanning"""
def __init__(self):
self.scan_results = {}
def run_nmap_scan(self, target, options):
"""Execute Nmap scan (conceptual - requires nmap installed)"""
print(f"\nRunning Nmap scan: nmap {options} {target}")
print("=" * 60)
# This is a conceptual implementation - actual execution requires nmap installed
# In practice, you'd use subprocess to call nmap or python-nmap library
scan_templates = {
"quick": "-T4 -F",
"intensive": "-T4 -A -p-",
"stealth": "-T2 -sS -f",
"service": "-sV --version-intensity 5",
"os": "-O --osscan-guess",
"script": "-sC --script default"
}
scan_type = options
if options in scan_templates:
actual_options = scan_templates[options]
else:
actual_options = options
print(f"Command: nmap {actual_options} {target}")
print("\nCommon Nmap Commands:")
print("  • Quick scan: nmap -T4 -F 192.168.1.0/24")
print("  • Service detection: nmap -sV 192.168.1.1")
print("  • OS detection: nmap -O 192.168.1.1")
print("  • Aggressive scan: nmap -A 192.168.1.1")
print("  • Full port scan: nmap -p- 192.168.1.1")
print("  • Script scan: nmap -sC 192.168.1.1")
print("  • UDP scan: nmap -sU 192.168.1.1")
@staticmethod
def nmap_script_categories():
"""Explain Nmap script categories"""
print("\nNmap Script Categories")
print("=" * 50)
categories = {
"auth": "Authentication credentials",
"broadcast": "Network broadcast discovery",
"brute": "Brute force attacks",
"default": "Default scripts (safe)",
"discovery": "Host/service discovery",
"dos": "Denial of service",
"exploit": "Exploitation",
"external": "External services (whois, etc.)",
"fuzzer": "Fuzzing",
"intrusive": "Potentially intrusive scripts",
"malware": "Malware detection",
"safe": "Safe scripts (no impact)",
"version": "Version detection",
"vuln": "Vulnerability detection"
}
for category, description in categories.items():
print(f"  • {category:<12}: {description}")
@staticmethod
def useful_nmap_scripts():
"""List useful Nmap scripts"""
print("\nUseful Nmap Scripts")
print("=" * 50)
scripts = {
"http-enum": "Enumerate web directories",
"http-headers": "Retrieve HTTP headers",
"http-title": "Get web page titles",
"smb-os-discovery": "Discover SMB OS",
"smb-enum-shares": "Enumerate SMB shares",
"ssl-cert": "Get SSL certificate details",
"ssl-enum-ciphers": "Enumerate SSL ciphers",
"dns-brute": "Brute force DNS subdomains",
"whois": "WHOIS lookup",
"vulners": "Check vulnerabilities"
}
for script, description in scripts.items():
print(f"  • {script:<20}: {description}")
# Example usage
nmap = NmapWrapper()
nmap.run_nmap_scan("192.168.1.0/24", "quick")
NmapWrapper.nmap_script_categories()

8. Network Mapping Tools Comparison

class ToolComparison:
"""Comparison of network mapping tools"""
tools = {
"Nmap": {
"type": "Command-line",
"features": ["Port scanning", "OS detection", "Service version", "Script engine"],
"best_for": "Comprehensive scanning, scripting",
"pros": "Powerful, flexible, extensive features",
"cons": "Steep learning curve"
},
"Masscan": {
"type": "Command-line",
"features": ["Very fast port scanning", "Internet-scale scanning"],
"best_for": "Large-scale, fast scanning",
"pros": "Extremely fast (millions packets/sec)",
"cons": "Less feature-rich than Nmap"
},
"Zmap": {
"type": "Command-line",
"features": ["Fast network scanning", "Protocol-specific modules"],
"best_for": "Internet-wide scanning",
"pros": "Very fast, efficient",
"cons": "No service detection"
},
"Zenmap": {
"type": "GUI",
"features": ["Nmap GUI", "Visualization", "Profiles"],
"best_for": "Beginners, visualization",
"pros": "User-friendly, graphical output",
"cons": "Limited compared to command line"
},
"Angry IP Scanner": {
"type": "GUI (Java)",
"features": ["IP scanning", "NetBIOS info", "Ping sweep"],
"best_for": "Quick network discovery",
"pros": "Cross-platform, simple interface",
"cons": "Limited features"
},
"Netcat": {
"type": "Command-line",
"features": ["Manual banner grabbing", "Port scanning"],
"best_for": "Manual exploration, scripts",
"pros": "Lightweight, versatile",
"cons": "Manual, no automation"
}
}
@classmethod
def compare(cls):
"""Display tool comparison"""
print("Network Mapping Tools Comparison")
print("=" * 80)
for name, details in cls.tools.items():
print(f"\n🔧 {name}")
print(f"   Type: {details['type']}")
print(f"   Features: {', '.join(details['features'])}")
print(f"   Best For: {details['best_for']}")
print(f"   Pros: {details['pros']}")
print(f"   Cons: {details['cons']}")
ToolComparison.compare()

9. Legal and Ethical Considerations

class LegalEthicalConsiderations:
"""Legal and ethical guidelines for network scanning"""
@staticmethod
def legal_guidelines():
"""Provide legal guidelines for network scanning"""
print("Legal Guidelines for Network Scanning")
print("=" * 60)
guidelines = [
"1. Authorization: Always obtain written permission before scanning",
"2. Scope: Only scan systems you own or have explicit permission for",
"3. Laws: Be aware of local and international laws (CFAA, Computer Misuse Act)",
"4. Data Protection: Handle discovered data responsibly",
"5. Disclosure: Report findings responsibly to relevant parties",
"6. Contract: Ensure scanning is within scope of agreements",
"7. Impact: Consider potential impact on production systems"
]
for guideline in guidelines:
print(f"  {guideline}")
@staticmethod
def ethical_principles():
"""Outline ethical principles for security testing"""
print("\nEthical Principles for Security Testing")
print("=" * 60)
principles = {
"Do No Harm": "Avoid disrupting services or damaging systems",
"Transparency": "Be open about your activities and findings",
"Confidentiality": "Protect discovered vulnerabilities and data",
"Integrity": "Do not modify or corrupt systems or data",
"Competence": "Only perform tests you're qualified to conduct",
"Responsibility": "Report findings appropriately and timely"
}
for principle, description in principles.items():
print(f"  • {principle}: {description}")
@staticmethod
def scanning_permission_template():
"""Provide template for scanning authorization"""
print("\nScanning Authorization Template")
print("=" * 60)
print("""
Authorization for Network Security Testing
I, [NAME], as [ROLE] of [ORGANIZATION], hereby authorize [TESTER_NAME] 
to perform network security testing including:
- Network discovery and host enumeration
- Port scanning (TCP and UDP)
- Service version detection
- OS fingerprinting
- Vulnerability scanning
Scope of testing:
- IP Ranges: [LIST IP RANGES]
- Time Window: [START DATE] to [END DATE]
- Systems Excluded: [LIST EXCLUDED SYSTEMS]
Authorized personnel: [NAMES]
Rules of Engagement:
- Testing will not intentionally disrupt services
- Findings will be reported confidentially
- Any critical findings will be reported immediately
Signed: ______________________
Date: ______________________
""")
LegalEthicalConsiderations.legal_guidelines()
LegalEthicalConsiderations.ethical_principles()

10. Practical Exercise: Network Discovery Script

class NetworkDiscoveryExercise:
"""Complete network discovery and scanning exercise"""
def __init__(self, target_network):
self.target_network = target_network
self.discovery_results = {
'live_hosts': [],
'open_ports': {},
'services': {},
'os_fingerprints': {},
'summary': {}
}
def run_full_discovery(self):
"""Run complete network discovery workflow"""
print("=" * 70)
print("NETWORK DISCOVERY AND MAPPING EXERCISE")
print("=" * 70)
# Step 1: Network Discovery
print("\n[1] NETWORK DISCOVERY")
print("-" * 40)
discovery = NetworkDiscovery()
if discovery.parse_network(self.target_network):
self.discovery_results['live_hosts'] = discovery.discover_hosts()
discovery.resolve_all_hostnames()
if not self.discovery_results['live_hosts']:
print("No live hosts found. Exiting.")
return
# Step 2: Port Scanning
print("\n[2] PORT SCANNING")
print("-" * 40)
scanner = TCPScanner()
common_ports = [21, 22, 23, 25, 53, 80, 443, 3306, 3389, 8080]
for host in self.discovery_results['live_hosts'][:3]:  # Limit to first 3 hosts
print(f"\nScanning {host.ip}:")
open_ports = scanner.tcp_connect_scan(host.ip, common_ports)
self.discovery_results['open_ports'][host.ip] = open_ports
# Step 3: Service Detection
print("\n[3] SERVICE DETECTION")
print("-" * 40)
detector = ServiceDetection()
for host in self.discovery_results['live_hosts'][:3]:
if host.ip in self.discovery_results['open_ports']:
services = detector.scan_services(host.ip, 
self.discovery_results['open_ports'][host.ip])
self.discovery_results['services'][host.ip] = services
# Step 4: OS Fingerprinting
print("\n[4] OS FINGERPRINTING")
print("-" * 40)
fingerprinter = OSFingerprinting()
for host in self.discovery_results['live_hosts'][:3]:
result = fingerprinter.tcp_os_fingerprint(host.ip, 80)
self.discovery_results['os_fingerprints'][host.ip] = result
print(f"\n{host.ip}: {result['os']} (confidence: {result['confidence']})")
# Step 5: Generate Report
self.generate_report()
return self.discovery_results
def generate_report(self):
"""Generate discovery report"""
print("\n" + "="*70)
print("NETWORK DISCOVERY REPORT")
print("="*70)
print(f"\nTarget Network: {self.target_network}")
print(f"Live Hosts Found: {len(self.discovery_results['live_hosts'])}")
print("\nHost Details:")
print("-" * 50)
for host in self.discovery_results['live_hosts'][:3]:
print(f"\n📡 {host.ip}")
if host.hostname:
print(f"   Hostname: {host.hostname}")
if host.ip in self.discovery_results['os_fingerprints']:
os_info = self.discovery_results['os_fingerprints'][host.ip]
print(f"   OS: {os_info['os']} ({os_info['confidence']} confidence)")
if host.ip in self.discovery_results['open_ports']:
print(f"   Open Ports: {', '.join(map(str, self.discovery_results['open_ports'][host.ip]))}")
if host.ip in self.discovery_results['services']:
print("   Services:")
for service in self.discovery_results['services'][host.ip]:
print(f"      • {service['port']}: {service['service']} "
f"(version: {service['version']})")
print("\n" + "="*70)
print("RECOMMENDATIONS")
print("="*70)
for host in self.discovery_results['live_hosts'][:3]:
if host.ip in self.discovery_results['open_ports']:
open_ports = self.discovery_results['open_ports'][host.ip]
for port in open_ports:
if port in [22, 23, 21]:
print(f"  • {host.ip} - Consider restricting access to port {port}")
if port in [80, 443]:
print(f"  • {host.ip} - Ensure web applications are up to date")
if port in [3306, 1433]:
print(f"  • {host.ip} - Database port exposed, consider firewall rules")
# Run the exercise
# exercise = NetworkDiscoveryExercise("192.168.1.0/24")
# results = exercise.run_full_discovery()

11. Security Hardening Recommendations

class SecurityHardening:
"""Network security hardening recommendations"""
@staticmethod
def hardening_guidelines():
"""Provide network hardening recommendations"""
print("Network Security Hardening Guidelines")
print("=" * 60)
categories = {
"Network Segmentation": [
"Implement VLANs to isolate different traffic types",
"Use firewalls to control inter-VLAN traffic",
"Create DMZ for public-facing services",
"Implement micro-segmentation for critical assets"
],
"Access Control": [
"Implement 802.1X for network authentication",
"Use ACLs to restrict traffic",
"Disable unused ports and services",
"Implement least privilege access"
],
"Monitoring": [
"Deploy IDS/IPS for threat detection",
"Implement centralized logging (SIEM)",
"Regular vulnerability scanning",
"Monitor for port scans and anomalies"
],
"Encryption": [
"Encrypt all sensitive traffic",
"Use strong cipher suites (TLS 1.3)",
"Implement VPN for remote access",
"Enable WPA3 for wireless networks"
],
"Configuration Management": [
"Harden network device configurations",
"Change default credentials",
"Regular security audits",
"Patch management process"
]
}
for category, recommendations in categories.items():
print(f"\n📌 {category}:")
for rec in recommendations:
print(f"   • {rec}")
SecurityHardening.hardening_guidelines()

Conclusion

Network mapping and port scanning are essential skills for cybersecurity professionals. This guide has covered:

Key Takeaways

  1. Discovery Techniques: ICMP, ARP, and TCP/UDP probes for host discovery
  2. Scanning Methods: Various port scanning techniques with different stealth levels
  3. Service Detection: Banner grabbing and fingerprinting for service identification
  4. OS Fingerprinting: TTL analysis, TCP stack behavior, and banner analysis
  5. Tools: Nmap, Masscan, and other network mapping utilities
  6. Legal/Ethical: Always obtain permission before scanning
  7. Hardening: Recommendations to protect against scanning

Common Ports to Know

PortServiceSecurity Concern
21FTPPlaintext authentication
22SSHWeak ciphers, brute force
23TelnetPlaintext communication
25SMTPOpen relay, spam
80HTTPLack of encryption
443HTTPSWeak SSL/TLS
3306MySQLDefault credentials
3389RDPBrute force attacks
445SMBEternalBlue, ransomware

Final Thoughts

Network mapping and port scanning are powerful reconnaissance techniques. Use them responsibly—only on systems you own or have explicit permission to test. The knowledge gained from these techniques helps organizations identify and fix vulnerabilities before attackers can exploit them.

Leave a Reply

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


Macro Nepal Helper