feat: implement dynamic Eleventy tiling blog, modular CSS, and agent customizations
- Add project foundation README.md and root AGENTS.md for pair programming - Configure .agents/ rules and skills for Eleventy tiling and Obsidian publishing - Decompose monolithic styles into modular tokens, reset, layout, and component CSS - Implement Nunjucks layout inheritance (base.njk, post.njk, page.njk) and reusable partials - Configure Eleventy 3 with markdown-it-anchor, syntax highlighting, and dynamic collections - Migrate sample prototypes into dynamic dispatches lander, gateway, and Markdown posts - Add multi-stage Dockerfile and clean-URL nginx.conf for production serving
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
---
|
||||
layout: layouts/post.njk
|
||||
title: "High-Availability Traefik Router with Docker Compose"
|
||||
date: 2026-07-15
|
||||
tags:
|
||||
- homelab
|
||||
- networking
|
||||
- docker
|
||||
excerpt: "Architecting a redundant reverse-proxy setup with automated Let's Encrypt wildcard DNS challenge routing and zero-downtime container swaps."
|
||||
readingTime: "12 MIN READ"
|
||||
featured: false
|
||||
difficulty: "ADVANCED"
|
||||
---
|
||||
|
||||
## 1.0 Topology Overview
|
||||
|
||||
Operating production services on bare-metal home clusters demands strict ingress routing, SSL termination, and health checking. Rather than managing manual Nginx upstream definitions, Traefik dynamically listens to Docker socket events and generates routing graphs automatically.
|
||||
|
||||
```text
|
||||
[Internet / WireGuard Mesh]
|
||||
|
|
||||
[Edge Router]
|
||||
|
|
||||
+--------+--------+
|
||||
| |
|
||||
[Traefik 01] [Traefik 02] (Keepalived VIP)
|
||||
| |
|
||||
+--------+--------+
|
||||
|
|
||||
[Internal Overlay]
|
||||
|
|
||||
+-------+-------+
|
||||
| | |
|
||||
[App1] [App2] [App3]
|
||||
```
|
||||
|
||||
## 2.0 Docker Compose Infrastructure
|
||||
|
||||
The core proxy layer is configured with strict network isolation, healthchecks, and non-root execution:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.1
|
||||
container_name: edge_router
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
environment:
|
||||
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./traefik.yml:/traefik.yml:ro
|
||||
- ./acme.json:/acme.json
|
||||
networks:
|
||||
- proxy_net
|
||||
|
||||
networks:
|
||||
proxy_net:
|
||||
external: true
|
||||
```
|
||||
|
||||
## 3.0 Verification & Failover Testing
|
||||
|
||||
Run the health check endpoint using `curl` to verify response headers:
|
||||
|
||||
```sh
|
||||
curl -Iv https://router.rooks.internal/ping
|
||||
```
|
||||
|
||||
All requests route through mutual TLS with zero dropped connections during container redeploys.
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
layout: layouts/post.njk
|
||||
title: "Reverse Engineering IoT Firmware: SPI Flash Extraction"
|
||||
date: 2026-07-20
|
||||
tags:
|
||||
- firmware
|
||||
- hardware
|
||||
- security
|
||||
- bus-pirate
|
||||
excerpt: "Physical hardware exploitation and firmware dump walkthrough via direct SPI flash memory extraction on an IoT gateway using Bus Pirate and flashrom."
|
||||
readingTime: "8 MIN READ"
|
||||
featured: true
|
||||
difficulty: "INTERMEDIATE"
|
||||
---
|
||||
|
||||
## 1.0 Executive Summary
|
||||
|
||||
In security audits of embedded systems, retrieving the firmware image is the critical foundational step. When manufacturers encrypt over-the-air (OTA) updates and blow electronic fuses to permanently disable silicon debug ports (such as `UART` serial consoles and `JTAG/SWD` test pads), physical memory extraction directly off the circuit board becomes mandatory.
|
||||
|
||||
This writeup details the complete process of extracting a binary image from an 8-pin SOP SPI flash chip (Winbond W25Q64JV, 8MB) using a **Dangerous Prototypes Bus Pirate v4** hardware bridge and the open-source `flashrom` utility.
|
||||
|
||||
<div class="markdown-callout callout-note">
|
||||
<div class="callout-title">[!NOTE] Target Board Isolation</div>
|
||||
<p>Always de-solder the SPI flash chip or clamp using an SOP8 test clip with the host microcontroller's reset line (<code>/RESET</code>) driven low to prevent the main SoC from contending on the SPI bus.</p>
|
||||
</div>
|
||||
|
||||
## 2.0 Hardware Pinout & Bus Pirate Setup
|
||||
|
||||
The target is an 8-pin Small Outline Package (SOP-8). Pin 1 is easily identified by the circular depression in the epoxy mold. Connect the Bus Pirate flying leads directly according to the standard SPI protocol mapping:
|
||||
|
||||
### 2.1 SOP8 Pinout Matrix
|
||||
|
||||
| SOP8 Pin # | Signal Name | Bus Pirate Lead | Electrical Purpose |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **1** | `/CS` | CS (White) | Chip Select (Active Low) |
|
||||
| **2** | `DO (MISO)` | MISO (Black) | Serial Data Output from Flash |
|
||||
| **3** | `/WP` | +3.3V (VPU) | Write Protect (Tied High to Disable) |
|
||||
| **4** | `GND` | GND (Brown) | System Ground Reference |
|
||||
| **5** | `DI (MOSI)` | MOSI (Grey) | Serial Data Input to Flash |
|
||||
| **6** | `CLK` | CLK (Purple) | Serial Clock Driven by Master |
|
||||
| **7** | `/HOLD` | +3.3V (VPU) | Hold / Suspend Input (Tied High) |
|
||||
| **8** | `VCC` | +3.3V (Red) | Supply Voltage (Nominal 3.3V DC) |
|
||||
|
||||
<div class="markdown-callout callout-warning">
|
||||
<div class="callout-title">[!WARNING] Electrical Voltage Rating</div>
|
||||
<p>Verify whether your target chip is a <strong>3.3V</strong> part (e.g., <code>W25Q64FV</code>) or a <strong>1.8V</strong> part (e.g., <code>W25Q64FW</code>). Supplying 3.3V logic to a 1.8V chip will permanently destroy the silicon junction gates.</p>
|
||||
</div>
|
||||
|
||||
## 3.0 SPI Extraction via flashrom
|
||||
|
||||
Plug the Bus Pirate into your analysis workstation via USB. It registers as `/dev/ttyUSB0`. Query the chip ID register using the `0x9F` JEDEC Read ID command:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
# Query the SPI flash details using flashrom via Bus Pirate
|
||||
flashrom -p buspirate_spi:dev=/dev/ttyUSB0,spispeed=1M -r firmware_dump1.bin
|
||||
|
||||
# Repeat extraction to create a secondary dump for comparison
|
||||
flashrom -p buspirate_spi:dev=/dev/ttyUSB0,spispeed=1M -r firmware_dump2.bin
|
||||
|
||||
# Verify the integrity of the binary dumps by diffing
|
||||
cmp firmware_dump1.bin firmware_dump2.bin
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "[+] SPI Dumps match identically! Proceeding to hashing..."
|
||||
md5sum firmware_dump1.bin
|
||||
sha256sum firmware_dump1.bin
|
||||
else
|
||||
echo "[-] Bit flip or voltage sag detected! Re-run extraction." >&2
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
Press <kbd>Ctrl</kbd> + <kbd>C</kbd> if the bus fails to synchronize. Once complete, inspect the initial bytes with `hexdump`:
|
||||
|
||||
```text
|
||||
0000000: 2705 1956 7062 8251 60a4 2130 0041 5262 '..Vpb.Q`.!0.ARb
|
||||
0000010: 6873 7173 0000 0004 0000 0000 0000 1000 hsqs............
|
||||
0000020: 0002 0001 0000 0000 636f 6e66 6967 2e64 ........config.d
|
||||
```
|
||||
|
||||
Notice the magic bytes `6873 7173` (ASCII representation: **`hsqs`**) at offset `0x000010`. This confirms the presence of a SquashFS compressed root filesystem!
|
||||
|
||||
## 4.0 Binary Verification & Hashes
|
||||
|
||||
Before proceeding with automated deconstruction using `binwalk -Me`, record cryptographic hashes in your lab notebook:
|
||||
|
||||
- **Dump Size:** `8,388,608 bytes` (8192 KiB)
|
||||
- **MD5:** `d41d8cd98f00b204e9800998ecf8427e`
|
||||
- **SHA-256:** `a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e`
|
||||
|
||||
## 5.0 Audit Checklist
|
||||
|
||||
Ensure all forensics hygiene steps have been recorded:
|
||||
|
||||
- [x] Visual optical inspection and pinout diagram documented
|
||||
- [x] Clean dual flashrom dumps matching via bitwise `cmp`
|
||||
- [x] SquashFS magic header identified at offset `0x10`
|
||||
- [ ] Filesystem extraction and hardcoded credentials analysis (Part 2)
|
||||
Reference in New Issue
Block a user