2025-08-03 11:16:25 +02:00
|
|
|
import asyncio
|
|
|
|
import socket
|
|
|
|
import ipaddress
|
|
|
|
import platform
|
|
|
|
from tqdm import tqdm
|
|
|
|
|
|
|
|
def get_local_ip():
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
try:
|
|
|
|
s.connect(('8.8.8.8', 80))
|
|
|
|
ip = s.getsockname()[0]
|
|
|
|
except Exception:
|
|
|
|
ip = '127.0.0.1'
|
|
|
|
finally:
|
|
|
|
s.close()
|
|
|
|
return ip
|
|
|
|
|
|
|
|
async def ping(ip):
|
|
|
|
ping_cmd = f"ping -n 1 -w 1000 {ip}" if platform.system() == 'Windows' else f"ping -c 1 -W 1 {ip}"
|
|
|
|
try:
|
|
|
|
proc = await asyncio.create_subprocess_shell(
|
|
|
|
ping_cmd,
|
|
|
|
stdout=asyncio.subprocess.DEVNULL,
|
|
|
|
stderr=asyncio.subprocess.DEVNULL
|
|
|
|
)
|
|
|
|
returncode = await proc.wait()
|
|
|
|
return returncode == 0
|
|
|
|
except Exception:
|
|
|
|
return False
|
|
|
|
|
|
|
|
async def check_port(ip, port, timeout=1):
|
|
|
|
try:
|
|
|
|
reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout)
|
2025-08-04 00:49:53 +02:00
|
|
|
try:
|
|
|
|
banner = await asyncio.wait_for(reader.read(1024), 1.0)
|
|
|
|
banner = banner.decode('utf-8', errors='ignore').strip()
|
|
|
|
except:
|
|
|
|
banner = ''
|
2025-08-03 11:16:25 +02:00
|
|
|
writer.close()
|
|
|
|
await writer.wait_closed()
|
2025-08-04 00:49:53 +02:00
|
|
|
return True, banner
|
2025-08-03 11:16:25 +02:00
|
|
|
except:
|
2025-08-04 00:49:53 +02:00
|
|
|
return False, ''
|
2025-08-03 11:16:25 +02:00
|
|
|
|
|
|
|
async def scan_ip(ip, ports, ports_services):
|
|
|
|
ip_str = str(ip)
|
|
|
|
if not await ping(ip_str):
|
|
|
|
return ip_str, False, []
|
|
|
|
tasks = [check_port(ip_str, port) for port in ports]
|
|
|
|
results = await asyncio.gather(*tasks)
|
2025-08-04 00:49:53 +02:00
|
|
|
open_ports = [(port, ports_services.get(port, 'Unknown'), banner) for port, (is_open, banner) in zip(ports, results) if is_open]
|
2025-08-03 11:16:25 +02:00
|
|
|
return ip_str, True, open_ports
|
|
|
|
|
|
|
|
async def full_scan(ip, ports_services):
|
|
|
|
all_ports = range(1, 65536)
|
|
|
|
sem = asyncio.Semaphore(200)
|
|
|
|
with tqdm(total=len(all_ports), desc=f"Full scan {ip}") as pbar:
|
|
|
|
async def check(port):
|
|
|
|
async with sem:
|
2025-08-04 00:49:53 +02:00
|
|
|
is_open, banner = await check_port(ip, port, timeout=0.5)
|
|
|
|
if is_open:
|
2025-08-03 11:16:25 +02:00
|
|
|
service = ports_services.get(port, 'Unknown')
|
|
|
|
pbar.update(1)
|
2025-08-04 00:49:53 +02:00
|
|
|
return (port, service, banner)
|
2025-08-03 11:16:25 +02:00
|
|
|
else:
|
|
|
|
pbar.update(1)
|
|
|
|
return None
|
|
|
|
tasks = [check(port) for port in all_ports]
|
|
|
|
results = await asyncio.gather(*tasks)
|
|
|
|
open_ports = sorted([p for p in results if p is not None])
|
|
|
|
return ip, open_ports
|
|
|
|
|
2025-08-04 00:49:53 +02:00
|
|
|
async def get_dns_info(ip_str):
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
for attempt in range(3):
|
|
|
|
try:
|
|
|
|
hostname = (await loop.run_in_executor(None, socket.gethostbyaddr, ip_str))[0]
|
|
|
|
a_record = await loop.run_in_executor(None, socket.gethostbyname, hostname)
|
|
|
|
return hostname, a_record
|
|
|
|
except Exception as e:
|
|
|
|
print(f"Attempt {attempt+1} failed for {ip_str}: {e}")
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
return "Unknown", "Unknown"
|
|
|
|
|
2025-08-03 11:16:25 +02:00
|
|
|
async def main():
|
|
|
|
local_ip = get_local_ip()
|
|
|
|
network = ipaddress.IPv4Network(f"{local_ip}/24", strict=False)
|
|
|
|
ports_services = {
|
|
|
|
1: 'TCPMUX',
|
|
|
|
7: 'Echo',
|
|
|
|
9: 'Discard',
|
|
|
|
13: 'Daytime',
|
|
|
|
17: 'QOTD',
|
|
|
|
19: 'Chargen',
|
|
|
|
20: 'FTP Data',
|
|
|
|
21: 'FTP Control',
|
|
|
|
22: 'SSH',
|
|
|
|
23: 'Telnet',
|
|
|
|
25: 'SMTP',
|
|
|
|
37: 'Time',
|
|
|
|
39: 'RLP',
|
|
|
|
42: 'Nameserver',
|
|
|
|
43: 'WHOIS',
|
|
|
|
49: 'TACACS',
|
|
|
|
53: 'DNS',
|
|
|
|
67: 'BOOTPS',
|
|
|
|
68: 'BOOTPC',
|
|
|
|
69: 'TFTP',
|
|
|
|
70: 'Gopher',
|
|
|
|
79: 'Finger',
|
|
|
|
80: 'HTTP',
|
|
|
|
81: 'Hosts2-NS',
|
|
|
|
88: 'Kerberos',
|
|
|
|
102: 'ISO-TSAP',
|
|
|
|
107: 'RTelnet',
|
|
|
|
109: 'POP2',
|
|
|
|
110: 'POP3',
|
|
|
|
111: 'SunRPC',
|
|
|
|
113: 'Ident',
|
|
|
|
115: 'SFTP',
|
|
|
|
119: 'NNTP',
|
|
|
|
123: 'NTP',
|
|
|
|
135: 'MS RPC',
|
|
|
|
137: 'NetBIOS Name',
|
|
|
|
138: 'NetBIOS Datagram',
|
|
|
|
139: 'NetBIOS Session',
|
|
|
|
143: 'IMAP',
|
|
|
|
161: 'SNMP',
|
|
|
|
162: 'SNMP Trap',
|
|
|
|
179: 'BGP',
|
|
|
|
194: 'IRC',
|
|
|
|
201: 'AppleTalk Routing',
|
|
|
|
209: 'QMTP',
|
|
|
|
213: 'IPX',
|
|
|
|
220: 'IMAPv3',
|
|
|
|
389: 'LDAP',
|
|
|
|
401: 'UPS',
|
|
|
|
427: 'SLP',
|
|
|
|
443: 'HTTPS',
|
|
|
|
445: 'Microsoft DS',
|
|
|
|
464: 'Kerberos Change',
|
|
|
|
465: 'SMTPS',
|
|
|
|
497: 'Dantz Retrospect',
|
|
|
|
500: 'ISAKMP',
|
|
|
|
512: 'Exec',
|
|
|
|
513: 'Login',
|
|
|
|
514: 'Syslog',
|
|
|
|
515: 'LPD',
|
|
|
|
520: 'RIP',
|
|
|
|
543: 'Klogin',
|
|
|
|
544: 'Kshell',
|
|
|
|
546: 'DHCPv6 Client',
|
|
|
|
547: 'DHCPv6 Server',
|
|
|
|
554: 'RTSP',
|
|
|
|
563: 'NNTPS',
|
|
|
|
587: 'SMTP Submission',
|
|
|
|
591: 'FileMaker',
|
|
|
|
593: 'HTTP RPC',
|
|
|
|
631: 'IPP',
|
|
|
|
636: 'LDAPS',
|
|
|
|
639: 'MSDP',
|
|
|
|
646: 'LDP',
|
|
|
|
691: 'MS Exchange',
|
|
|
|
749: 'Kerberos Admin',
|
|
|
|
873: 'rsync',
|
|
|
|
990: 'FTPS',
|
|
|
|
993: 'IMAPS',
|
|
|
|
994: 'IRCS',
|
|
|
|
995: 'POP3S',
|
|
|
|
1080: 'SOCKS',
|
|
|
|
1194: 'OpenVPN',
|
|
|
|
1433: 'MSSQL',
|
|
|
|
1434: 'MSSQL Monitor',
|
|
|
|
1521: 'Oracle',
|
|
|
|
1720: 'H.323',
|
|
|
|
1723: 'PPTP',
|
|
|
|
1741: 'CiscoWorks',
|
|
|
|
1812: 'RADIUS',
|
|
|
|
1813: 'RADIUS Acct',
|
2025-08-04 00:49:53 +02:00
|
|
|
1984: 'Big Brother Monitor',
|
2025-08-03 11:16:25 +02:00
|
|
|
1985: 'HSRP',
|
|
|
|
2000: 'Cisco SCCP',
|
|
|
|
2049: 'NFS',
|
|
|
|
2082: 'cPanel',
|
|
|
|
2083: 'cPanel SSL',
|
|
|
|
2086: 'WHM',
|
|
|
|
2087: 'WHM SSL',
|
|
|
|
2095: 'cPanel Webmail',
|
|
|
|
2096: 'cPanel Webmail SSL',
|
|
|
|
2100: 'Oracle XDB FTP',
|
|
|
|
2222: 'DirectAdmin',
|
2025-08-04 00:49:53 +02:00
|
|
|
2242: 'Folio Remote Server',
|
|
|
|
2248: 'User Management Service',
|
|
|
|
2280: 'LNVPOLLER',
|
2025-08-03 11:16:25 +02:00
|
|
|
2301: 'Compaq Insight',
|
|
|
|
2381: 'HP Insight',
|
|
|
|
2401: 'CVS',
|
|
|
|
2433: 'MS SQL Analysis',
|
|
|
|
2483: 'Oracle DB SSL',
|
|
|
|
2484: 'Oracle DB SSL',
|
|
|
|
2638: 'Sybase',
|
|
|
|
2710: 'XBT Tracker',
|
2025-08-04 00:49:53 +02:00
|
|
|
3000: 'Ruby on Rails',
|
|
|
|
3050: 'Interbase/Firebird',
|
|
|
|
3100: 'OpCon/xps',
|
2025-08-03 11:16:25 +02:00
|
|
|
3128: 'Squid',
|
|
|
|
3260: 'iSCSI',
|
|
|
|
3268: 'AD Global Catalog',
|
|
|
|
3269: 'AD Global Catalog SSL',
|
|
|
|
3306: 'MySQL',
|
|
|
|
3389: 'RDP',
|
|
|
|
3478: 'STUN',
|
|
|
|
3690: 'SVN',
|
|
|
|
3784: 'Ventrilo',
|
|
|
|
3785: 'Ventrilo',
|
|
|
|
3899: 'Remote Web Workplace',
|
|
|
|
4000: 'Diablo II',
|
2025-08-04 00:49:53 +02:00
|
|
|
4190: 'Sieve Mail Filter',
|
2025-08-03 11:16:25 +02:00
|
|
|
4321: 'BoBo',
|
2025-08-04 00:49:53 +02:00
|
|
|
4369: 'Erlang EPMD',
|
|
|
|
4431: 'adWISE Pipe',
|
2025-08-03 11:16:25 +02:00
|
|
|
4664: 'Google Desktop',
|
|
|
|
4899: 'Radmin',
|
2025-08-04 00:49:53 +02:00
|
|
|
4949: 'Munin',
|
2025-08-03 11:16:25 +02:00
|
|
|
5000: 'UPnP',
|
|
|
|
5001: 'Synology',
|
|
|
|
5009: 'Airport Admin',
|
|
|
|
5051: 'IDA Agent',
|
|
|
|
5060: 'SIP',
|
|
|
|
5190: 'AIM/ICQ',
|
|
|
|
5222: 'XMPP',
|
|
|
|
5269: 'XMPP SSL',
|
|
|
|
5432: 'PostgreSQL',
|
2025-08-04 00:49:53 +02:00
|
|
|
54744: 'Unknown',
|
2025-08-03 11:16:25 +02:00
|
|
|
5500: 'VNC Hotline',
|
|
|
|
5554: 'Sasser',
|
2025-08-04 00:49:53 +02:00
|
|
|
5555: 'ADB',
|
2025-08-03 11:16:25 +02:00
|
|
|
5631: 'pcAnywhere Data',
|
|
|
|
5632: 'pcAnywhere Master',
|
|
|
|
5800: 'VNC HTTP',
|
|
|
|
5900: 'VNC',
|
|
|
|
6000: 'X11',
|
|
|
|
6112: 'Battle.net',
|
|
|
|
6129: 'DameWare',
|
|
|
|
6346: 'Gnutella',
|
|
|
|
6347: 'Gnutella',
|
|
|
|
6379: 'Redis',
|
|
|
|
6665: 'IRC',
|
|
|
|
6666: 'IRC',
|
|
|
|
6667: 'IRC',
|
|
|
|
6668: 'IRC',
|
|
|
|
6669: 'IRC',
|
|
|
|
6697: 'IRC SSL',
|
|
|
|
6881: 'BitTorrent',
|
|
|
|
6969: 'BitTorrent',
|
2025-08-04 00:49:53 +02:00
|
|
|
7071: 'IWC Replica',
|
2025-08-03 11:16:25 +02:00
|
|
|
7212: 'GhostSite',
|
|
|
|
7777: 'Oracle Web',
|
|
|
|
8000: 'HTTP Alternate',
|
2025-08-04 00:49:53 +02:00
|
|
|
8001: 'VCOM Tunnel',
|
|
|
|
8006: 'Proxmox VE',
|
2025-08-03 11:16:25 +02:00
|
|
|
8008: 'HTTP Alternate',
|
2025-08-04 00:49:53 +02:00
|
|
|
8009: 'AJP',
|
2025-08-03 11:16:25 +02:00
|
|
|
8080: 'HTTP Alternate',
|
|
|
|
8081: 'HTTP Alternate',
|
2025-08-04 00:49:53 +02:00
|
|
|
8088: 'HTTP Alternate',
|
|
|
|
8089: 'Splunk',
|
|
|
|
8090: 'HTTP Alternate',
|
2025-08-03 11:16:25 +02:00
|
|
|
8118: 'Privoxy',
|
|
|
|
8200: 'MiniDLNA',
|
2025-08-04 00:49:53 +02:00
|
|
|
8424: 'Unknown',
|
2025-08-03 11:16:25 +02:00
|
|
|
8443: 'HTTPS Alternate',
|
|
|
|
8554: 'RTSP Alternate',
|
2025-08-04 00:49:53 +02:00
|
|
|
8762: 'Unknown',
|
2025-08-03 11:16:25 +02:00
|
|
|
8767: 'TeamSpeak',
|
|
|
|
8888: 'HTTP Alternate',
|
|
|
|
9000: 'SonarQube',
|
|
|
|
9001: 'Tor',
|
2025-08-04 00:49:53 +02:00
|
|
|
9002: 'Dynamix',
|
|
|
|
9003: 'Unknown',
|
2025-08-03 11:16:25 +02:00
|
|
|
9030: 'Tor',
|
|
|
|
9040: 'Tor',
|
|
|
|
9050: 'Tor',
|
|
|
|
9100: 'JetDirect',
|
|
|
|
9119: 'MXit',
|
|
|
|
9200: 'Elasticsearch',
|
2025-08-04 00:49:53 +02:00
|
|
|
9230: 'Unknown',
|
2025-08-03 11:16:25 +02:00
|
|
|
9418: 'Git',
|
|
|
|
9999: 'Abyss',
|
|
|
|
10000: 'Webmin',
|
|
|
|
11371: 'OpenPGP',
|
|
|
|
12345: 'NetBus',
|
|
|
|
13720: 'NetBackup',
|
|
|
|
13721: 'NetBackup',
|
|
|
|
13724: 'Veritas',
|
|
|
|
13782: 'Veritas',
|
|
|
|
13783: 'Veritas',
|
|
|
|
19226: 'Panda',
|
|
|
|
19638: 'Ensim',
|
|
|
|
20000: 'Usermin',
|
|
|
|
22222: 'EasyEngine',
|
|
|
|
24800: 'Synergy',
|
|
|
|
25999: 'Yahoo IM',
|
|
|
|
27015: 'Half-Life',
|
|
|
|
27017: 'MongoDB',
|
|
|
|
27374: 'Sub7',
|
|
|
|
28015: 'Rust',
|
|
|
|
31337: 'Back Orifice',
|
|
|
|
33434: 'Traceroute',
|
|
|
|
37777: 'Dahua DVR',
|
|
|
|
40193: 'Novell',
|
|
|
|
41523: 'MS SQL',
|
|
|
|
43594: 'Runescape',
|
|
|
|
43595: 'Runescape',
|
|
|
|
44818: 'EtherNet/IP',
|
|
|
|
47808: 'BACnet',
|
|
|
|
49152: 'Dynamic',
|
|
|
|
49153: 'Dynamic',
|
|
|
|
49154: 'Dynamic',
|
|
|
|
49155: 'Dynamic',
|
|
|
|
49156: 'Dynamic',
|
|
|
|
49157: 'Dynamic',
|
|
|
|
55555: 'FreeCiv',
|
|
|
|
60000: 'Deep Throat',
|
|
|
|
65000: 'Stacheldraht'
|
|
|
|
}
|
|
|
|
ports = list(ports_services.keys())
|
|
|
|
|
|
|
|
tasks = [scan_ip(ip, ports, ports_services) for ip in network.hosts()]
|
|
|
|
results = await asyncio.gather(*tasks)
|
|
|
|
|
|
|
|
active_devices = []
|
|
|
|
common_open_ports = {}
|
|
|
|
for ip, active, open_ports in results:
|
|
|
|
if active:
|
|
|
|
active_devices.append(ip)
|
|
|
|
if open_ports:
|
2025-08-04 00:49:53 +02:00
|
|
|
common_open_ports[str(ip)] = open_ports
|
|
|
|
|
|
|
|
dns_tasks = [get_dns_info(str(ip)) for ip in active_devices]
|
|
|
|
dns_results = await asyncio.gather(*dns_tasks)
|
|
|
|
dns_infos = {str(active_devices[i]): dns_results[i] for i in range(len(active_devices))}
|
|
|
|
|
|
|
|
devices_need_full = []
|
|
|
|
for ip in active_devices:
|
|
|
|
ip_str = str(ip)
|
|
|
|
if common_open_ports.get(ip_str) or dns_infos[ip_str][0] != "Unknown":
|
|
|
|
devices_need_full.append(ip_str)
|
2025-08-03 11:16:25 +02:00
|
|
|
|
|
|
|
full_tasks = [full_scan(ip, ports_services) for ip in devices_need_full]
|
|
|
|
full_results = await asyncio.gather(*full_tasks)
|
|
|
|
|
2025-08-04 00:49:53 +02:00
|
|
|
devices_with_open_ports = {}
|
|
|
|
for ip in active_devices:
|
|
|
|
ip_str = str(ip)
|
|
|
|
devices_with_open_ports[ip_str] = common_open_ports.get(ip_str, [])
|
|
|
|
|
2025-08-03 11:16:25 +02:00
|
|
|
for full_ip, full_open in full_results:
|
|
|
|
devices_with_open_ports[full_ip] = full_open
|
|
|
|
|
|
|
|
print("Active devices:")
|
|
|
|
for dev in active_devices:
|
|
|
|
print(dev)
|
|
|
|
|
|
|
|
print("\nDevices with open ports:")
|
|
|
|
for ip, open_ports in devices_with_open_ports.items():
|
2025-08-04 00:49:53 +02:00
|
|
|
hostname, a_record = dns_infos[ip]
|
|
|
|
print(f"{ip} (Hostname: {hostname}, A: {a_record}):")
|
|
|
|
if hostname != "Unknown":
|
|
|
|
print(f" DNS Records:")
|
|
|
|
print(f" PTR: {hostname}")
|
|
|
|
print(f" A: {a_record}")
|
|
|
|
for port, service, banner in open_ports:
|
|
|
|
print(f" - {port}: {service}" + (f" ({banner})" if banner else ""))
|
2025-08-03 11:16:25 +02:00
|
|
|
|
|
|
|
asyncio.run(main())
|