-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
101 lines (84 loc) · 3.46 KB
/
main.py
File metadata and controls
101 lines (84 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python3
import socket
import sys
import argparse
from datetime import datetime
from scapy.all import IP, TCP, sr1
import random
def scan_syn_port(ip, port, timeout=1):
"""Perform a SYN scan on a single port."""
src_port = random.randint(1024, 65535) # Random source port for stealth
syn_pkt = IP(dst=ip) / TCP(sport=src_port, dport=port, flags="S")
response = sr1(syn_pkt, timeout=timeout, verbose=0)
if response is None:
return False
if response.haslayer(TCP):
if response[TCP].flags == 0x12: # SYN-ACK indicates open port
# Send RST to close the connection gracefully
rst_pkt = IP(dst=ip) / TCP(sport=src_port, dport=port, flags="R")
sr1(rst_pkt, timeout=1, verbose=0)
return True
elif response[TCP].flags == 0x14: # RST-ACK indicates closed port
return False
return False
def scan_tcp_connect_port(ip, port):
"""Perform a TCP Connect scan on a single port."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1) # Set timeout to 1 second
result = sock.connect_ex((ip, port))
sock.close()
return result == 0 # True if port is open
except socket.error:
return False
def scan_ports(ip, start_port, end_port, use_syn=False):
"""Scan a range of ports on the target IP."""
print(f"\nScanning host: {ip}")
print(f"Scan started at: {datetime.now()}")
print("-" * 50)
open_ports = []
for port in range(start_port, end_port + 1):
is_open = scan_syn_port(ip, port) if use_syn else scan_tcp_connect_port(ip, port)
if is_open:
open_ports.append(port)
print(f"Port {port}: Open")
return open_ports
def main():
"""Main function to handle command-line arguments and execute the port scan."""
parser = argparse.ArgumentParser(description="CLI Port Scanner with TCP Connect and SYN scan options")
parser.add_argument("host", help="Target IP address or hostname to scan")
parser.add_argument("start_port", type=int, help="Starting port number")
parser.add_argument("end_port", type=int, help="Ending port number")
parser.add_argument("syn_scan", type=str, choices=['yes', 'no'], help="Use SYN scanning (yes/no, requires root privileges for SYN)")
args = parser.parse_args()
try:
# Resolve hostname to IP address
target_ip = socket.gethostbyname(args.host)
except socket.gaierror:
print("Error: Unable to resolve hostname!")
sys.exit(1)
# Validate port range
if args.start_port < 1 or args.end_port > 65535 or args.start_port > args.end_port:
print("Error: Invalid port range! Ports must be between 1 and 65535.")
sys.exit(1)
try:
use_syn = args.syn_scan == 'yes'
if use_syn:
print("Performing SYN scan (requires root privileges)...")
else:
print("Performing TCP Connect scan...")
open_ports = scan_ports(target_ip, args.start_port, args.end_port, use_syn=use_syn)
print("-" * 50)
if open_ports:
print(f"Open ports: {open_ports}")
else:
print("No open ports found.")
print(f"Scan completed at: {datetime.now()}")
except KeyboardInterrupt:
print("\nScan interrupted by user.")
sys.exit(0)
except socket.error:
print("Error: Network connectivity issue.")
sys.exit(1)
if __name__ == "__main__":
main()