204 Commits

Author SHA1 Message Date
Cobra 3153b7e8a3 Robust interface detection — retry fallback chain for headless boot (#206)
Fixes interface auto-detection failures on Pi Zero 2W where wlan0 doesn't exist
at boot. Implementation:

- Added detect_interface_with_retry() function with 3x retry fallback chain
- Config-supplied interface preferred, then /proc/net/route, then UP interface
- Exponential backoff: 5s, 10s, 20s delays between retries
- Filters excluded prefixes: lo, tailscale*, wg*, tun*, docker*, veth*, br-*
- Used in Engine.__init__(), PacketCapture.start(), MacManager.start()
- Full test coverage: 10 tests for detection, backoff, filtering

Addresses issue where network stack initializes after boot and interfaces
become available after 5-10 second delay.
2026-04-08 20:58:43 -04:00
Cobra 1f43d97f03 Add test to verify Engine instantiates and injects CaptureBus into passive modules (#204) 2026-04-08 20:57:10 -04:00
Cobra 967fac5ce5 Enrich net_alerter alerts with OUI vendor and reverse DNS hostname
Parse nmap vendor name from MAC Address line (filtering out 'Unknown').
Fall back to socket.gethostbyaddr for IPs nmap didn't resolve a hostname
for. Alert label is now: 'hostname (vendor)' | 'hostname' | 'vendor' |
'unknown', in that priority order.
2026-04-08 20:31:49 -04:00
Cobra d9c27eaf66 Fix Cloudflare bot detection blocking net_alerter Matrix sends
urllib's default Python-urllib user agent is flagged by Cloudflare Bot
Fight Mode (error 1010) when m.example.org homeserver sits behind
Cloudflare. Add a browser-like User-Agent to Matrix PUT/POST requests so
Cloudflare passes the traffic through.
2026-04-08 20:19:24 -04:00
Cobra 019a96b205 Fix flash bugs: remove netplan wifi conflict, suppress eth default route, force IPv4 for Tailscale install
- Remove 20-wifi.yaml netplan block (Bug 1): causes netplan to spawn its own wpa_supplicant instance, which claims ctrl_iface and blocks wpa_supplicant@wlan0.service. The per-interface systemd service is the correct approach.
- Add cleanup line to remove any pre-existing 20-wifi.yaml from the Armbian image.
- Patch 10-dhcp-all-interfaces.yaml to suppress default route on ethernet (Bug 2): without this, ethernet DHCP default route metric 100 beats WiFi metric 1024, routing internet traffic to ethernet which has no upstream. Causes Tailscale and firstboot to fail.
- Force IPv4 resolution in Tailscale curl (Bug 3): some homelab/ISP networks lack IPv6 internet routes. IPv6 DNS resolution for tailscale.com causes immediate curl failure on first boot.
2026-04-08 19:37:38 -04:00
Cobra 248ba78e15 Fix WiFi: enable wpa_supplicant@wlan0 — instance was never linked 2026-04-08 15:56:48 -04:00
Cobra 334f9830e1 Replace .bigbrother with .implant in all identity strings — avoid tool name exposure on fresh flash 2026-04-08 14:08:00 -04:00
Cobra e114d6067a Remove autossh reverse tunnel references — module deleted, causing ImportError on startup 2026-04-08 14:07:52 -04:00
Cobra 1dbcb6aad3 Wire net_alerter cron into setup.sh — reads bb-config.env, seeds baseline on first boot 2026-04-08 13:50:58 -04:00
Cobra b0fd5865cc Make binary downloads non-fatal and add force-confold for nftables conffile prompt 2026-04-08 12:22:25 -04:00
Cobra 3cdccbf47d Fix WiFi conflict and SSH accessibility on fresh flash
- Remove wpa_supplicant@wlan0.service enablement: Netplan spawns its own
  wpa_supplicant instance, enabling the @wlan0 unit creates a second one
  that fights for the socket, causing WiFi instability and SSH drops
- Write /etc/nftables.conf to card at flash time: Armbian bookworm default
  nftables policy drops all input; SSH was unreachable despite sshd running.
  Ruleset allows established, loopback, ICMP, and TCP/22 only

Fixes DevTrack #317 and #295
2026-04-08 11:08:02 -04:00
Cobra 90c26ae24d Fix firstboot service startup: GOPATH env, enable all services, add bettercap passive caplet
- Set HOME/GOPATH/GOMODCACHE before go install kerbrute on arm64 to fix
  'module cache not found' abort that prevented --enable-service from running
- Enable bigbrother-capture, bigbrother-watchdog, and bettercap.service
  in --enable-service block (previously only bigbrother-core was enabled)
- Add services/bettercap.service: runs passive_recon.cap with net.recon +
  net.sniff + events.stream instead of idle api.rest only
- bettercap.service depends on bigbrother-core to ensure engine is up first

Fixes DevTrack #311 and #312
2026-04-08 10:51:09 -04:00
Cobra d66b547045 Fix wpa_supplicant conflict and firstboot robustness
- Remove generic wpa_supplicant.service symlink when wpa_supplicant@wlan0 is enabled — both services fight over wlan0 causing WiFi instability and SSH drops
- Add udev rule to disable WiFi power saving (aw859a drops connections under load with power save on)
- Drop set -e from firstboot script so a failing step does not kill the whole run
- Guard setup.sh call — skip gracefully if not present (dev/test scenario)

Fixes #295 and #296
2026-04-07 21:50:51 -04:00
Cobra 1803c54182 Switch WiFi config from NetworkManager to Netplan+wpa_supplicant
Armbian minimal uses systemd-networkd+wpa_supplicant via Netplan, not NM.
Write Netplan YAML, wpa_supplicant-wlan0.conf, and networkd .network file.
Enable wpa_supplicant@wlan0.service via symlink if template exists.
2026-04-07 17:02:36 -04:00
Cobra d2f4f9759d Fix SD flash mounting wrong partition — Armbian p1=boot p2=rootfs
WiFi, SSH keys, root password, firstboot service were all being written to
the FAT32 boot partition (p1) instead of the ext4 rootfs (p2). Detect the
ext4 partition by filesystem type and mount that as MOUNT_POINT.
2026-04-07 16:44:22 -04:00
Cobra 61a1756dae Fix mktemp overwrite prompt in autossh tunnel keygen 2026-04-07 15:56:59 -04:00
Cobra 56ad5662ac Fix ssh-keygen overwrite prompt and key landing in root home
mktemp creates the file before ssh-keygen runs — keygen sees it exists
and prompts. Switch to mktemp -d so keygen writes a fresh file.

When run via sudo SUDO_USER is set but HOME=/root. Resolve the real
home via getent so the key lands in the operator's ~/.ssh, not root's.
2026-04-07 15:47:31 -04:00
Cobra 6cb48909b2 Save generated SSH key locally to ~/.ssh/bb-<device_id>
Infisical is the backup copy. Local key at a predictable path means
no hunting — ssh -i ~/.ssh/bb-<device_id> just works.
2026-04-07 15:22:55 -04:00
Cobra 42c05f37e6 Fix ANSI rendering and Infisical key storage in operator wizard
echo calls in summary/final sections were missing -e flag so ANSI
escape codes printed literally instead of rendering.

Infisical SSH key storage was targeting a non-existent 'bigbrother'
folder, silently failing to store the private key. Removed folder
argument so keys store at root where creds CLI can retrieve them.
2026-04-07 15:22:16 -04:00
Cobra e00769631a Remove homeserver default — no infrastructure fingerprints in wizard 2026-04-07 14:56:46 -04:00
Cobra 4c332eabb4 Proper Matrix alerter support with client API
Matrix doesn't use a simple webhook URL — needs homeserver, room ID,
and bot token separately. Uses PUT /_matrix/client/v3/rooms/.../send
with Bearer token auth. Room ID is bash-encoded (! → %21, : → %3A)
to avoid Python dependency pre-setup. Also adds ntfy and plain
webhook as options under a typed alerter menu.
2026-04-07 14:55:23 -04:00
Cobra 84f0775f76 Align device ID with MAC profile OUI for consistent network identity
Device ID is now a MAC-format hex string (12 chars) using the same
OUI as the randomly selected device profile. If the device gets an
Amazon OUI for its MAC, the device ID starts with fc65de. Hostname,
MAC, and device ID all point to the same vendor — no inconsistency
for anyone watching the network.
2026-04-07 14:48:22 -04:00
Cobra d8de49a53d Remove bb- prefix from device ID default
bb- prefix is a tool fingerprint — visible in Infisical key names,
alerter payloads, and config files on the device. Default is now
a plain 10-char hex string with no identifying prefix.
2026-04-07 14:44:59 -04:00
Cobra af124cc6d0 Default VPN to Tailscale, add auth key expiry warning
Tailscale handles NAT traversal automatically via DERP relay — more
reliable than WireGuard for devices landing on unknown networks.
Add reminder to use reusable non-expiring keys for long-term drops.
2026-04-07 14:41:17 -04:00
Cobra b0fb5af1fb Include device IP and hostname in firstboot alerter beacon
Blind drops need some way to locate the device when no VPN is selected.
Alerter now reports public IP (via ipify) with fallback to local IP,
plus hostname — gives enough info to SSH directly on same-network drops.
2026-04-07 14:37:04 -04:00
Cobra 2b00b28de6 Add reverse SSH tunnel (autossh) as VPN option in operator wizard
Generates a dedicated tunnel keypair during setup, prints public key
for operator to pre-stage on server, writes private key to SD card.
On first boot: installs autossh, writes bb-tunnel.service with
correct RemoteForward and reconnect settings. Zero network traffic
until operator initiates connection through the tunnel port.
2026-04-07 14:30:10 -04:00
Cobra ae79d64913 Align default hostname with MAC device profiles for OPSEC consistency 2026-04-07 14:19:55 -04:00
Cobra 2b53da80d0 Fix wizard: defaults for all prompts, random hostname/device-id, download robustness
- Add prompt_default() helper: shows defaults, accepts Enter to use them
- WiFi: default=n (skip), keeps passphrase prompt loop
- Root password: auto-generate with openssl, show in summary if used, operator can override
- SSH key: default=1 (generate new)
- Device ID: auto-generate bb-<8-char-uuid>
- Boot mode: default=1 (passive)
- VPN: default=1 (none)
- Hostname: NEW section with auto-generated node-<6-char-uuid> default
- Alerter: default=n (disabled)
- Download: use curl -L (no -f), verify file exists and >50MB
- Config summary: show hostname, mask password (show auto-generated clearly)
- Apply config: write BB_HOSTNAME to /etc/hostname and /etc/hosts
- No eval with user input: use printf -v for variable assignment
2026-04-07 14:17:01 -04:00
Cobra ae35f3f7b8 Fix HOME path when run via sudo — use SUDO_USER's home not /root 2026-04-07 14:12:07 -04:00
Cobra 6f2a6dacea Fix SCRIPT_DIR path now that operator_setup.sh is at repo root 2026-04-07 14:05:36 -04:00
Cobra 8e7e3fe91d Move operator_setup.sh to repo root for direct access 2026-04-07 14:05:12 -04:00
Cobra ab34023c51 Fix set -e crash in image detection and device selection
ls glob on empty cache dir exits non-zero and kills script under
set -euo pipefail. Switched to find which exits 0 on no matches.
Same fix for grep|sed pipeline in device selection; added empty
DEVICE guard.
2026-04-07 14:02:32 -04:00
Cobra 0e49eb914e Add operator SD setup wizard: flash, configure, first-boot autonomy
Single script covers full drop implant prep: image download and flash,
WiFi (with UUID fix), per-device SSH keygen to Infisical, mode selection,
VPN (Tailscale/WireGuard), network alerter webhook, and first-boot service.
Insert card, power on, walk away.
2026-04-07 13:58:01 -04:00
Cobra 5e5f88d6cb Full autonomous first-boot: fix WiFi UUID, self-installing setup
WiFi keyfiles require UUID or NM silently ignores them — that was why
WiFi never connected. Rewrote preconfig_sd.sh to:
- Generate UUID for NM keyfile
- Copy BB source to /root/bb-src/ on the card
- Install bb-firstboot.service that runs setup.sh --enable-service
  after network-online.target, then disables itself
- Per-device keygen, private key to Infisical

Single command now produces a card that boots and self-installs.
2026-04-07 13:45:04 -04:00
Cobra e1f937f42c Generate per-device SSH keypair instead of copying operator keys
Each device gets a unique ed25519 keypair generated at preconfig time.
Private key goes to Infisical (bigbrother/SSH_PRIVKEY_<ID>), public key
to the SD card only. No operator keys or identifying comments on device.
2026-04-07 13:42:45 -04:00
Cobra 77aac72d31 Strip SSH key comments on deploy; add preconfig_sd.sh
Copying authorized_keys verbatim onto a drop implant leaks internal hostnames,
usernames, and tool names in key comments. preconfig_sd.sh now strips all
comments (awk '{print $1,$2}') when writing keys to SD card. deploy.sh adds
the same strip step on the live device as a safety net.
2026-04-07 13:41:44 -04:00
Cobra 8037462276 Randomize system hostname from device profile to match MAC identity 2026-04-07 13:33:54 -04:00
Cobra 7070f6548c Add reimage bootstrap: deploy.sh, setup_wifi.sh, fix setup.sh enable/reinstall, idempotent DB inserts 2026-04-07 13:20:15 -04:00
Cobra 0f754cfb7f Fix DB table/column mismatch and stale PID noise on startup
build_data.py created 'profiles' but mac_manager queries 'mac_profiles'.
Columns category/model renamed to device_type/device_name. device_type
values aligned with _CATEGORY_MAP in mac_manager (streaming, smart_tv,
phone, tablet, smart_speaker, iot, printer, gaming).

ja3_fingerprints.db table renamed from 'fingerprints' to 'ja3_profiles'
and expanded with all columns ja3_spoofer queries (name, description,
cipher_suites, extensions, elliptic_curves, ec_point_formats as JSON).

StateManager.reset_module_status() clears stale 'running' entries on
startup so watchdog doesn't flag old-session PIDs as dead modules.
Engine.start_all() calls reset before launch and does a 3s post-startup
liveness check, logging any modules that crashed immediately after fork.
2026-04-07 13:05:31 -04:00
Cobra e15e077be8 Skip MAC rotation on active WiFi interfaces to prevent ENETDOWN
When wlan0 is the primary data interface (WiFi-only deployment), changing
its MAC via SIOCSIFHWADDR drops the AP association and puts all AF_PACKET
sockets into ENETDOWN permanently until wpa_supplicant re-associates.

- _apply_profile: skip set_mac if _eth_iface is a WiFi interface
- _apply_profile: skip WiFi set_mac if _wifi_iface == _eth_iface (same card)
- stop: mirror the same skip logic for MAC restoration

DHCP hostname + TCP stack tuning still applied for blending on WiFi-only nodes.
2026-04-07 12:48:56 -04:00
Cobra 7f58f1cab3 Fix StateManager deadlock with explicit BEGIN IMMEDIATE + retry
with conn: context manager in Python sqlite3 doesn't respect busy_timeout
for the implicit BEGIN; under concurrent subprocess writes the transaction
would fail immediately. Replace with explicit BEGIN IMMEDIATE + retry loop
(6 attempts, 0.5s back-off) to handle WAL write contention.
2026-04-07 12:23:38 -04:00
Cobra a8b81f38c9 Fix credential_db schema conflict and add resilience
credential_sniffer and credential_db both wrote to the same credentials.db
with different schemas; credential_db's executescript failed when creating
the crack_status index on an existing table that lacked that column.

Fix: split credential_db's schema init into table DDL + migration + indexes
so missing columns are added before index creation runs. Migration also
handles any future schema drift.

state.py: add 30s timeout + busy_timeout PRAGMA to write connection so
concurrent subprocess writes stop failing with 'database is locked'.

capture_bus.py: reconnect on ENETDOWN instead of aborting the capture
loop — mac_manager temporarily brings the interface down during MAC
rotation which was silently killing all packet capture.
2026-04-07 12:19:56 -04:00
Cobra 1f0e3ee79a Cap stealth/intel/connectivity modules on Pi3B tier to prevent OOM
- Add max_stealth: 3 and max_other: 4 limits to pi3b tier in HARDWARE_TIERS
- Enforce those caps in _tier_allows() for stealth and intel+connectivity modules
- Disable heavy passive modules: vlan_discovery, network_mapper, auth_flow_tracker, smb_monitor, cloud_token_harvester, ldap_harvester, rdp_monitor, quic_analyzer
- Disable heavy stealth modules: lkm_rootkit, ids_tester, ja3_spoofer, overlayfs_manager, encrypted_storage, anti_forensics, traffic_mimicry
- Disable heavy intel modules: supply_chain_detect, security_posture, tool_output_parser, topology_mapper, user_timeline, net_intel
- Disable heavy connectivity modules: ble_emergency, cellular_backup, bridge, wireguard, wifi_client

On Pi 3B (1GB RAM, 700MB budget), this prevents 35+ subprocesses spawning and causing OOM crashes. Keeps lightweight modules running: dns_logger, tls_sni_extractor, credential_sniffer, host_discovery, os_fingerprint, traffic_analyzer, packet_capture, mac_manager, process_disguise, log_suppression, tmpfs_manager, watchdog, credential_db, change_detector, operator_audit, tailscale, data_exfil.
2026-04-06 22:44:52 -04:00
Cobra 7442dc24dd Fix CaptureBus cross-fork visibility — restart reader in each module subprocess
With multiprocessing fork, threads are not inherited. The parent's
CaptureBus reader thread runs in the parent but module subprocesses
subscribe AFTER fork, so their SubscriberQueue entries are added to
a child-local copy of _subscribers that the parent reader never sees.

Fix: reset and restart CaptureBus in each module subprocess so it
has its own reader thread on the inherited AF_PACKET socket. Each
module gets independent packet delivery. Linux AF_PACKET allows
multiple readers on the same interface.
2026-04-06 22:12:26 -04:00
Cobra 5be7fcf6d4 Fix module subprocess lifecycle and capture_bus injection bugs
Three bugs causing all modules to exit within seconds of startup:

1. _module_runner had no keep-alive loop after calling module.start().
   All modules use a thread-spawning pattern where start() returns
   immediately, so the subprocess exited and killed all daemon threads.
   Added while module._running: sleep(1) loop to block until stop().

2. Engine injected capture_bus under key 'capture_bus' but 9 modules
   (auth_flow_tracker, cloud_token_harvester, ldap_harvester, network_mapper,
   rdp_monitor, quic_analyzer, smb_monitor, db_interceptor, vlan_discovery)
   look for '_capture_bus'. Inject both keys so all modules get it.

3. mac_manager crashes on startup when innocuous_macs.db exists but has
   no mac_profiles table (DB not yet seeded). Added OperationalError
   handler to fall back to random OUI instead of crashing.
2026-04-06 21:57:30 -04:00
Cobra 78738622eb Securely wipe state.db on exit (#216)
- Add secure_wipe_file() to utils/crypto.py for file overwrites + deletion
- Add secure_wipe parameter to StateManager.stop() method
- Wipes all SQLite WAL files (.db, .db-wal, .db-shm) with 3 passes
- Normal exit now calls state.stop(secure_wipe=True) to clear state database
- Falls back to regular delete if secure wipe fails
- Prevents state.db from persisting on disk after shutdown
2026-04-06 11:44:44 -04:00
Cobra edf2ea7c36 Encrypt sensitive credential fields before event bus emission (#215)
- Add encrypt_credential_dict() and decrypt_credential_field() to utils/crypto.py
- Create utils/credential_encryption.py with encryption/decryption helpers
- Add get_credential_encryption_key() to retrieve key from Infisical at runtime
- Add emit_credential_found() wrapper for modules to use instead of direct bus.emit()
- Update all 15 modules emitting CREDENTIAL_FOUND to use encrypted wrapper
- Update 4 modules consuming CREDENTIAL_FOUND to decrypt payload before processing
- Sensitive fields (username, password, hash, token, etc.) encrypted with AES-256-GCM
- Falls back to plaintext if encryption key unavailable or encryption fails
2026-04-06 11:43:46 -04:00
Cobra f15b8994cd Fix #214: Prevent ToolManager crash callback deadlock
- Move crash_callback execution outside of self._lock
- Callback is called after releasing the monitor lock
- Re-acquire lock only for restart decision logic
- Prevents deadlock if callback tries to acquire same lock
- Maintains thread safety for restart and process state updates
2026-04-06 11:40:36 -04:00
Cobra 1b93378f02 Fix #213: Guard BIGBROTHER_DESIGN.md from deployment
- Add BIGBROTHER_DESIGN.md to .gitignore (prevent accidental commits)
- Remove from git tracking (already committed, but won't be in future releases)
- Design document contains sensitive operational details
- Prevents disclosure of architecture during implant extraction
2026-04-06 11:40:03 -04:00
Cobra 50deaf0cfb Fix #212: Remove autossh reverse tunnel module
- Delete modules/connectivity/reverse_tunnel.py (contradicts design)
- BigBrother design specifies WireGuard-only operator access
- Reverse SSH tunnel introduces unnecessary complexity and OPSEC risk
- Operator access is now exclusively through WireGuard VPN per spec
2026-04-06 11:39:56 -04:00