rayyme6/python-port-scanner
GitHub: rayyme6/python-port-scanner
一个支持多线程 Connect 扫描与 Scapy SYN 扫描的轻量级 Python 端口扫描工具,具备服务识别与报告导出功能。
Stars: 1 | Forks: 0
# Python 端口扫描器
一个使用 Python 编写的命令行 TCP 端口扫描器,用于学习网络编程、进行授权的安全评估以及排查网络服务问题。
该扫描器支持多线程 TCP connect 模式,以及使用 Scapy 进行数据包级别的半开 SYN 扫描。它可以扫描自定义端口范围,执行基本的服务和 banner 识别,显示扫描进度,并将结果导出到文本文件。
## 功能
* 多线程 TCP connect 扫描
* 使用 Scapy 进行半开 TCP SYN 扫描
* 支持主机名和 IPv4 地址
* 支持单个端口、端口范围和混合端口规范
* 基本服务识别
* Banner 抓取
* HTTP 服务探测
* 可配置的超时时间
* 可配置的 connect 扫描线程数
* 实时进度显示
* 纯文本报告导出
* 检测完全无响应或不可达的目标
* 优雅的错误处理
* TCP connect 扫描无需外部依赖
## 扫描模式
| 模式 | 标志 | 库 | 权限 | 描述 |
| ---------------- | ------- | --------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| TCP Connect 扫描 | 默认 | Python `socket` | 无 | 完成完整的 TCP 三次握手。它是多线程的、可靠的,并且在无需管理权限的情况下即可运行。 |
| SYN 扫描 | `--syn` | Scapy | Root / Administrator | 发送 TCP SYN 数据包并检查回复,而无需完成握手。目前的实现是按顺序扫描端口,可能比多线程 connect 扫描器慢。 |
### TCP Connect 扫描
默认扫描器使用 Python 的 socket 库尝试完整的 TCP 连接。
当连接成功时,该端口被视为开放:
```
Scanner → SYN
Target → SYN-ACK
Scanner → ACK
```
由于完成了完整的连接,目标服务的连接日志中可能会记录此尝试。
### SYN 扫描
SYN 扫描器使用 Scapy 创建和发送原始 TCP 数据包。
典型的响应解释如下:
```
SYN-ACK response → Open
RST response → Closed
No response → Filtered, dropped, or unreachable
ICMP response → Network device or firewall responded
```
当端口返回 SYN-ACK 时,扫描器会立即发送一个 TCP 重置(RST)数据包:
```
Scanner → SYN
Target → SYN-ACK
Scanner → RST
```
这可以防止正常的 TCP 握手被完成。
## 要求
* Python 3.8 或更高版本
* 进行 SYN 扫描需使用 Linux 或 macOS
* 进行 SYN 扫描需使用 Scapy
* 发送原始 SYN 数据包需要 Root 权限
标准的 TCP connect 扫描器仅使用 Python 的标准库。
## 安装
克隆仓库:
```
git clone https://github.com/YOUR_USERNAME/python-port-scanner.git
cd python-port-scanner
```
创建 Python 虚拟环境:
```
python3 -m venv .venv
```
激活环境:
```
source .venv/bin/activate
```
安装项目依赖:
```
pip install -r requirements.txt
```
`requirements.txt` 文件会安装 Scapy,该库仅在 SYN 扫描时需要。
## 用法
基本语法:
```
python3 port_scanner.py TARGET [OPTIONS]
```
显示完整的帮助菜单:
```
python3 port_scanner.py --help
```
## 示例
### 扫描 TCP 端口 1 到 1024
```
python3 port_scanner.py 192.168.1.10
```
默认的端口范围是 `1-1024`。
这意味着扫描器会检查从 1 到 1024 的每一个 TCP 端口。它不会使用 Nmap 列出的前 1024 个最常见端口。
### 扫描特定端口
```
python3 port_scanner.py 192.168.1.10 -p 22,80,443
```
### 扫描端口范围
```
python3 port_scanner.py 192.168.1.10 -p 1-5000
```
### 扫描混合端口和范围
```
python3 port_scanner.py 192.168.1.10 -p 22,80,443,8000-8100
```
### 扫描主机名
```
python3 port_scanner.py example.com -p 80,443
```
### 更改超时时间
```
python3 port_scanner.py 192.168.1.10 -p 1-1024 --timeout 0.5
```
较短的超时时间会使扫描更快,但可能会漏掉缓慢的响应。
较长的超时时间在缓慢的网络上更可靠,但可能会显著增加扫描持续时间。
### 更改线程数
```
python3 port_scanner.py 192.168.1.10 -p 1-5000 --threads 100
```
线程设置仅适用于 TCP connect 扫描。
### 执行 SYN 扫描
使用虚拟环境时:
```
sudo .venv/bin/python port_scanner.py 192.168.1.10 -p 1-1024 --syn
```
创建原始数据包通常需要 root 权限。
### 执行不带 banner 抓取的 SYN 扫描
```
sudo .venv/bin/python port_scanner.py 192.168.1.10 -p 1-1024 --syn --no-banner
```
这将执行半开端口发现,而不会为了识别服务而建立额外的完整 TCP 连接。
### 在 connect 模式下跳过 banner 抓取
```
python3 port_scanner.py 192.168.1.10 -p 1-65535 --no-banner
```
当仅需要开放的端口号时,这可以使扫描更快。
### 将报告保存到文件
```
python3 port_scanner.py 192.168.1.10 -p 1-1024 -o report.txt
```
输出文件包含:
* 目标主机名或 IP 地址
* 解析后的 IP 地址
* 扫描类型
* 日期和时间
* 扫描持续时间
* 开放端口
* 服务标签
* 抓取到的 banner
## 命令行选项
| 参数 | 用途 |
| ----------------- | ---------------------------------------------------------- |
| `target` | 目标 IPv4 地址或主机名 |
| `-p`, `--ports` | 要扫描的端口,例如 `22,80,443`、`1-1024` 或混合输入 |
| `-t`, `--timeout` | 每个端口的超时时间(秒) |
| `--threads` | TCP connect 扫描的最大并发线程数 |
| `--syn` | 使用 Scapy SYN 扫描器 |
| `--no-banner` | 跳过服务和 banner 识别 |
| `-o`, `--output` | 将扫描报告写入文本文件 |
| `-h`, `--help` | 显示帮助菜单 |
默认值:
```
Ports: 1-1024
Timeout: 1.0 second
Threads: 200
Mode: TCP connect scan
```
## 输出示例
```
Target: 192.168.100.1 (192.168.100.1)
Ports : 1024
Mode : TCP connect scan (socket)
scanned 1024/1024 ports.
==============================================================
Scan report for 192.168.100.1 (192.168.100.1)
Scan type : TCP connect scan (socket)
Duration : 5.44s
==============================================================
PORT STATE SERVICE BANNER
------ ----- ------- ------------------------------
23 open Telnet
53 open DNS
80 open HTTP HTTP/1.1 404 Not Found
3 open port(s) found.
```
在此示例中:
* TCP 端口 23 接受了连接。
* TCP 端口 53 接受了连接。
* TCP 端口 80 接受了连接并返回了 HTTP 响应。
* 没有 banner 的端口的服务名称可能基于其常规的端口分配。
## 工作原理
程序遵循以下一般流程:
```
Read command-line arguments
↓
Resolve the target to an IPv4 address
↓
Parse and validate the port specification
↓
Select TCP connect or SYN scanning
↓
Probe every requested port
↓
Collect open ports
↓
Attempt service and banner identification
↓
Print the results
↓
Optionally save a report
```
## 端口解析
扫描器接受多种端口格式。
### 单个端口
```
80
```
### 多个端口
```
22,80,443
```
### 端口范围
```
1-1024
```
### 混合输入
```
22,80,443,8000-8100
```
重复的端口会自动移除,最终列表会进行排序。
有效的端口号范围是 1 到 65535。
无效的示例包括:
```
0
65536
100-50
abc
```
## TCP Connect 扫描
TCP connect 扫描器使用 `socket.connect_ex()` 测试每个端口。
可能的结果包括:
### 开放
连接成功,并且 `connect_ex()` 返回 `0`。
```
is_open = True
got_reply = True
```
### 关闭
目标主动拒绝连接。
```
is_open = False
got_reply = True
```
这通常意味着主机可达,但没有应用程序在该端口上监听。
### 无有效响应
连接尝试超时或被静默丢弃。
```
is_open = False
got_reply = False
```
可能的原因包括:
* 防火墙静默丢弃了探测包
* 主机离线
* 目标地址不正确
* 存在路由问题
* 超时时间过短
* 发生丢包
connect 扫描器使用线程池,以便并发测试多个端口。
## SYN 扫描
SYN 扫描器使用 Scapy 创建一个包含 IP 层和 TCP 层的数据包:
```
IP(dst=target_ip) / TCP(
sport=source_port,
dport=destination_port,
flags="S"
)
```
该数据包包含:
* 目标 IPv4 地址
* 随机的高位源端口
* 被测试的目标端口
* SYN 标志
* 随机 TCP 序列号
Scapy 发送数据包并等待响应。
### SYN-ACK 响应
SYN-ACK 通常表示端口开放。
扫描器发送重置数据包以终止半开连接。
### RST 响应
重置通常表示端口已关闭。
### 无响应
缺少响应可能意味着被过滤、丢包、目标不可达或主机离线。
### ICMP 响应
路由器、防火墙或目标系统可能会返回 ICMP 错误。
当前的 SYN 扫描器一次测试一个端口。未来版本可能会使用 Scapy 的批量发送功能来提高性能。
## 服务和 banner 识别
发现开放端口后,扫描器会尝试进行基本的服务识别。
流程如下:
1. 根据常规端口号分配一个备选服务名称。
2. 打开到该端口的 TCP 连接。
3. 简短等待服务发送 banner。
4. 如果未收到任何内容,则发送通用的 HTTP `HEAD` 请求。
5. 检查响应中是否有可识别的协议。
某些服务会立即发送识别性的 banner。
SSH banner 示例:
```
SSH-2.0-OpenSSH_9.6
```
FTP banner 示例:
```
220 FTP Server Ready
```
SMTP banner 示例:
```
220 mail.example.com ESMTP
```
对于静默的服务,扫描器会发送:
```
HEAD / HTTP/1.0
Host: TARGET_IP
```
如果响应以 `HTTP/` 开头,则该服务被识别为 HTTP。
示例:
```
HTTP/1.1 404 Not Found
```
`404 Not Found` 响应依然是 HTTP 服务器接受并处理了请求的证据。这并不代表该端口已关闭。
## 服务识别准确性
仅基于端口号的服务名称是尽力而为的标签,并非最终确定性的识别。
例如,开放的 TCP 端口 23 会被标记为 `Telnet`,因为端口 23 通常与 Telnet 关联。然而,另一个应用程序也可能被配置为监听该端口。
当扫描器收到以下信息时,会提供更强有力的识别:
* 可识别的 banner
* SSH 协议字符串
* 有效的 HTTP 响应
* HTTP `Server` 标头
扫描器不会执行完整的服务版本指纹识别,例如:
```
nmap -sV
```
## 了解端口状态
### 开放
程序正在该端口上接受 TCP 连接。
### 关闭
主机有响应,但没有程序在该端口上接受连接。
### 被过滤
防火墙或网络设备可能正在阻止或静默丢弃探测包。
### 不可达或无响应
目标可能离线、地址不正确、因路由问题被隔离或受过滤保护。
当前的最终报告仅列出开放端口。
## 完全无响应的目标
两种扫描引擎都会跟踪目标是否返回了任何响应。
开放端口的响应和明确的拒绝都证实了有设备进行了回复。
如果每个探测都超时且没有回复,扫描器会打印警告,而不是确信地报告该主机没有开放端口。
完全无响应的结果可能意味着:
* 目标离线
* 目标更改了 IP 地址
* 防火墙正在静默丢弃数据包
* 启用了无线客户端隔离
* 设备位于不同的 VLAN 上
* 扫描器与目标之间无法进行路由
* 超时时间太短
有用的故障排除命令包括:
```
ping -c 4 192.168.1.10
```
```
ip route
```
```
ip neigh
```
您还可以检查路由器的 DHCP 客户端或已连接设备列表。
## 虚拟环境和 `sudo`
建议在虚拟环境中安装 Scapy:
```
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
运行此命令:
```
sudo python3 port_scanner.py TARGET --syn
```
可能会使用 root 用户的 Python 环境,而不是您的虚拟环境。因此,Root 可能无法找到 Scapy。
请使用虚拟环境内的 Python 可执行文件:
```
sudo .venv/bin/python port_scanner.py TARGET --syn
```
这赋予了脚本原始套接字权限,同时仍使用安装在 `.venv` 中的包。
避免使用以下命令全局安装包:
```
sudo pip install scapy
```
因为这可能会干扰操作系统管理的 Python 环境。
## 项目结构
```
python-port-scanner/
├── port_scanner.py
├── requirements.txt
└── README.md
```
### `port_scanner.py`
包含:
* 命令行界面
* 端口解析
* 主机名解析
* TCP connect 扫描器
* SYN 扫描器
* banner 识别
* 结果格式化
* 文本报告生成
### `requirements.txt`
包含 SYN 扫描所需的 Scapy 依赖。
### `README.md`
包含安装说明、用法示例、技术解释、限制和负责任的使用指南。
## 实际应用
本项目可在授权环境中用于:
* 网络故障排除
* 验证服务是否可达
* 检查服务器暴露情况
* 测试防火墙配置
* 审计家庭网络
* 验证云服务器安全组
* 部署后服务验证
* 网络安全实验室练习
* 学习 socket 编程
* 学习 TCP 数据包结构
* 了解 TCP 握手
* 基本的资产和服务发现
* 防御性安全评估
它是一个学习和审计工具,而不是一个漏洞利用框架。
## 限制
当前的限制包括:
* 仅支持 TCP 扫描
* 不支持 UDP 扫描
* 仅支持 IPv4
* 无操作系统指纹识别
* 无漏洞检测
* 无漏洞利用功能
* 基于基本 banner 的服务识别
* 无完整的服务版本指纹识别
* SYN 探测当前按顺序发送
* 最终报告仅列出开放端口
* 无 JSON 或 CSV 输出
* 无多主机或子网扫描
* 扫描结果之间无历史比较
* 向静默的开放服务发送通用 HTTP 探测
* Banner 抓取错误被有意抑制
## 未来可能的改进
潜在的改进包括:
* 并发或批量 SYN 扫描
* UDP 扫描
* IPv6 支持
* 多主机扫描
* CIDR 子网支持
* 报告已关闭和被过滤的端口
* 特定于协议的服务探测
* 服务版本指纹识别
* JSON 报告导出
* CSV报告导出
* 结构化日志记录
* 可配置的重试次数
* 速率限制
* 历史扫描比较
* 自动化测试
* 更好的异常日志记录
* 可选的彩色终端输出
* 操作系统指纹识别
* 与漏洞数据库集成
## 学习成果
构建该项目展示了对以下知识的掌握:
* Python socket 编程
* TCP/IP 网络
* TCP 三次握手
* SYN、ACK、RST 和 ICMP 响应
* 原始数据包构建
* Scapy
* 多线程
* 线程池
* 超时
* 命令行应用程序设计
* 参数解析
* DNS 解析
* 错误处理
* Banner 抓取
* 服务识别
* 报告生成
* 防御性网络侦察
## 负责任的使用
仅扫描您拥有或获得明确测试授权的系统和网络。
授权目标的示例包括:
* 您自己的计算机
* 您自己的路由器
* 您的个人家庭实验室
* 大学网络安全实验室
* 拥有书面授权的客户系统
* 明确允许测试的专用公共扫描目标
未经授权的扫描可能违反:
* 当地法律
* 计算机滥用法
* 合同
* 可接受使用政策
* 互联网服务提供商政策
* 工作场所或大学安全规则
作者对滥用本软件不承担任何责任。
本项目仅用于教育、授权的安全测试和网络故障排除。
标签:Banner抓取, Python, Scapy, 插件系统, 数据泄露防护, 数据统计, 无后门, 端口扫描, 网络探测, 逆向工具