Skip to content

Commit 9e80d6e

Browse files
author
Tom Softreck
committed
update
1 parent 498f6ee commit 9e80d6e

1 file changed

Lines changed: 63 additions & 11 deletions

File tree

scripts/network_scanner.py

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66

77
import asyncio
88
import socket
9+
import aiohttp
910
import argparse
10-
from typing import List, Optional
11-
from dataclasses import dataclass
11+
import json
12+
from typing import List, Optional, Dict, Any
13+
from dataclasses import dataclass, asdict
1214

1315
@dataclass
1416
class NetworkService:
@@ -49,15 +51,59 @@ async def check_port(self, ip: str, port: int) -> bool:
4951
writer.close()
5052
await writer.wait_closed()
5153
return True
52-
except (asyncio.TimeoutError, ConnectionRefusedError, OSError):
54+
except (asyncio.TimeoutError, ConnectionRefusedError, OSError, ConnectionResetError):
5355
return False
5456

55-
def identify_service(self, port: int) -> str:
56-
"""Identify service based on port number."""
57+
async def identify_service(self, ip: str, port: int) -> Dict[str, Any]:
58+
"""Identify service running on the port."""
59+
# First check common ports
5760
for service, ports in self.COMMON_PORTS.items():
5861
if port in ports:
62+
return {
63+
'service': service,
64+
'protocol': 'tcp',
65+
'secure': port in [443, 8443, 8883],
66+
'banner': ''
67+
}
68+
69+
# Try to identify web services
70+
if port in [80, 443, 8080, 8000, 8001, 8888, 8443]:
71+
is_https = port in [443, 8443]
72+
service = await self.check_web_service(ip, port, is_https)
73+
if service:
5974
return service
60-
return "unknown"
75+
76+
return {
77+
'service': 'unknown',
78+
'protocol': 'tcp',
79+
'secure': False,
80+
'banner': ''
81+
}
82+
83+
async def check_web_service(self, ip: str, port: int, is_https: bool = False) -> Optional[Dict[str, Any]]:
84+
"""Check if a web service is running on the port."""
85+
protocol = 'https' if is_https else 'http'
86+
url = f"{protocol}://{ip}:{port}"
87+
88+
try:
89+
async with aiohttp.ClientSession() as session:
90+
try:
91+
async with session.get(url, timeout=aiohttp.ClientTimeout(total=self.timeout),
92+
ssl=False, allow_redirects=True) as response:
93+
if response.status < 500: # Any success or client error
94+
return {
95+
'service': 'http' if not is_https else 'https',
96+
'protocol': 'tcp',
97+
'secure': is_https,
98+
'banner': f"HTTP {response.status} {response.reason}",
99+
'headers': dict(response.headers)
100+
}
101+
except (aiohttp.ClientError, asyncio.TimeoutError):
102+
pass
103+
except Exception as e:
104+
pass
105+
106+
return None
61107

62108
async def scan_network(
63109
self,
@@ -92,12 +138,18 @@ async def scan_network(
92138
async def scan_port(self, ip: str, port: int) -> NetworkService:
93139
"""Scan a single port and return service info."""
94140
is_open = await self.check_port(ip, port)
95-
service = self.identify_service(port)
141+
if not is_open:
142+
return NetworkService(ip=ip, port=port, is_up=False)
143+
144+
service_info = await self.identify_service(ip, port)
96145
return NetworkService(
97146
ip=ip,
98147
port=port,
99-
service=service,
100-
is_up=is_open
148+
service=service_info['service'],
149+
protocol=service_info['protocol'],
150+
banner=service_info.get('banner', ''),
151+
is_secure=service_info.get('secure', False),
152+
is_up=True
101153
)
102154

103155
async def main():
@@ -109,8 +161,8 @@ async def main():
109161
help='Service types to scan (rtsp, http, https, ssh, etc.)')
110162
parser.add_argument('--port', '-p', default=None,
111163
help='Comma-separated list of ports or port ranges to scan (e.g., 80,443,8000-9000)')
112-
parser.add_argument('--timeout', '-t', type=float, default=1.0,
113-
help='Connection timeout in seconds (default: 1.0)')
164+
parser.add_argument('--timeout', '-t', type=float, default=3.0,
165+
help='Connection timeout in seconds (default: 3.0)')
114166
parser.add_argument('--verbose', '-v', action='store_true',
115167
help='Show detailed output')
116168

0 commit comments

Comments
 (0)