Metadata-Version: 2.4
Name: bluehood
Version: 0.2.0
Summary: Bluetooth neighborhood monitor - track devices in your area
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: bleak>=0.21.0
Requires-Dist: aiosqlite>=0.19.0
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: mac-vendor-lookup>=0.1.12
Provides-Extra: metrics
Requires-Dist: prometheus-client>=0.21.0; extra == "metrics"
Dynamic: license-file

# Bluehood

**Bluetooth Neighborhood** - Track BLE devices in your area and analyze traffic patterns.

[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://buymeacoffee.com/d3hkz6gwle)

---

> **WARNING: Alpha Software**
>
> This project is in early development and is **not ready for production use**. Features may change, break, or be removed without notice. Use at your own risk. Data collected should be treated as experimental.

---

## Screenshots

![Dashboard](screenshots/dashboard.png)
*Main dashboard showing device list with filtering, search, and real-time statistics*

![Settings](screenshots/settings.png)
*Tabbed configuration page — Alerts, Operations, Groups, and Security*

![About](screenshots/about.png)
*Intel page with project information and capabilities overview*

## Why?

This project was inspired by the [WhisperPair vulnerability](https://whisperpair.eu/) ([CVE-2025-36911](https://nvd.nist.gov/vuln/detail/CVE-2025-36911)), which highlighted privacy risks in Bluetooth devices.

Thousands of Bluetooth devices surround us at all times: phones, cars, TVs, headphones, hearing aids, delivery vehicles, and more. Bluehood demonstrates how simple it is to passively detect these devices and observe patterns in their presence.

With enough data, you could potentially:
- Understand what time someone typically walks their dog
- Detect when a visitor arrives at a house
- Identify patterns in daily routines based on device presence

This metadata can reveal surprisingly personal information without any active interaction with the devices.

**Bluehood is an educational tool to raise awareness about Bluetooth privacy.** It's a weekend project, but the implications are worth thinking about.

## What?

Bluehood is a Bluetooth scanner that:

- **Continuously scans** for nearby Bluetooth devices (both BLE and Classic)
- **Identifies devices** by vendor (MAC address lookup) and BLE service UUIDs
- **Classifies devices** into categories (phones, audio, wearables, IoT, vehicles, etc.)
- **Tracks presence patterns** over time with hourly/daily heatmaps
- **Filters out noise** from randomized MAC addresses (privacy-rotated devices)
- **Analyzes device correlations** to find devices that appear together
- **Sends push notifications** when watched devices arrive or leave
- **Provides a web dashboard** for monitoring and analysis

## Features

### Scanning
- Dual-mode scanning: Bluetooth Low Energy (BLE) and Classic Bluetooth
- MAC address vendor lookup (local database + online API fallback)
- BLE service UUID fingerprinting for accurate device classification
- Classic Bluetooth device class parsing
- Randomized MAC filtering (hidden from main view)

### Device Management
- Mark devices as "Watched" for tracking personal devices
- Organize devices into custom groups
- Set friendly names for known devices
- Add custom notes/tags to any device
- Device type detection (phones, audio, wearables, IoT, vehicles, etc.)

### Analytics
- **30-day presence timeline** visualization
- **Signal strength (RSSI) history** chart with 7-day data
- **Hourly and daily activity heatmaps** showing when devices are active
- **Pattern analysis** ("Weekdays, evenings 5PM-9PM")
- **Dwell time analysis** showing total time devices spend in range
- **Device correlation** detection to find devices that appear together
- **Proximity zones** (immediate, near, far, remote) based on signal strength
- Search by MAC, vendor, or name
- Date range search for historical queries

### Notifications (via ntfy.sh)
- Push notifications to your phone/desktop
- Notify when new devices are detected
- Notify when watched devices return
- Notify when watched devices leave
- Configurable thresholds for arrival/departure

### Operations
- **Heartbeat check-in** — periodically POST status to an uptime monitoring service (e.g., Uptime Kuma, Healthchecks.io)
- **Storage rotation** — automatically prune sightings older than a configurable number of days
- Both configurable from the web UI or via environment variables

### Web Interface
- **Compact/Detailed view toggle** for different display preferences
- **Screenshot mode** to obfuscate MACs and names for safe sharing
- **Keyboard shortcuts** for power users (press `?` to view)
- **CSV export** of device data
- **Device groups** for organizing related devices
- **Optional authentication** to secure access

## How?

### Quick Start with Docker (Recommended)

> **Prerequisites — Linux hosts only**
>
> Bluehood communicates with your Bluetooth adapter via BlueZ, the Linux Bluetooth stack. **BlueZ must be installed and running on the host before starting the container** — the Docker image itself does not include it.
>
> ```bash
> # Debian / Ubuntu (including Ubuntu Server)
> sudo apt install bluez
> sudo systemctl enable --now bluetooth
>
> # Arch Linux
> sudo pacman -S bluez bluez-utils
> sudo systemctl enable --now bluetooth
> ```
>
> Without BlueZ on the host you'll see an error like:
> `BLE scan error: [org.freedesktop.DBus.Error.ServiceUnknown] The name org.bluez was not provided by any .service files`

```bash
# Create a docker-compose.yml or download the one from this repo
# Then start with Docker Compose
docker compose up -d

# View logs
docker compose logs -f
```

The Docker image is available on GitHub Container Registry:

```
ghcr.io/dannymcc/bluehood:latest
```

The web dashboard will be available at **http://localhost:8080**

#### Docker Requirements

- Docker and Docker Compose
- Linux host with a **BLE-capable Bluetooth adapter** (Bluetooth 4.0+) that supports the **Central** role
- BlueZ installed and running on the host (`sudo apt install bluez && sudo systemctl enable --now bluetooth`)

> **Note**: Older adapters (Bluetooth 2.x/3.x) do not support BLE scanning. If your adapter lacks BLE Central role support, you will see: `No Bluetooth adapters with BLE 'central' role found`.

> **Note**: Docker runs in privileged mode with host networking for Bluetooth access. This is required for BLE scanning.

#### Docker Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `PUID` | `1000` | UID for the container user — set to match your host user (`id -u`) when using bind mounts |
| `PGID` | `1000` | GID for the container user — set to match your host group (`id -g`) when using bind mounts |
| `TZ` | UTC | Container timezone (e.g., `Europe/London`) |
| `BLUEHOOD_ADAPTER` | auto | Bluetooth adapter for BLE scanning (e.g., `hci0`) |
| `BLUEHOOD_CLASSIC_ADAPTER` | same as `BLUEHOOD_ADAPTER` | Separate adapter for classic Bluetooth scanning (e.g., `hci1`). When set to a different adapter, BLE and classic scans run concurrently. |
| `BLUEHOOD_DATA_DIR` | `/data` | Database storage directory |
| `BLUEHOOD_METRICS_PORT` | disabled | Prometheus metrics port (e.g., `9199`) |
| `BLUEHOOD_HEARTBEAT_URL` | disabled | URL to POST heartbeat check-ins (e.g., a healthchecks.io or uptime-kuma push URL) |
| `BLUEHOOD_HEARTBEAT_INTERVAL` | `300` | Seconds between heartbeat check-ins |
| `BLUEHOOD_PRUNE_DAYS` | `0` (disabled) | Auto-delete sightings older than N days to free storage |

### Bluetooth Adapter Requirements

Bluehood requires a **BLE-capable Bluetooth adapter** (Bluetooth 4.0 or later) with **Central** role support. Older Bluetooth 2.x/3.x adapters do not support BLE scanning and will not work.

If your adapter does not support the BLE Central role, Bluehood will exit with:
```
No Bluetooth adapters with BLE 'central' role found
```

You can check your adapter's capabilities with `bluetoothctl show` and look for `central` in the supported roles.

### Manual Installation (Linux)

```bash
# Install system dependencies (Arch Linux)
sudo pacman -S bluez bluez-utils python-pip

# Install system dependencies (Debian/Ubuntu)
sudo apt install bluez python3-pip

# Clone and install
git clone https://github.com/dannymcc/bluehood.git
cd bluehood
pip install -e .
```

#### Bluetooth Permissions

Bluetooth scanning requires elevated privileges. Choose one:

1. **Run as root** (simplest):
   ```bash
   sudo bluehood
   ```

2. **Grant capabilities to Python**:
   ```bash
   sudo setcap 'cap_net_admin,cap_net_raw+eip' $(readlink -f $(which python))
   bluehood
   ```

3. **Use systemd service** (recommended for always-on):
   ```bash
   sudo cp bluehood.service /etc/systemd/system/
   sudo systemctl daemon-reload
   sudo systemctl enable --now bluehood
   ```

### macOS

Bluehood works natively on macOS without Docker. macOS uses CoreBluetooth instead of BlueZ, which is handled automatically by the `bleak` library.

```bash
# Clone the repository
git clone https://github.com/dannymcc/bluehood.git
cd bluehood

# Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate

# Install
pip install -e .

# Run
python -m bluehood.daemon
```

The web dashboard will be available at **http://localhost:8080**

> **Note**: On first run, macOS will prompt you to allow Bluetooth access. You must grant this permission for scanning to work.

## Usage

```bash
# Start with web dashboard (default port 8080)
bluehood

# Specify a different port
bluehood --port 9000

# Use a specific Bluetooth adapter
bluehood --adapter hci1

# Use separate adapters for BLE and classic scanning (concurrent)
bluehood --adapter hci0 --classic-adapter hci1

# List available adapters
bluehood --list-adapters

# Disable web dashboard (scanning only)
bluehood --no-web

# Enable Prometheus metrics exporter on port 9199
bluehood --metrics-port 9199
```

## Web Dashboard

The dashboard provides:

- **Device list** with type icons, vendor, MAC, name, sightings, last seen
- **Device filters** by type (phones, audio, IoT, etc.) and watched status
- **Search** by MAC, vendor, or name
- **Date range search** to find devices seen in a specific time window
- **Tabbed settings** page — Alerts, Operations, Groups, and Security (direct-link via hash, e.g. `/settings#operations`)
- **Device details** modal with:
  - BLE service fingerprints
  - Hourly/daily activity heatmaps
  - 30-day presence timeline
  - Signal strength (RSSI) history chart
  - Pattern analysis
  - Dwell time statistics
  - Correlated devices list
  - Proximity zone indicator
  - Operator notes field
  - Group assignment

### Keyboard Shortcuts

| Key | Action |
|-----|--------|
| `/` | Focus search bar |
| `r` | Refresh device list |
| `c` | Toggle compact view |
| `w` | Toggle watch on selected device |
| `Esc` | Close modal |
| `?` | Show keyboard shortcuts |

### Screenshot Mode

Enable screenshot mode from the sidebar to obfuscate sensitive data before sharing screenshots:
- MAC addresses show only first 2 octets (e.g., `AA:BB:XX:XX:XX:XX`)
- Friendly names show only first 2 characters (e.g., `Da********`)
- CSV exports also respect screenshot mode

## Push Notifications

Bluehood can send push notifications via [ntfy.sh](https://ntfy.sh), a free, open-source notification service.

1. Create a topic at ntfy.sh (e.g., `bluehood-myname-alerts`)
2. Subscribe to the topic on your phone using the ntfy app
3. In Bluehood settings, enter your topic name and enable notifications
4. Configure which events trigger notifications:
   - New device detected
   - Watched device returns (after being absent)
   - Watched device leaves (not seen for X minutes)

## Data Storage

Data is stored in `~/.local/share/bluehood/bluehood.db` (SQLite).

Override location with environment variables:
- `BLUEHOOD_DATA_DIR` - Directory for data files
- `BLUEHOOD_DB_PATH` - Direct path to database file

> **Note**: Heartbeat and pruning settings can be configured from the web UI (Settings > Operations) or via environment variables. GUI values take priority over env vars.

## How It Works

### Device Classification

Bluehood classifies devices using multiple signals (in priority order):

1. **BLE Service UUIDs** - Most accurate (Heart Rate = wearable, A2DP = audio, etc.)
2. **Device name patterns** - "iPhone", "Galaxy", "AirPods", etc.
3. **Vendor OUI lookup** - Apple, Samsung, Bose, etc.

### Randomized MACs

Modern devices randomize their MAC addresses for privacy. Bluehood:
- Detects randomized MACs (locally administered bit)
- Hides them from the main device list (not useful for tracking)
- Shows a count of hidden randomized devices

### Pattern Analysis

Bluehood analyzes sighting timestamps to detect patterns:

- **Time of day**: Morning, Afternoon, Evening, Night
- **Day of week**: Weekdays, Weekends
- **Frequency**: Constant, Daily, Regular, Occasional, Rare

Example patterns: "Daily, evenings (5PM-9PM)", "Weekdays, morning (8AM-12PM)"

### Device Correlation

Bluehood detects devices that frequently appear together within a configurable time window. This can reveal:
- Devices owned by the same person (phone + smartwatch)
- People who travel together
- Devices that share a schedule

### Proximity Zones

Based on RSSI signal strength, devices are classified into proximity zones:
- **Immediate** (> -50 dBm): Very close, within a few meters
- **Near** (-50 to -60 dBm): Nearby, same room
- **Far** (-60 to -70 dBm): Further away, adjacent rooms
- **Remote** (< -70 dBm): Distant, at edge of detection range

### Dwell Time Analysis

Tracks how long devices spend in range by analyzing gaps between sightings. A configurable gap threshold (default 15 minutes) determines when a new "session" begins.

## Prometheus Metrics

Bluehood can expose metrics for Prometheus scraping. Enable by setting the `BLUEHOOD_METRICS_PORT` environment variable or the `--metrics-port` CLI flag.

```bash
# Via environment variable
export BLUEHOOD_METRICS_PORT=9199

# Via CLI
bluehood --metrics-port 9199
```

Metrics are served at `http://host:9199/metrics`.

### Available Metrics

| Metric | Type | Description |
|--------|------|-------------|
| `bluehood_scans_total` | Counter | Total scan cycles completed |
| `bluehood_scan_errors_total` | Counter | Scan errors (label: `scan_type`) |
| `bluehood_sightings_total` | Counter | Total device sightings recorded |
| `bluehood_new_devices_total` | Counter | New unique devices discovered |
| `bluehood_last_scan_devices` | Gauge | Devices in last scan (label: `scan_type`) |
| `bluehood_devices_total` | Gauge | Unique devices in DB (label: `bt_type`) |
| `bluehood_devices_active` | Gauge | Devices seen in last 5 minutes |
| `bluehood_devices_watched` | Gauge | Watched device count |
| `bluehood_devices_ignored` | Gauge | Ignored device count |
| `bluehood_scan_duration_seconds` | Histogram | Scan cycle duration |
| `bluehood_device_rssi_dbm` | Histogram | RSSI distribution of BLE devices |
| `bluehood_build_info` | Info | Version information |

### Grafana Dashboard

A ready-to-import Grafana dashboard is included at [`grafana/bluehood-dashboard.json`](grafana/bluehood-dashboard.json). Import it via the Grafana UI (Dashboards > Import) or the API:

```bash
curl -X POST "http://localhost:3000/api/dashboards/db" \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d "{\"dashboard\": $(cat grafana/bluehood-dashboard.json), \"overwrite\": true}"
```

## Troubleshooting

### No devices found
- Ensure your adapter supports BLE (Bluetooth 4.0+) with the Central role — older adapters won't work
- Ensure Bluetooth adapter is enabled: `bluetoothctl power on`
- Check adapter is detected: `bluehood --list-adapters`
- Run with sudo if permission denied

### Docker issues

**`BLE scan error: org.freedesktop.DBus.Error.ServiceUnknown` / `The name org.bluez was not provided`**

BlueZ is not installed or not running on the host. Fix:
```bash
sudo apt install bluez          # Debian/Ubuntu
sudo systemctl enable --now bluetooth
docker compose restart
```

**General checklist:**
- Ensure BlueZ is installed on the **host** (not just in the container)
- Verify Bluetooth service is running: `systemctl status bluetooth`
- Confirm your adapter is visible: `bluetoothctl list`

## Contributing

Contributions welcome! Please open an issue or PR on GitHub.

### Contributors

- [@martinh2011](https://github.com/martinh2011) (Martin Hüser) - MAC vendor cache improvements
- [@hatedabamboo](https://github.com/hatedabamboo) (Kirill Solovei) - Light theme support
- [@krnltrp](https://github.com/krnltrp) - Web UI enhancements
- [@jacobpretorius](https://github.com/jacobpretorius) (Jacob Pretorius) - CSV export JS fix (#14), click to open setting (#16)
- [@unqualifiedkoala](https://github.com/unqualifiedkoala) - Documented BLE adapter requirements
- [@dazzag24](https://github.com/dazzag24) - Reported macOS address format issue
- [@floese](https://github.com/floese) (W.A.Flozart) - Firefox doubleclick fix (#29)
- [@GeiserX](https://github.com/GeiserX) (Sergio Fernández) - Prometheus metrics exporter (#35), non-blocking vendor DB fix (#37), dual-adapter scanning (#33), robust scan recovery with rfkill (#40)

## License

MIT License - See [LICENSE](LICENSE) for details.

## Disclaimer

This tool is for educational purposes only. Be mindful of privacy laws in your jurisdiction when monitoring Bluetooth devices. The author is not responsible for any misuse of this software.

---

Created by [Danny McClelland](https://github.com/dannymcc)
