121 lines
5.5 KiB
Markdown
121 lines
5.5 KiB
Markdown
# Tài liệu Kỹ thuật: Cơ chế Quét IP trên Mạng (Network Scanner)
|
||
|
||
## 1. Tổng quan
|
||
|
||
Thành phần quét IP trong `scanner.py` dò tìm và liệt kê tất cả thiết bị **đang thực sự online** trên một dải mạng (ví dụ: `192.168.1.0/24`), trả về danh sách chứa **IP** và **MAC Address** của từng thiết bị.
|
||
|
||
Scanner hoạt động theo cơ chế 2 bước (Ping trước → ARP sau):
|
||
1. **ICMP Ping Sweep:** Chỉ những IP có phản hồi ping mới được ghi nhận là online.
|
||
2. **ARP Lookup:** Ngay sau khi IP phản hồi ping, OS tự động cập nhật ARP cache cho IP đó. Scanner lập tức query ARP table để lấy MAC chính xác nhất.
|
||
|
||
> **Giải quyết vấn đề ARP cache cũ (stale entries):** Khác với phương pháp ARP scan truyền thống (`arp -a` liệt kê toàn mạng) thường dính thiết bị đã ngắt kết nối do bị cache, cách làm này **chỉ query ARP cho những IP vừa pass qua bài test ping**. Thiết bị offline sẽ rớt ở bước ping và không bao giờ được đưa vào danh sách.
|
||
|
||
---
|
||
|
||
## 2. Luồng hoạt động chính (Hàm `scan_network`)
|
||
|
||
```
|
||
scan_network(network)
|
||
│
|
||
├── stage_cb("ping") ← Thông báo UI bắt đầu quét
|
||
│
|
||
├── _ping_sweep(network) ← Ping đồng thời toàn bộ host
|
||
│ │
|
||
│ ├── _ping_one(ip) × N ← Mỗi host 1 thread
|
||
│ │
|
||
│ └── return [alive IPs]
|
||
│
|
||
├── stage_cb("mac") ← Thông báo UI bắt đầu lấy MAC
|
||
│
|
||
├── _get_mac_from_arp(ip) × K ← Tra MAC song song cho K IP alive
|
||
│
|
||
└── return [{"ip": ..., "mac": "AA:BB:CC:..."}, ...] ← Sorted by IP
|
||
```
|
||
|
||
**Bước 1 — Ping Sweep**
|
||
|
||
- Gọi `_ping_sweep(network)`: gửi ICMP Echo Request đồng thời tới **toàn bộ host** trong dải mạng.
|
||
- Chỉ các IP có `returncode == 0` (phản hồi thành công) mới được đưa vào danh sách `alive_ips`.
|
||
|
||
**Bước 2 — Địa chỉ MAC (ARP Lookup)**
|
||
|
||
- Từ danh sách `alive_ips`, tạo ThreadPoolExecutor (max_workers=32) để gọi `_get_mac_from_arp(ip)` đồng thời.
|
||
- Trích xuất MAC address bằng pattern matching chéo nền tảng.
|
||
|
||
**Bước 3 — Trả về kết quả**
|
||
|
||
- Danh sách sort tăng dần theo IP:
|
||
`[{"ip": "192.168.1.2", "mac": "AA:BB:CC:DD:EE:FF"}, ...]`
|
||
|
||
---
|
||
|
||
## 3. Phân tích chi tiết các hàm
|
||
|
||
### `_ping_one(ip, is_win)`
|
||
|
||
Ping một IP đơn lẻ, trả về `True` nếu host phản hồi, `False` nếu không.
|
||
|
||
Timeout tối ưu theo nền tảng:
|
||
|
||
| OS | Lệnh | Timeout wait | Timeout process |
|
||
| ------- | ------------------ | ------------ | --------------- |
|
||
| Windows | `ping -n 1 -w 300` | 300ms | 2s |
|
||
| macOS | `ping -c 1 -W 300` | 300ms | 2s |
|
||
| Linux | `ping -c 1 -W 1` | 1s | 2s |
|
||
|
||
> macOS và Linux dùng cùng flag `-W` nhưng đơn vị khác nhau (macOS: ms, Linux: giây) — được xử lý tách biệt theo `sys.platform`.
|
||
|
||
Windows sử dụng `CREATE_NO_WINDOW` flag để tránh mở cửa sổ console cho mỗi subprocess.
|
||
|
||
### `_ping_sweep(network, progress_cb)`
|
||
|
||
- Tạo `ThreadPoolExecutor(max_workers=len(hosts))` — **toàn bộ host ping đồng thời**, không batching.
|
||
- Giới hạn an toàn: chỉ chạy với subnet `/24` trở xuống (`num_addresses <= 256`).
|
||
- Trả về danh sách IP (string) đã phản hồi thành công.
|
||
- Gọi `progress_cb(done, total)` sau mỗi ping để UI cập nhật thanh tiến độ.
|
||
|
||
### `_get_mac_from_arp(ip)`
|
||
|
||
- Gọi lệnh hệ điều hành để đọc ARP cache cho IP cụ thể:
|
||
- **Windows**: `arp -a <ip>`
|
||
- **macOS / Linux**: `arp -n <ip>`
|
||
- Sử dụng Regex để parse MAC address và trả về dưới format chuẩn `AA:BB:CC:DD:EE:FF`.
|
||
- Nếu không tìm thấy, fallback thành `"N/A"`.
|
||
|
||
### `scan_network(network, progress_cb, stage_cb)`
|
||
|
||
- Entry point chính.
|
||
- `stage_cb("ping")` và `stage_cb("mac")` thông báo UI giai đoạn hiện tại.
|
||
- Trả về `list[dict]` với format `{"ip": str, "mac": str}`, sorted theo IP tăng dần.
|
||
|
||
---
|
||
|
||
## 4. Hiệu năng
|
||
|
||
| Thông số | Giá trị |
|
||
| --------------------------- | ------------------------------------ |
|
||
| Ping workers | `len(hosts)` (~254, tất cả cùng lúc) |
|
||
| Ping timeout — Windows | 300ms |
|
||
| Ping timeout — macOS | 300ms |
|
||
| Ping timeout — Linux | 1s |
|
||
| Process timeout | 2s |
|
||
| **Tổng thời gian scan /24** | **~1–2s** |
|
||
|
||
---
|
||
|
||
## 5. Ưu & Nhược điểm
|
||
|
||
**Ưu điểm:**
|
||
|
||
- **Có đầy đủ IP và MAC**, rất hữu ích cho log và tracking lịch sử thiết bị nạp FW.
|
||
- **Không bị dính ARP cache cũ**: Do chỉ lấy MAC của các IP vừa ping thành công.
|
||
- Không cần quyền Admin/Root.
|
||
- Không phụ thuộc thư viện bên ngoài (không cần Npcap / Scapy phức tạp).
|
||
- Tương thích đa nền tảng (Windows/macOS/Linux).
|
||
- Cực nhanh nhờ cơ chế full-parallel.
|
||
|
||
**Nhược điểm:**
|
||
|
||
- Thiết bị cố tình chặn gói tin ICMP (tắt ping) sẽ không bị phát hiện.
|
||
- Ping 254 thiết bị cùng lúc bằng tiến trình con (`subprocess`) trên Windows có overhead hệ thống cao hơn Unix.
|