# ⚡ Mira Firmware Loader Công cụ desktop dùng để **scan, phát hiện và flash firmware hàng loạt** cho các thiết bị OpenWrt trong mạng LAN. > **Tech stack:** Python 3.9+ · PyQt6 · Paramiko/SCP · Scapy · Requests · PyInstaller > **Phiên bản:** `1.1.2` --- ## 📁 Cấu trúc dự án ```text Mira_Firmware_Loader/ ├── main.py # UI chính (PyQt6) ├── version.txt # Số phiên bản ứng dụng ├── requirements.txt # Danh sách dependencies ├── core/ │ ├── scanner.py # Quét thiết bị mạng đa lớp (Ping sweep + ARP + Scapy) │ ├── workers.py # ScanThread — chạy scanner trong background thread │ ├── api_flash.py # Flash firmware qua LuCI HTTP API │ ├── ssh_utils.py # SSH/SCP transport helpers dùng chung │ ├── ssh_new_flash.py # Luồng SSH cho chế độ Nạp Mới (Telnet → set passwd → SSH) │ ├── ssh_update_flash.py # Luồng SSH cho chế độ Update (SSH trực tiếp) │ ├── flash_new_worker.py # NewFlashThread — QThread điều phối Nạp Mới FW │ └── flash_update_worker.py # UpdateFlashThread — QThread điều phối Update FW ├── ui/ │ ├── components.py # Custom Qt Widgets (CollapsibleGroupBox) │ └── styles.py # Stylesheet toàn ứng dụng ├── utils/ │ ├── network.py # Helper IP / network (get_local_ip, get_default_network) │ └── system.py # Lấy thông tin máy, resource path cho PyInstaller ├── docs/ │ ├── api_flash_docs.md # Tài liệu kỹ thuật LuCI API flash │ ├── load_fw_ssh_docs.md # Tài liệu kỹ thuật SSH flash (cả 2 luồng) │ └── scanner_docs.md # Tài liệu kỹ thuật scanner ├── run.sh # Script khởi chạy (macOS/Linux) ├── run.bat # Script khởi chạy (Windows) └── build_windows.bat # Script đóng gói thành .exe (Windows, PyInstaller) ``` --- ## 🔧 Cài đặt & Chạy ### Yêu cầu - Python **3.9+** - Thư viện: `PyQt6`, `scapy`, `requests`, `paramiko`, `scp`, `pyinstaller` (để build) - _Windows:_ Cài [Npcap](https://npcap.com/) để Scapy có thể gửi ARP broadcast (không bắt buộc — có fallback) ### Khởi chạy nhanh **macOS / Linux:** ```bash ./run.sh ``` **Windows:** ```bat run.bat ``` > Script tự tạo `venv` và cài dependencies nếu chưa có. ### 📦 Build file chạy độc lập (.exe) cho Windows ```bat build_windows.bat ``` Output: `dist\Mira_Firmware_Loader.exe` — không cần cài Python trên máy đích. --- ## 🏗 Kiến trúc hệ thống ``` ┌──────────────────────────────────────────────────────────┐ │ main.py (UI) │ │ │ │ Machine Info │ Firmware Selector │ Network Scan │ │ ───────────────────────────────────────────────────── │ │ Device Table [ ] IP │ MAC │ Status │ │ ───────────────────────────────────────────────────── │ │ Flash Controls │ │ Flash Mode: [ New Flash | Update Firmware ] │ │ Method: [ API (LuCI) | SSH (paramiko) ] │ │ Concurrent devices: [SpinBox] │ │ [ ⚡ FLASH SELECTED DEVICES ] │ └────────────────────────┬─────────────────────────────────┘ │ ┌──────────────┼──────────────┐ │ │ ┌──────▼──────┐ ┌────────▼────────────────┐ │ scanner.py │ │ Flash Workers │ │ │ │ │ │ 1. Ping │ │ NewFlashThread │ │ Sweep │ │ ├─ method=api │ │ 2. arp -a │ │ │ └── api_flash.py │ │ 3. Scapy │ │ └─ method=ssh │ │ ARP │ │ └── ssh_new_flash │ └─────────────┘ │ │ │ UpdateFlashThread │ │ └─ ssh_update_flash.py │ └─────────────────────────┘ │ ┌──────────▼──────────┐ │ ssh_utils.py │ │ (Transport Layer) │ │ _create_ssh_client │ │ _upload_firmware │ │ _verify_firmware │ │ _sync_and_sysupgr │ └─────────────────────┘ ``` --- ## 🔄 Luồng hoạt động chi tiết ### 1. Quét mạng (Network Scan) `scanner.py` dùng chiến lược 3 lớp, đảm bảo phát hiện đầy đủ mà không cần quyền Root: | Giai đoạn | Mô tả | | -------------- | ----------------------------------------------------------------------------------------------------------------------------- | | **Ping Sweep** | Gửi ping song song (100 threads) đến toàn bộ host trong dải `/24` để đánh thức thiết bị và điền ARP cache | | **ARP Table** | Đọc `arp -a` bằng regex, hỗ trợ cả định dạng Windows (`cc-2d-...`) và macOS/Linux (`aa:bb:...`) | | **Scapy ARP** | Gửi ARP broadcast trực tiếp để lấp khoảng trống. Yêu cầu Npcap (Windows) hoặc root (Linux); tự động bỏ qua nếu không khả dụng | Kết quả được merge theo IP và sort tăng dần trước khi trả về UI. ### 2. Bảng thiết bị (Device Table) - Hiển thị cột: checkbox, IP, MAC, Status - Mặc định ẩn gateway và IP máy tính đang chạy (có thể bật "Show all") - Thiết bị đã flash trong session được đánh dấu "Already Flashed" và tự bỏ tick ### 3. Flash Firmware Có 2 chế độ và 2 method, tổng cộng 3 luồng thực thi khác nhau: #### Chế độ `New Flash` — dùng cho thiết bị vừa reset cứng | Method | Luồng | Mô tả | | -------------- | ------------------ | ------------------------------------------------------------------------------------------- | | **API (LuCI)** | `api_flash.py` | Đăng nhập LuCI → upload firmware → Proceed. Hỗ trợ Barrier Breaker 14.07 và OpenWrt mới hơn | | **SSH** | `ssh_new_flash.py` | Kết nối Telnet → đặt password mới → SSH → SCP upload → sysupgrade | **Luồng SSH – New Flash chi tiết:** 1. Telnet port 23 (thiết bị vừa reset, chưa có pass) 2. Đặt password `admin123a` qua lệnh `passwd` 3. SSH vào với password vừa đặt 4. SCP upload firmware lên `/tmp/` 5. Verify file tồn tại 6. `sync && sysupgrade -F -v -n` → thiết bị reboot (connection drop = DONE) #### Chế độ `Update Firmware` — dùng cho thiết bị đang chạy OpenWrt Luồng `ssh_update_flash.py`, SSH trực tiếp (không qua Telnet): 1. SSH kết nối với `root` / `admin123a` (fallback: `admin`) 2. SCP upload firmware lên `/tmp/` 3. Verify file tồn tại 4. `sync && sysupgrade -F -v -n` → thiết bị reboot > ⚠️ Update Mode hiển thị cảnh báo nếu IP thiết bị khác `192.168.11.102` và yêu cầu xác nhận. ### 4. Xử lý song song | Tham số | Mô tả | | ---------------------- | ------------------------------------------------------------------------ | | **Concurrent devices** | Số thiết bị flash đồng thời (`ThreadPoolExecutor`). `0` = không giới hạn | --- ## ⚙️ Cấu hình mặc định | Tham số | Giá trị mặc định | Mô tả | | ---------------------- | ------------------------------------ | --------------------------------- | | **Network** | Tự suy ra từ local IP (`x.x.x.0/24`) | Dải mạng để quét | | **Flash Mode** | `New Flash` | Nạp mới hoặc Update | | **Method** | `API (LuCI)` | Phương thức flash cho New Flash | | **SSH User** | `root` | Hardcoded, không hiển thị trên UI | | **SSH Password** | `admin123a` | Hardcoded, không hiển thị trên UI | | **Concurrent devices** | `10` | Số luồng flash song song | | **Show all** | Tắt | Ẩn gateway và IP máy host | --- ## 🔒 Lưu ý bảo mật & Quyền - **Scapy (chế độ sâu):** Cần Npcap (Windows) hoặc `sudo` (macOS/Linux). App vẫn hoạt động mà không cần quyền Admin nhờ fallback Ping Sweep + `arp -a`. - **CREATE_NO_WINDOW:** Khi gọi subprocess (`ping`, `arp`), ứng dụng dùng flag `CREATE_NO_WINDOW` trên Windows để ngăn cửa sổ console hiện ra. - **HTTP thuần:** Firmware được upload qua HTTP (không HTTPS). Chỉ dùng trong mạng LAN nội bộ, không nên dùng trên mạng mở. - **Credentials cố định:** SSH credentials (`root`/`admin123a`) được hardcode trong `flash_update_worker.py` và truyền từ `main.py`, không hiển thị trên UI.