havl-code/my-network-scanner
GitHub: havl-code/my-network-scanner
一个基于 Python 和 Scapy 的轻量级命令行网络扫描器,通过 ARP 发现、SYN 扫描和 banner 抓取帮助用户学习底层网络侦察原理。
Stars: 0 | Forks: 0
# my-network-scanner
[](https://www.python.org/)
[](LICENSE)
一个轻量级的 Python ARP + SYN 扫描器,用于发现本地网络上的存活主机,检查一系列常见的 TCP 端口,尽可能抓取服务 banner,并根据 TTL 粗略猜测每个主机的操作系统。其构建目的是为了学习基础的网络侦察工具在底层是如何工作的。
```
[+] ARP scanning 192.168.1.0/24...
[+] Host found: 192.168.1.1 | d8:9e:f3:11:22:33
[+] SYN scanning 192.168.1.1...
[+] Results saved to results.json
```
## 为什么
像 `nmap` 这样的工具可以完成上述所有工作,甚至更多,但使用它们并不能教会你太多关于*如何*实现的知识。这个项目恰恰相反:它是一个小巧易读的脚本,只对单个子网进行一次扫描,因此每个部分(ARP 发现、SYN 扫描、banner 抓取、基于 TTL 的操作系统猜测)从头到尾都很容易阅读。
## 设计决策
- **先进行 ARP,然后是 TCP。** 快速的 ARP 扫描可以找出子网上哪些主机真正存活,从而避免将时间浪费在扫描没人使用的地址端口上。
- **通过 scapy 进行原始 SYN 扫描。** 使用手工制作的 SYN 数据包而非完整的 TCP 连接来探测端口,并且在发现每个开放端口后发送 RST,这样被扫描的主机就不会留下半开连接。
- **banner 抓取是对每个端口尝试一次尽力而为的连接。** 如果服务在超时时间内没有响应,则只记录为没有 banner,而不进行重试,以保持扫描长度的可预测性。
- **操作系统猜测仅基于 TTL,且只是一种猜测。** TTL 范围(`<=64` → Linux/Unix,`<=128` → Windows,`<=255` → 网络设备)是一种粗略的启发式方法,而不是指纹识别。许多主机无法被准确地匹配。
- **并发主机扫描。** 一旦知道了存活主机,每台主机就会在自己的线程中进行扫描(一次最多 10 个),这样面对包含大量主机的子网时,就不会一个接一个地顺序扫描。
- **限制在 /24 及以下。** 超过 256 个主机的任何请求都会在最初被拒绝,而不是允许其无限期运行;如果你只关心一台设备,请改为扫描单个 IP。
- **可安全中断。** Ctrl+C 会触发一个 signal handler,它将到目前为止找到的所有内容保存到 `results.json` 中,而不是丢失整个扫描结果。
## 环境要求
- Python 3.7+
- Root/管理员权限,或者被授予了 raw-socket 权限的 Python 二进制文件(参见已知限制)
- [`scapy`](https://pypi.org/project/scapy/),唯一的第三方依赖;其他所有内容(`socket`、`json`、`datetime`、`signal`、`ipaddress`)均为 Python 标准库
## 设置
```
git clone https://github.com/havl-code/my-network-scanner.git
cd my-network-scanner
python -m venv .venv
source .venv/bin/activate
pip install scapy
```
## 用法
访问原始数据包需要提升权限。由于 `sudo` 会将 `PATH` 重置为系统 Python,如果在已激活的 venv 中运行 `sudo python scanner.py`,将会报出 `ModuleNotFoundError: No module named 'scapy'` 错误,即使已经安装了该包,因为 sudo 看不到你的 venv。请使用以下方法之一:
```
# 直接将 sudo 指向 venv 的 python
sudo .venv/bin/python scanner.py
# 或者,完全不使用 sudo 以普通用户身份运行(一次性设置):
sudo setcap cap_net_raw,cap_net_admin=eip .venv/bin/python3
python scanner.py
```
系统会提示你输入网络:
```
Enter network (e.g. 192.168.1.0/24 or single IP): 192.168.1.0/24
```
## 输出
结果将保存到 `results.json` 中:
```
{
"network": "192.168.1.0/24",
"scanned_at": "2025-06-02T13:00:00",
"devices": [
{
"ip": "192.168.1.1",
"mac": "d8:9e:f3:11:22:33",
"os": "Linux/Unix",
"open_ports": [22, 80],
"banners": {
"22": "SSH-2.0-OpenSSH_7.6",
"80": "Apache HTTPD"
}
}
]
}
```
如果某台主机在任何开放端口上都没有可达的 banner,则其 `banners` 对象将简单地保持为空。
## 已知限制
- **`sudo` 和 venv 默认下无法兼容。** 请参阅用法下的说明:除非你明确指定,否则 `sudo` 使用的是系统 python,而不是你 venv 中的 python。
- **`setcap` 会永久赋予**你应用它的任何 python 二进制文件 raw-socket 权限。这很方便,但请仅对你信任和控制的 python(例如你项目的 venv 解释器)执行此操作,而不要对系统全局的 python 执行此操作。
- **基于 TTL 的操作系统检测是近似的。** 这是一种低成本的启发式方法,并不是真正的指纹识别,并且可能会错误识别位于某些防火墙/NAT 后面的主机。
- **限制最多 256 个主机(/24)。** 如果需要扫描更大的范围,请扫描单个 IP,或者在不同的较小范围内多次运行。
- **没有针对丢弃数据包的重试逻辑。** 在不稳定的网络上,丢失的 SYN/ACK 会被识别为已关闭的端口;系统不会重新探测。
## 学习目标
- ARP 发现和本地子网枚举
- TCP SYN 扫描和端口指纹识别
- 使用 raw sockets 进行基础的 banner 抓取
- 使用 TTL 进行粗略的操作系统估算
- 处理中断并安全地持久化部分结果
- 使用线程池进行并发扫描
## 免责声明
仅供**教育**和**授权**使用。请勿扫描你不拥有或未获得明确测试权限的网络或设备。未经授权的扫描是非法且不道德的。
## Licence
基于 MIT Licence 发布,请参阅 [LICENSE](LICENSE)。
标签:ARP发现, Python, Scapy, SYN扫描, 域名解析, 插件系统, 无后门, 网络安全, 网络扫描器, 逆向工具, 隐私保护