深入现代网络扫描器原理与实践:自制 Python SYN 扫描器与服务指纹识别
1. 引言:现代网络扫描器的重要性
网络扫描器是安全工作中基础且强大的工具。理解现代扫描器技术,能更好应对网络安全挑战。现代扫描器需具备:高速扫描、精准识别、深度检测、规避检测、灵活扩展等特性。
本文将剖析现代扫描器原理,并实践自制 Python SYN 扫描器和服务指纹识别,助您理解底层技术,提升安全工具开发技能。
2. 现代网络扫描器架构与核心原理
现代扫描器是复杂系统,核心架构包括:扫描引擎、服务指纹识别模块、漏洞检测模块、任务管理、配置管理、用户界面、数据存储等组件。
2.1 核心扫描技术:SYN 扫描
原理: SYN 扫描利用 TCP 三次握手,只发 SYN 包,不完成三次握手。
-
扫描过程: 发送 SYN 包 -> 收 SYN-ACK (开放) 或 RST (关闭)。
-
优势: 快速、隐蔽、准确。
-
代码实现 (Python Raw Socket):
import socket import struct import time import random import array def syn_scan_port(target_ip, port): """SYN 扫描单个端口""" try: # 创建 Raw Socket raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) raw_socket.settimeout(2) # 构造 IP 头部 ip_header = struct.pack('!BBHHHBBHLL', 0x45, 0, 20+20, random.randint(1, 65535), 0, 64, socket.IPPROTO_TCP, 0, socket.inet_aton('192.168.1.102'), socket.inet_aton(target_ip)) # 构造 TCP 头部 tcp_header = struct.pack('!HHLLBBHHH', random.randint(1024, 65535), port, 0, 0, 5 << 4 | 0, 0, 0, 0, 0) tcp_syn_flags = 0x02 tcp_header_list = list(struct.unpack('!HHLLBBHHH', tcp_header)) tcp_header_list[4] = (tcp_header_list[4] | tcp_syn_flags) tcp_header = struct.pack('!HHLLBBHHH', *tcp_header_list) # 计算校验和 ip_checksum = calculate_checksum(ip_header) ip_header = ip_header[:10] + struct.pack('!H', ip_checksum) + ip_header[12:] pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton('192.168.1.102'), socket.inet_aton(target_ip), 0, socket.IPPROTO_TCP, len(tcp_header)) tcp_checksum = calculate_checksum(pseudo_header + tcp_header) tcp_header = tcp_header[:16] + struct.pack('!H', tcp_checksum) + tcp_header[18:] # 发送 SYN 数据包 packet = ip_header + tcp_header raw_socket.sendto(packet, (target_ip, port)) # 接收响应 recv_packet = raw_socket.recvfrom(65535) ip_header_reply = recv_packet[0][0:20] ip_header_unpack = struct.unpack('!BBHHHBBHLL', ip_header_reply) ip_protocol_reply = ip_header_unpack[6] tcp_header_reply = recv_packet[0][ip_header_unpack[2]:ip_header_unpack[2]+20] tcp_header_unpack_reply = struct.unpack('!HHLLBBHHH', tcp_header_reply) tcp_flags_reply = tcp_header_unpack_reply[5] # 判断端口状态 if tcp_flags_reply & 0x12 == 0x12: return "open" elif tcp_flags_reply & 0x14 == 0x14: return "closed" else: return "filtered" except socket.timeout: return "filtered" except socket.error: return "error" finally: if 'raw_socket' in locals(): raw_socket.close() def calculate_checksum(packet): """计算 IP/TCP 头部校验和""" if len(packet) % 2 != 0: packet += b'\0' res = sum(array.unpack("!H", packet[i:i+2])[0] for i in range(0, len(packet), 2)) res = (res >> 16) + (res & 0xffff) res += res >> 16 return (~res) & 0xffff
2.2 服务指纹识别技术 (HTTP 服务为例)
服务指纹识别旨在识别服务类型和版本。常用技术包括 Banner Grabbing、协议分析、应用层探测,并依赖服务指纹数据库。
-
HTTP 服务指纹识别实现 (Python):
# ... (之前的 SYN 扫描代码) ... SERVICE_FINGERPRINTS = { # 简化的 HTTP 服务指纹数据库 "nginx": ["nginx"], "apache": ["Apache", "httpd"], "iis": ["Microsoft-IIS", "Microsoft IIS"] } def get_http_banner(target_ip, port): """获取 HTTP 服务 Banner 信息""" try: client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.settimeout(3) client_socket.connect((target_ip, port)) http_get_request = b"GET / HTTP/1.1\r\nHost: " + target_ip.encode() + b"\r\n\r\n" client_socket.sendall(http_get_request) response = client_socket.recv(4096).decode('utf-8', errors='ignore') headers = response.split('\r\n\r\n')[0] server_banner = "" for header_line in headers.split('\r\n'): if header_line.startswith("Server:"): server_banner = header_line.split("Server:")[1].strip() break client_socket.close() return server_banner except socket.timeout: return None except socket.error: return None def identify_service(banner): """根据 Banner 信息识别服务类型""" if not banner: return "Unknown Service" banner_lower = banner.lower() for service_name, fingerprints in SERVICE_FINGERPRINTS.items(): for fingerprint in fingerprints: if fingerprint.lower() in banner_lower: return service_name.capitalize() return "Unknown Service" # ... (main 函数) ... def main(): import argparse import sys import ipaddress COMMON_PORTS = [21, 22, 23, 25, 53, 80, 110, 135, 139, 443, 445, 1433, 1521, 3306, 3389, 5900, 6379, 8080] VULN_SIGNATURES = {} # 漏洞检测特征 (精简版去掉了漏洞检测) parser = argparse.ArgumentParser(description="Python Network Scanner (SYN Scan & Service Fingerprinting)") parser.add_argument("target", help="Target IP address or IP range") parser.add_argument("-p", "--ports", help="Ports to scan (comma-separated), default common", default="common") args = parser.parse_args() target = args.target ports_arg = args.ports if ports_arg == "common": ports = COMMON_PORTS else: try: ports = [int(p) for p in ports_arg.split(',')] except ValueError: print("[-] Invalid port format.") sys.exit(1) if '/' in target: try: ip_network = ipaddress.ip_network(target, strict=False) print(f"[*] Scanning IP range: {ip_network}") for ip in ip_network: print(f"[*] Scanning IP: {ip}") for port in ports: port_status = syn_scan_port(str(ip), port) if port_status == "open": service_banner = get_http_banner(str(ip), port) service_name = identify_service(service_banner) print(f"[+] Port {port} is Open (SYN Scan) - Service: {service_name}") if service_banner: print(f" [Banner]: {service_banner.strip()}") elif port_status == "closed": print(f"[-] Port {port} is Closed (SYN Scan)") elif port_status == "filtered": print(f"[*] Port {port} is Filtered (SYN Scan)") elif port_status == "error": print(f"[-] Port {port} Scan Error") except ValueError: print("[-] Invalid IP range format.") sys.exit(1) else: print(f"[*] Scanning target IP: {target}") for port in ports: port_status = syn_scan_port(target, port) if port_status == "open": service_banner = get_http_banner(target, port) service_name = identify_service(service_banner) print(f"[+] Port {port} is Open (SYN Scan) - Service: {service_name}") if service_banner: print(f" [Banner]: {service_banner.strip()}") elif port_status == "closed": print(f"[-] Port {port} is Closed (SYN Scan)") elif port_status == "filtered": print(f"[*] Port {port} is Filtered (SYN Scan)") elif port_status == "error": print(f"[-] Port {port} Scan Error") if __name__ == "__main__": main()
3. 扫描器使用方法
与之前版本相同,使用命令行参数配置目标和端口。
示例:
python3 scanner.py 192.168.1.102python3 scanner.py 192.168.1.0/24 -p 80,443
示例输出:
[*] Scanning target IP: 192.168.1.102
[+] Port 22 is Filtered (SYN Scan)
[+] Port 80 is Open (SYN Scan) - Service: Nginx
[Banner]: nginx/1.14.0
[+] Port 443 is Open (SYN Scan) - Service: Apache
[Banner]: Apache/2.2.31 (Unix)
[+] Port 3389 is Closed (SYN Scan)
[*] SYN Scan Finished.
4. 局限性与未来方向
自制扫描器仍有局限,如:
- 服务指纹识别有限: 仅 HTTP 服务,指纹库简陋。
- 漏洞检测缺失: 去除了漏洞检测功能,需后续扩展。
- 性能待提升: 单线程扫描,速度较慢。
- 规避检测不足: 易被 WAF/IDS/IPS 拦截。
- 功能基础: 缺少 UDP 扫描等高级技术,功能模块简单。
未来方向: 扩展指纹库、增强识别算法、开发漏洞插件、优化性能、提升规避检测能力、完善报告等。
5. 总结与思考
自制 Python SYN 扫描器和服务指纹识别实践,深入理解了网络扫描核心原理。 网络扫描器是学习网络安全技术的平台。持续改进自制扫描器,能掌握更多技能。
6. 结语
希望本文能助您理解网络扫描技术。安全工具开发是持续学习过程,愿您不断进步,提升安全技能。
本次关于自制 Python SYN 扫描器与服务指纹识别的分享到此结束。欢迎交流探讨。