SS-Sauron/Heimdall-Wake-On-Lan-ESP32

GitHub: SS-Sauron/Heimdall-Wake-On-Lan-ESP32

一款 ESP32 MQTT 远程电源管理固件,通过 Wake-on-LAN 唤醒局域网设备并提供 TOTP 认证与 OPSEC 隐蔽功能。

Stars: 2 | Forks: 0

Heimdall # 👁 HEIMDALL **网络守护者** *时刻注视。永不沉睡。随时唤醒沉睡之物。*
[![Version](https://img.shields.io/badge/version-v1.0.0-blueviolet?style=for-the-badge)](https://github.com/SS-Sauron/Heimdall/releases) [![CI](https://img.shields.io/github/actions/workflow/status/SS-Sauron/Heimdall/build.yml?style=for-the-badge)](https://github.com/SS-Sauron/Heimdall/actions/workflows/build.yml) [![Web Flasher](https://img.shields.io/badge/Web%20Flasher-Live-brightgreen?style=for-the-badge&logo=googlechrome&logoColor=white)](https://ss-sauron.github.io/Heimdall-Wake-On-Lan-ESP32/) [![ESP-IDF](https://img.shields.io/badge/ESP--IDF-v6.0.1-E7352C?style=for-the-badge&logo=espressif&logoColor=white)](https://idf.espressif.com/) [![Platform](https://img.shields.io/badge/ESP32-classic-E7352C?style=for-the-badge&logo=espressif&logoColor=white)](https://www.espressif.com/) [![License](https://img.shields.io/badge/license-Apache--2.0-brightgreen?style=for-the-badge)](LICENSE) [![MQTT](https://img.shields.io/badge/MQTT-TLS%208883-660066?style=for-the-badge&logo=mqtt&logoColor=white)](https://mqtt.org/)
一款紧凑的 **ESP32** 固件,它在你的 MQTT broker 上默默值守,拦截唤醒命令,并向本地网络中沉睡的机器广播 **Wake-on-LAN magic packet**。 只需通过内置的 captive portal 配置一次——然后就可以忘记它的存在。直到你需要它为止。
## ✦ 功能简介 ``` (OTA Updates) [ HTTP/OTA Server ] ◄── TLS ── [ Heimdall / ESP32 ] ──── UDP ────► [ Target PC ] ▲ │ ▲ TLS └──────────── ICMP ────────────┘ │ (Ping Feedback) │ │ │ [ MQTT Broker ] ─────────────────┴───────────────── TLS ────────────┘ (Sleep Listener) ``` Heimdall 是一款专为 ESP32 打造的完整远程电源管理与网络安全工具。开箱即用,它提供: - **Wake-on-LAN**:向任何本地子网广播 magic packet 以唤醒沉睡的 PC。 - **远程 PC 休眠**:包含一个配套的监听脚本,可通过 MQTT 安全地让你的 PC 重新进入休眠状态。 - **GPIO 控制**:允许你远程切换连接到 ESP32 的物理继电器或指示灯。 - **隐蔽性与 OPSEC**:可配置为在完全不可见的状态下运行,包含 MAC 欺骗、虚假主机名、通过 HMAC 派生的 MQTT topic 以及 TOTP 身份验证,以防止未经授权的网络控制。 ## ✦ 功能特性 | 图标 | 功能特性 | |---|---| | 🌐 | **Captive Portal 配置** — 连接,配置,完成。支持在 iOS、Android 和 Windows 上进行完整的 DNS 重定向 | | 🔐 | **三种构建预设** — STANDARD(完整版)、HARDENED(OPSEC + 便利性)、HARDENED STEALTH(最小足迹) | | 🔑 | **TOTP 身份验证** — 符合 RFC 6238 标准。每个唤醒命令都需要有效的一次性代码(仅限 HARDENED 版本) | | 🕵️ | **身份混淆** — MAC 欺骗、通用设备主机名、通过 HMAC 派生的不透明 MQTT topic(仅限 HARDENED 版本) | | 📡 | **动态广播** — 在 runtime 计算正确的广播地址。适用于任何子网 | | 🔄 | **支持 OTA** — 双槽分区表,失败时自动回滚 | | 🛡️ | **自愈式 WiFi** — 区分错误密码与临时中断。在路由器重启期间绝不会弹回到设置模式 | | 🏷️ | **自定义主机名** — 设置你自己的设备名称,并与 DHCP、mDNS 和 NetBIOS 同步 | | 🏓 | **Ping 反馈** — 可选通过 ICMP echo 请求确认 PC 唤醒状态 | | 🔌 | **GPIO 输出控制** — 远程切换特定的 ESP32 引脚(例如用于物理继电器)。在 HARDENED 构建版本中受 TOTP 保护 | | 🔒 | **SecureOn 密码** — 唤醒需要将 6 字节 SecureOn 密码附加到 magic packet 的现代主板 | | 💤 | **PC 休眠伴侣** — 包含一个跨平台伴侣脚本,可通过 MQTT 远程安全地让你的 PC 休眠 | | 💡 | **状态 LED** — 提供 portal、连接中、就绪和已发送唤醒状态的视觉反馈 | | 🔁 | **崩溃循环检测** — 统计 RTC memory 中连续的固件崩溃次数,并在连续发生 3 次 panic 后自动回退到 captive portal(计数器在断电时重置) | | 🌍 | **Web Flasher** — 通过 USB 直接从浏览器刷入固件。无需 IDE 或工具链 | ## ✦ 构建配置
| | STANDARD | HARDENED | HARDENED STEALTH | |---|:---:|:---:|:---:| | Captive Portal 配置 | ✅ | ✅ | ✅ | | OTA 双槽分区 | ✅ | ✅ | ✅ | | 自愈式 WiFi 恢复 | ✅ | ✅ | ✅ | | 动态广播地址 | ✅ | ✅ | ✅ | | Ping 反馈 (ICMP) | ✅ | ✅ | ❌ | | GPIO 输出控制 | ✅ | ✅ | ❌ | | SecureOn 密码 | ✅ | ✅ | ✅ | | 状态 LED 反馈 | ✅ | ✅ | ❌ | | MQTT 响应 / 存在状态 | ✅ | ✅ | ❌ | | TOTP 命令身份验证 | ❌ | ✅ | ✅ | | HMAC 派生 MQTT topic | ❌ | ✅ | ✅ | | MAC 地址欺骗 | ❌ | ✅ | ✅ | | 主机名混淆 | ❌ | ✅ | ✅ | 有关源码构建命令和自定义,请参阅[构建配置](docs/build_profiles.md)。
## ✦ 硬件要求 - **ESP32**(经典版)开发板 - 连接到你的本地 WiFi 网络 - 可访问 MQTT broker(本地或云端,端口 1883 或 8883 TLS) - *(可选)* 默认使用 ESP32 的内置 LED 进行视觉状态反馈(出于隐蔽性考虑可禁用) 就是这样。无需任何额外组件。 ## ✦ 物理设置 **在正常运行期间,Heimdall 不需要通过 USB 连接到你的 PC。** 由于 Wake-on-LAN 使用无线广播机制,ESP32 只需要两样东西即可工作: 1. 电源(例如标准的 USB 充电器)。 2. 与你休眠 PC 连接到同一个本地网络子网的连接。 你可以将 ESP32 插在房间角落、沙发后面,甚至完全不同房间的插座上。当来自 MQTT broker 的命令到达时,ESP32 会通过你的 WiFi 广播一个“Magic Packet”,然后你的路由器会将其通过以太网线(或 WiFi)转发,以唤醒你沉睡的 PC。 ## ✦ Web Flasher(无需 IDE) 安装 Heimdall 最简单的方法是使用官方的 Web Flasher 直接从你的浏览器进行。你不需要安装任何开发工具,也不需要从源码编译任何东西。 **[🚀 启动 Heimdall Web Flasher](https://ss-sauron.github.io/Heimdall-Wake-On-Lan-ESP32/)** 1. 通过 USB 将你的 ESP32 连接到计算机。 2. 在受支持的浏览器(Chrome、Edge 或 Opera)中打开上面的链接。 3. 选择所需的构建配置(**Standard**、**Hardened (Full)** 或 **Hardened Stealth**),然后点击 **Connect**。 4. 选择你的 ESP32 的 COM 端口。 5. 点击 **Install Heimdall** 并等待刷入完成。 刷入后,跳转到下面的快速开始中的**第 4 步**,连接到 captive portal 并配置你的凭证。 ## ✦ 前置条件(从源码构建) 在构建之前,请确保已在你的 shell 中安装并导出了 ESP-IDF 环境。 | 要求 | 版本 | 备注 | |---|---|---| | [ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/) | v6.0.1 | 使用官方安装程序或 `install.sh` 流程 | | Python | 3.8+ | 由 ESP-IDF 工具设置安装 | | Xtensa ESP32 toolchain | ESP-IDF 管理 | 由 `install.sh` / ESP-IDF 安装程序安装 | | IDF Component Manager | ESP-IDF 内置 | 在构建期间解析管理的组件 | 使用以下命令检查活动环境: ``` idf.py --version ``` ## ✦ 快速开始(从源码构建) **1. 克隆项目** ``` git clone https://github.com/SS-Sauron/Heimdall.git cd Heimdall idf.py set-target esp32 ``` **2. 选择构建配置(可选)** 默认配置为 STANDARD。要切换到 HARDENED 或从源码构建 Stealth,请参阅[构建配置](docs/build_profiles.md)。构建前的快速覆盖方法: ``` idf.py menuconfig ``` 导航到 **WoL Relay → Build Profile**,选择配置,保存并退出。 对于不使用 menuconfig 的 Hardened 或 Stealth: ``` # Hardened (完整版) SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.hardened" idf.py build # Hardened Stealth SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.hardened;sdkconfig.hardened.stealth" idf.py build ``` **3. 构建、刷入并监控** ``` idf.py build flash monitor ``` **4. 连接到 portal** 首次启动时,Heimdall 会创建一个受 WPA2 保护的 WiFi 接入点。启用串行配置输出后,SSID 和永久 portal 密码将打印到串口监视器中。从你的手机或笔记本电脑连接——配置页面会在 iOS、Android 和 Windows 上自动打开。
Heimdall Captive Portal Configuration
保存后,设备将重启进入中继模式。使用下面的成功启动日志来确认 WiFi、TLS 和 MQTT 是否全部正常工作。 **5. 发送唤醒命令** 将目标机器的 MAC 地址作为纯文本 payload 发布到 Heimdall 的命令 topic: ``` AA:BB:CC:DD:EE:FF ``` *(如果你启用了 Ping 反馈,你可以选择包含目标 IP。有关 payload 格式,请参阅 **使用与操作**)。* 你的机器就会被唤醒。 向同一个命令 topic 发布不同的目标 MAC,即可唤醒同一个局域网上其他支持 WoL 的设备。Heimdall 不会存储单一的目标 PC MAC;payload 会为每个命令选择目标。 ## ✦ MQTT Broker Heimdall 可与托管或本地 MQTT broker 配合使用。对于基于 TLS 的 MQTT 使用端口 `8883`,或者在受信任的本地网络上对于普通 MQTT 使用端口 `1883`。 示例托管 broker 包括 [HiveMQ Cloud](https://www.hivemq.com/mqtt-cloud-broker/) 和 [Adafruit IO](https://io.adafruit.com)。这些仅作为示例;任何兼容的 MQTT broker 应该都可以工作。 在 portal 中,输入 broker 主机名,例如: ``` example-cluster.s1.eu.hivemq.cloud ``` 不要在 broker 字段中包含凭证、路径或真实的机密信息。诸如 `mqtts://`、`mqtt://`、`https://` 和 `tcp://` 之类的 scheme 前缀会被接受,但在存储前会被去除。 ## ✦ 首次配置启动 ``` I (645) main: Not provisioned — starting captive portal I (646) main: Portal password: (permanent — same after every reset) I (660) portal: Portal AP SSID: NETGEAR-XXXXXX I (663) portal: Portal AP Auth: WPA2 I (1109) portal: SoftAP started SSID: NETGEAR-XXXXXX Auth: WPA2 DHCP opt-114: http://192.168.4.1/ I (1117) dns_server: Listening on UDP port 53 — redirect → 192.168.4.1 I (1122) dns_server: Started — redirecting all A queries to 192.168.4.1 I (1135) portal: HTTP server ready on port 80 I (1135) portal: Portal ready — waiting for credentials I (10709) esp_netif_lwip: DHCP server assigned IP to a client, IP is: 192.168.4.2 I (123605) portal: Stripped scheme prefix from broker URL: 'https://xxx.eu.hivemq.cloud' → 'xxx.eu.hivemq.cloud' I (123618) storage: Credentials saved successfully I (123619) storage: Hostname saved: test-relay-name I (137113) portal: Credentials saved — rebooting into relay mode ``` ## ✦ 中继成功启动 在配置了有效的 WiFi 和 MQTT 凭证后,下一次重启应跳过 portal 并进入中继模式。重要的成功标志包括:WiFi 获取 IP 地址、TLS 验证 broker 证书、MQTT 连接成功,以及确认命令 topic 订阅。
Heimdall relay startup confirmation screen
``` I (646) identity: Hostname loaded from NVS: test-relay I (649) main: Credentials found — starting relay I (2875) wifi_sta: Got IP: I (2876) main: WiFi connected I (2879) main: Starting MQTT relay I (2881) opsec: Command topic: wol/ I (2885) opsec: Status topic: wol//s I (2887) opsec: Log topic: wol//l I (2893) mqtt_relay: Connecting to MQTT broker: mqtts://.hivemq.cloud:8883 I (2900) mqtt_relay: MQTT credential lengths: username= password= I (2906) mqtt_relay: TLS hostname verification/SNI: enabled via broker URI hostname I (2917) mqtt_relay: MQTT client started — relay is active I (3702) esp-x509-crt-bundle: Certificate validated I (4895) mqtt_relay: MQTT connected — subscribing to: wol/ I (5002) mqtt_relay: Subscription confirmed (msg_id=22951) ``` 如果日志显示到 `MQTT connected` 和 `Subscription confirmed`,则 Heimdall 已上线,并正在上面显示的命令 topic 上等待唤醒命令。 ## ✦ 使用与操作 一旦 Heimdall 成功配置并连接到你的 MQTT broker,你就可以开始发送唤醒命令了。 ### ✦ 查找你的命令 Topic Heimdall 订阅和发布的 topic 取决于所选的构建配置。响应分为 **Status** topic (`/s`) 用于保留的机器可读状态,以及 **Log** topic (`/l`) 用于未保留的人类可读诊断信息。 **STANDARD 构建** ``` Command: wol/ Status: wol//s Log: wol//l ``` `` 是在串口监视器中打印的 ESP32 station MAC。 **HARDENED 构建** ``` Command: <16-character-hmac-topic> Status: <16-character-hmac-topic-base>/s Log: <16-character-hmac-topic-base>/l ``` HARDENED topic 是由设备 MAC 和配置期间生成的密钥派生出的不透明字符串。它们在中继启动期间打印到串口监视器。 ### ✦ 让 PC 休眠 Heimdall 包含一个跨平台伴侣脚本(`sleep_listener.py` 和 `sleep_listener.exe`),可在你的目标 PC 上静默运行。当它通过你的 MQTT broker 接收到特定的休眠命令时,会立即触发操作系统休眠(或挂起)。 有关完整的设置说明,请参阅 **[PC 休眠监听指南](docs/pc_sleep_listener.md)**。 ### ✦ 使用触发脚本 代码库包含了现成的 Bash 脚本,可为你格式化 MQTT payload 并处理 `mosquitto_pub` 命令。 **前提条件:** 你必须安装 `mosquitto-clients`(如果使用 hardened 脚本,还需安装 `oathtool`)。 **STANDARD 脚本用法:** ``` ./scripts/wake_standard.sh [user] [pass] ``` *示例:* `./scripts/wake_standard.sh mqtt.example.com 8883 "wol/AA:BB:CC:11:22:33" 99:88:77:66:55:44` **HARDENED 脚本用法(带 TOTP):** ``` ./scripts/wake_hardened.sh [user] [pass] ``` *示例:* `./scripts/wake_hardened.sh mqtt.example.com 8883 "a1b2c3d4e5f6g7h8" 99:88:77:66:55:44 "JBSWY3DPEHPK3PXP"` ### ✦ Ping 反馈(可选) 如果你的固在编译时启用了 `CONFIG_WOL_PING_FEEDBACK=y`,你可以在命令中包含目标 PC 的 IP 地址。Heimdall 将 ping 该机器,并在其成功启动或超时时发布警报。 **Standard 构建 (JSON):** 发送 JSON payload 代替纯文本: ``` {"mac":"AA:BB:CC:DD:EE:FF", "ip":"192.168.1.100"} ``` **Hardened 构建 (字符串):** 将 IP 地址作为第 4 段附加在 MAC 和 TOTP 之后: ``` AA:BB:CC:DD:EE:FF:123456:192.168.1.100 ``` ### ✦ 响应 Payload 在发送 magic packet 后(Standard 和 Hardened Full 构建),Heimdall 会向 **Status** topic (`/s`) 发布确认信息: ``` { "mac": "AA:BB:CC:DD:EE:FF", "status": "sent" } ``` 系统诊断信息(如 uptime 和剩余堆内存)会定期发布,并在执行唤醒命令时发布到 **Log** topic (`/l`): ``` { "free_heap": 187432, "uptime_s": 3672 } ``` 如果请求了 Ping 反馈,一旦机器启动(或超时),你将在 **Status** topic 上收到*第二条*消息: ``` { "mac": "AA:BB:CC:DD:EE:FF", "status": "awake", "boot_time_s": 14 } ``` | 字段 | 描述 | |---|---| | `mac` | 发送 Wake-on-LAN magic packet 的目标 MAC 地址。 | | `status` | `sent`(已广播 WoL)、`awake`(ping 成功)、`timeout`(ping 失败)、`ota_start`(OTA 开始)、`ota_ok`(OTA 完成)或 `ota_fail`(OTA 错误)。 | | `reason` |(仅限 Status topic)解释 OTA 更新失败原因的描述性字符串。 | | `boot_time_s` | 从广播 WoL 到第一次成功收到 ping 回复之间经过的秒数。 | | `free_heap` |(仅限 Log topic)ESP32 上可用的 RAM 字节数。可用于监控设备健康状况。 | | `uptime_s` |(仅限 Log topic)自上次重启以来 ESP32 持续运行的总时间(秒)。 | ### ✦ GPIO 输出控制 如果你的固件在编译时启用了 `CONFIG_WOL_GPIO_COMMANDS=y`,你可以通过向主命令 topic 发布 JSON payload 来控制 ESP32 上的特定 GPIO 引脚。 只能控制 `CONFIG_WOL_GPIO_ALLOWED_PINS` 中列出的引脚。 **Standard 构建 (JSON):** ``` {"action":"gpio", "pin":4, "level":1} ``` **Hardened 构建 (带 TOTP 的 JSON):** ``` {"action":"gpio", "pin":4, "level":1, "totp":123456} ``` Heimdall 将向 **Status** topic (`/s`) 发布回确认信息: ``` {"action":"gpio", "pin":4, "level":1, "status":"ok"} ``` ### ✦ TOTP 设置(仅限 HARDENED) 启用 TOTP 后,每个唤醒命令都必须在目标 MAC 地址后附加一个有效的 6 位时间验证码: ``` AA:BB:CC:DD:EE:FF:123456 ``` TOTP 种子在配置期间生成,并在 portal 机密页面上**一次性**显示为 Base32 值以及 `otpauth://` URI。请立即保存。如果丢失,请恢复出厂设置并重新配置设备以生成新种子。 任何兼容 RFC 6238 的身份验证器应用或触发脚本都可以根据该种子生成代码。 ### ✦ 状态 LED 模式 Heimdall 默认使用 ESP32 的内置 LED (GPIO2) 提供实时的视觉反馈。你也可以选择将外部 LED 连接到自定义引脚,或者在配置中完全禁用 LED,以适用于隐蔽部署。 | 状态 | LED 模式 | 描述 | |---|---|---| | **Portal 模式** | 快速闪烁(~2.5Hz) | 等待你连接到 Heimdall WiFi 设置 portal | | **连接中** | 缓慢呼吸(~0.5Hz) | 正在尝试连接 WiFi 和 MQTT broker | | **就绪** | 常亮 | 已连接并正在主动监听唤醒命令 | | **已发送唤醒** | 快速闪烁 6 次(50ms) | Magic packet 已发送 —— 自动返回就绪状态 | ## ✦ Over-The-Air (OTA) 更新 Heimdall 使用带有自动回滚功能的双槽 OTA 分区表。如果新固件在启动时崩溃或未能连接到 MQTT broker,bootloader 会自动恢复到上一个正常工作的槽位。 **MQTT 触发的 OTA 拉取**是主要的更新方法。向 `/ota` 发布 JSON payload: ``` {"url":"https://example.com/heimdall.bin"} ``` HARDENED 构建需要 TOTP 代码: ``` {"url":"https://example.com/heimdall.bin","totp":123456} ``` 设备在此过程中会向 status topic 发布 `ota_start`、`ota_ok` 和 `ota_fail` 状态事件。有关完整的 payload 参考、进度事件、并发行为和 HTTP 注意事项,请参阅技术文档中的[通过 MQTT 进行 OTA 更新](docs/README.md#ota-updates-via-mqtt)部分。 你也可以通过以下方式手动更新: - **[Web Flasher](https://ss-sauron.github.io/Heimdall-Wake-On-Lan-ESP32/)** — 通过 USB 直接从浏览器刷入。无需工具。 - **`idf.py flash`** — 使用 ESP-IDF 工具链从源码重新构建并通过 USB 刷入。 回滚保证适用于所有方法:一旦新固件成功连接到你的 MQTT broker 并订阅了命令 topic,它就会调用 `esp_ota_mark_app_valid_cancel_rollback()` 来永久提交更新。 ## ✦ 恢复出厂设置 要清除存储的凭证并返回配置模式: 1. 按住 **BOOT** 按钮 5 秒钟。 2. 在串口监视器中等待恢复出厂设置确认信息。 3. 设备会擦除 `wol` NVS namespace 并重启进入 captive portal。 这在正常中继操作期间以及配置失误后均有效。 ## ✦ 项目结构 ``` Heimdall/ ├── components/ │ ├── dns_server/ # Captive portal DNS redirect │ ├── identity/ # MAC spoofing & hostname obfuscation │ ├── mqtt_relay/ # MQTT client & WoL dispatch core │ ├── opsec/ # HMAC topics, TOTP, SNTP │ ├── ota/ # MQTT-triggered HTTPS OTA pull │ ├── portal/ # Provisioning web server │ ├── status_led/ # Visual status LED feedback │ ├── storage/ # NVS credential persistence │ ├── wifi_sta/ # WiFi station with self-healing │ └── wol/ # Magic packet builder & broadcaster (SecureOn support) ├── docs/ # Extended documentation and Web Flasher UI (GitHub Pages) ├── experimental/ # Sandbox for upcoming features and design files ├── main/ # Boot sequence & orchestration ├── resources/ # README images and visual design assets ├── scripts/ # MQTT trigger helpers, Windows WoL setup, OTA push helper, │ # and PC sleep companion (sleep_listener.py / .exe) ├── .clangd # IDE language server config (clangd + ESP-IDF/GCC compatibility) ├── partitions.csv # OTA-ready dual-slot partition table ├── sdkconfig.defaults # Baseline Kconfig configuration for STANDARD profile ├── sdkconfig.hardened # Kconfig overrides for the HARDENED profile ├── sdkconfig.hardened.stealth # Stealth toggles layered on HARDENED └── sleep_listener.spec # PyInstaller spec used to build the sleep_listener.exe binary ``` ## ✦ CI/CD Pipeline 每次推送到 `main` 分支都会触发自动化的 GitHub Actions 工作流,该工作流会: - **构建** 使用官方 Espressif ESP-IDF Docker 镜像并行构建 STANDARD、HARDENED 和 HARDENED STEALTH 固件配置。 - **部署** 将 Web Flasher 部署到 GitHub Pages,将最新编译的 `.bin` 文件与 flasher UI 打包在一起,以便用户始终可以从浏览器刷入最新代码。 每个 Git 标签 (`v1.0.0`) 还会额外: - **创建 GitHub Release** 并将编译好的 `heimdall-standard.bin`、`heimdall-hardened.bin` 和 `heimdall-hardened-stealth.bin` 作为可下载的制品附加上去。 ## ✦ 贡献 欢迎提交 Bug 报告、功能请求和 Pull Request。在进行较大更改之前,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。
## ✦ 构建所用技术 [![C](https://img.shields.io/badge/C-99-A8B9CC?style=for-the-badge&logo=c&logoColor=white)](https://en.wikipedia.org/wiki/C99) [![FreeRTOS](https://img.shields.io/badge/FreeRTOS-embedded-brightgreen?style=for-the-badge)](https://www.freertos.org/) [![mbedTLS](https://img.shields.io/badge/mbedTLS-3.x-003865?style=for-the-badge)](https://tls.mbed.org/) [![lwIP](https://img.shields.io/badge/lwIP-network%20stack-0078D4?style=for-the-badge)](https://savannah.nongnu.org/projects/lwip/) *Heimdall 守望着 Bifrost —— 连接各个领域的桥梁。* *而这个项目守护着你的网络。同样的工作,更小的开发板。*
**[ [文档](docs/) · [发布版本](https://github.com/SS-Sauron/Heimdall/releases) · [许可证](LICENSE) ]**
标签:ESP32, OTA升级, TOTP认证, Wake-on-LAN, 后端开发, 固件开发, 底层编程, 物联网, 逆向工具