1. 为什么我们需要自己写端口扫描器端口扫描是网络安全领域最基础也最重要的技能之一。作为一名渗透测试工程师我几乎每天都会用到端口扫描工具。市面上的确有很多成熟的端口扫描器比如Nmap、Masscan等但它们要么功能过于复杂要么在某些特定场景下不够灵活。自己动手写一个端口扫描器有几个明显优势完全可控你可以根据具体需求定制扫描策略学习价值深入理解网络通信和端口扫描原理轻量化针对特定场景可以做得比通用工具更高效我最近用Python实现了一个轻量级端口扫描器代码不到200行但已经具备了基础扫描功能并且支持一些实用特性。下面分享我的实现思路和关键代码。2. 端口扫描的核心原理2.1 TCP三次握手与端口状态端口扫描的本质是尝试与目标主机的特定端口建立TCP连接。根据RFC 793定义的TCP协议一个端口可能有以下几种状态开放(Open)服务正在监听该端口会完成三次握手关闭(Closed)主机响应但无服务监听(RST响应)过滤(Filtered)无响应(可能被防火墙拦截)未过滤(Unfiltered)能收到响应但不确定是否开放最基础的扫描方式就是尝试与目标端口建立完整的TCP连接全连接扫描但这种扫描方式会在目标主机留下大量日志记录。2.2 常见扫描技术对比扫描类型原理优点缺点检测难度TCP全连接完成三次握手结果准确速度慢易被发现高SYN扫描只发SYN包速度快需要root权限中FIN扫描发送FIN包隐蔽性高结果不够准确低UDP扫描发送UDP包可检测UDP服务结果不可靠中Python的socket库默认只能实现全连接扫描要实现更高级的扫描方式需要借助scapy等底层网络库。3. Python实现基础扫描器3.1 基础扫描功能实现我们先实现一个最简单的全连接端口扫描器import socket from concurrent.futures import ThreadPoolExecutor def scan_port(host, port): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(1) result s.connect_ex((host, port)) if result 0: print(fPort {port} is open) return port except Exception as e: pass return None def port_scanner(host, ports): open_ports [] with ThreadPoolExecutor(max_workers100) as executor: results executor.map(lambda p: scan_port(host, p), ports) for port in results: if port: open_ports.append(port) return open_ports if __name__ __main__: target example.com port_range range(1, 1025) print(fScanning {target}...) open_ports port_scanner(target, port_range) print(fOpen ports: {open_ports})这个基础版本已经可以工作但有几个明显问题扫描速度较慢即使使用多线程容易被防火墙检测到没有实现超时控制结果输出过于简单3.2 性能优化技巧提高扫描速度的几个关键点动态调整超时时间对响应快的端口使用更短的超时def dynamic_timeout(port): # 常见服务端口使用更短超时 common_ports {80:0.5, 443:0.5, 22:0.8, 21:0.8} return common_ports.get(port, 1.5)端口扫描顺序优化先扫描常见服务端口common_ports [80, 443, 22, 21, 25, 3389, 3306, 53] other_ports [p for p in range(1,1025) if p not in common_ports] ports_to_scan common_ports other_ports智能线程池管理根据网络延迟动态调整线程数from threading import Semaphore class DynamicThreadPool: def __init__(self, max_workers): self.semaphore Semaphore(max_workers) def submit(self, func, *args): self.semaphore.acquire() try: result func(*args) return result finally: self.semaphore.release()4. 进阶功能实现4.1 服务指纹识别检测到开放端口后我们可以进一步识别运行的服务def service_detection(host, port): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(1) s.connect((host, port)) s.send(bGET / HTTP/1.1\r\n\r\n) banner s.recv(1024).decode().strip() if HTTP in banner: return HTTP Service elif SSH in banner: return SSH Service # 其他服务识别规则... else: return Unknown Service except: return Unable to detect4.2 结果可视化输出将扫描结果生成可视化报告from prettytable import PrettyTable def generate_report(host, open_ports, services): table PrettyTable() table.field_names [Port, Status, Service, Banner] for port in open_ports: service services.get(port, {}).get(service, Unknown) banner services.get(port, {}).get(banner, )[:50] table.add_row([port, Open, service, banner]) print(f\nScan Report for {host}) print(table) print(f\nTotal open ports: {len(open_ports)})5. 实际应用中的注意事项5.1 合法性与道德考量端口扫描是一把双刃剑使用时必须注意只扫描你有权限测试的目标避免对关键基础设施进行扫描控制扫描频率避免造成网络拥塞商业使用前咨询法律顾问提示在测试环境中可以使用localhost或自己搭建的靶机进行练习。5.2 规避检测的技巧如果需要在真实环境中使用可以考虑以下方法降低被发现的风险随机化扫描顺序和时间间隔使用代理或分布式扫描节点限制扫描速率混合使用多种扫描技术import random import time def stealth_scan(host, ports): random.shuffle(ports) for port in ports: scan_port(host, port) time.sleep(random.uniform(0.1, 1.5))5.3 常见问题排查连接超时问题检查目标主机是否在线确认网络连接正常适当增加超时时间权限不足问题某些扫描类型需要root权限Linux/Mac下使用sudo运行Windows下以管理员身份运行防火墙干扰尝试不同的扫描技术调整扫描速率使用分散的源IP地址6. 扩展思路与进阶方向这个基础扫描器还可以进一步扩展集成更多扫描技术使用scapy实现SYN扫描添加UDP端口扫描功能实现操作系统指纹识别分布式扫描架构使用Redis作为任务队列多台机器协同扫描结果集中存储分析自动化漏洞检测常见服务漏洞检测弱口令爆破CVE漏洞匹配Web界面Flask/Django开发管理界面可视化扫描结果历史记录查询# 使用scapy实现SYN扫描示例 from scapy.all import * def syn_scan(host, port): ans sr1(IP(dsthost)/TCP(dportport,flagsS), timeout1, verbose0) if ans and ans.haslayer(TCP): if ans.getlayer(TCP).flags 0x12: # SYN-ACK return True return False实现一个完整的端口扫描器需要考虑的细节很多但核心原理并不复杂。我建议先从基础版本开始然后逐步添加你需要的功能。在实际项目中我会根据目标环境的特点调整扫描策略这也是自己编写扫描器的优势所在。
阅读完成 · 觉得有帮助?