跳至正文

Zigbee / Z-Wave IoT

Overview

Zigbee and Z-Wave are wireless mesh protocols used in smart home and building IoT deployments. KYRA MDR collects device event logs from IoT gateways (Zigbee2MQTT, Home Assistant, Hubitat, SmartThings) to detect unauthorized device pairing, anomalous command patterns, and firmware tampering across IoT networks.

Prerequisites

  • KYRA MDR account (MDR tier or above)
  • KYRA Collector installed and reachable from the IoT gateway host
  • IoT gateway with logging capability:
    • Zigbee2MQTT (recommended for Zigbee monitoring)
    • Home Assistant with ZHA or Zigbee2MQTT integration
    • Hubitat Elevation hub
    • SmartThings hub
  • MQTT broker (Mosquitto or similar) if using Zigbee2MQTT

Configuration

Zigbee2MQTT provides the most detailed logging for Zigbee device monitoring.

Step 1: Configure Zigbee2MQTT Logging

Edit /opt/zigbee2mqtt/data/configuration.yaml:

# Zigbee2MQTT configuration
advanced:
log_level: info # debug, info, warn, error
log_output:
- console
- file
log_directory: /opt/zigbee2mqtt/data/log
log_rotation: true
log_symlink_current: true # symlink to current log file
# Security settings
network_key: GENERATE # auto-generate network encryption key
pan_id: GENERATE # auto-generate PAN ID
# Enable device join notifications
permit_join: false # disable open pairing by default
# MQTT settings
mqtt:
base_topic: zigbee2mqtt
server: mqtt://localhost:1883

Step 2: Subscribe to MQTT Bridge Events

The MQTT bridge publishes structured events to specific topics:

Terminal window
# Subscribe to all Zigbee2MQTT bridge events
mosquitto_sub -h localhost -t 'zigbee2mqtt/bridge/#' -v
# Key topics for security monitoring:
# zigbee2mqtt/bridge/event - device join, leave, interview
# zigbee2mqtt/bridge/log - general bridge logs
# zigbee2mqtt/bridge/state - bridge online/offline state
# zigbee2mqtt/bridge/devices - full device list on startup
# Subscribe to device-specific events
mosquitto_sub -h localhost -t 'zigbee2mqtt/+' -v

Example bridge event payloads:

// Device joined (zigbee2mqtt/bridge/event)
{"type":"device_joined","data":{"friendly_name":"0x00158d000XXXXXXX","ieee_address":"0x00158d000XXXXXXX"}}
// Device left (zigbee2mqtt/bridge/event)
{"type":"device_leave","data":{"ieee_address":"0x00158d000XXXXXXX","friendly_name":"living_room_sensor"}}
// Device interview completed
{"type":"device_interview","data":{"friendly_name":"new_device","status":"successful","ieee_address":"0x00158d000XXXXXXX"}}

Step 3: Forward MQTT Events to KYRA Collector

Create a log forwarder that subscribes to MQTT and sends to syslog:

/opt/kyra/zigbee-mqtt-forwarder.sh
#!/bin/bash
COLLECTOR="<COLLECTOR_IP>"
mosquitto_sub -h localhost -t 'zigbee2mqtt/bridge/event' -t 'zigbee2mqtt/bridge/log' | while read -r line; do
echo "$line" | logger -t zigbee2mqtt -n "$COLLECTOR" -P 514 --tcp
done
Terminal window
sudo chmod +x /opt/kyra/zigbee-mqtt-forwarder.sh
# Create systemd service
sudo tee /etc/systemd/system/kyra-zigbee-forwarder.service << 'EOF'
[Unit]
Description=KYRA Zigbee MQTT Log Forwarder
After=mosquitto.service zigbee2mqtt.service
[Service]
ExecStart=/opt/kyra/zigbee-mqtt-forwarder.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now kyra-zigbee-forwarder

Step 4: Forward Zigbee2MQTT File Logs via rsyslog

/etc/rsyslog.d/30-zigbee2mqtt.conf
module(load="imfile" PollingInterval="5")
input(type="imfile"
File="/opt/zigbee2mqtt/data/log/current/log.txt"
Tag="zigbee2mqtt"
Facility="local6"
Severity="info")
local6.* @@<COLLECTOR_IP>:514
Terminal window
sudo systemctl restart rsyslog

Option B: Home Assistant

Forward Home Assistant logs that include ZHA or Zigbee2MQTT events:

# Home Assistant configuration.yaml
logger:
default: warning
logs:
homeassistant.components.zha: info
homeassistant.components.mqtt: info
zigpy: info

Forward Home Assistant logs via rsyslog:

/etc/rsyslog.d/30-homeassistant.conf
module(load="imfile" PollingInterval="5")
input(type="imfile"
File="/config/home-assistant.log"
Tag="homeassistant"
Facility="local6"
Severity="info")
local6.* @@<COLLECTOR_IP>:514

Option C: Hubitat Elevation

Hubitat provides event logs via its built-in API:

Terminal window
# Get recent device events
curl -s "http://<HUBITAT_IP>/apps/api/<APP_ID>/devices/all?access_token=<TOKEN>" \
| jq '.[].name'
# Get events for a specific device
curl -s "http://<HUBITAT_IP>/apps/api/<APP_ID>/devices/<DEVICE_ID>/events?access_token=<TOKEN>" \
| jq '.[] | {name, value, date, deviceId}'

Create a periodic collection script:

#!/bin/bash
# /opt/kyra/hubitat-collector.sh - run via cron every 5 minutes
HUBITAT="http://<HUBITAT_IP>/apps/api/<APP_ID>"
TOKEN="<ACCESS_TOKEN>"
COLLECTOR="<COLLECTOR_IP>"
curl -s "$HUBITAT/devices/all/events?access_token=$TOKEN" \
| logger -t hubitat -n "$COLLECTOR" -P 514 --tcp

Verify on KYRA Collector

Terminal window
kyra-collector status
kyra-collector logs --source zigbee --tail 10

Collected Log Types

Log TypeDescriptionSecurity Use
Device JoinNew device pairing with IEEE address and modelUnauthorized device detection
Device LeaveDevice removal or loss of connectivityDevice inventory tracking
Device InterviewDevice capability discovery and endpoint enumerationNew device profiling
State ChangesDevice state transitions (on/off, open/close, motion)Anomalous behavior detection
Command EventsCommands sent to devices (set temperature, unlock door)Unauthorized control detection
Bridge StateGateway online/offline, coordinator statusGateway health monitoring
Network MapZigbee mesh routing table and link qualityNetwork integrity

Security-Critical IoT Events

EventIndicatorDescription
device_joined when permit_join: falseUnauthorized pairingDevice paired without explicit permission
Unknown IEEE address in device_joinedRogue devicePreviously unseen device on the network
device_leave for critical deviceTamperingSecurity sensor or lock removed from network
Rapid state changes on door lockLock manipulationPotential brute force or replay attack on smart lock
permit_join changed to true remotelyNetwork openedZigbee network opened for pairing without authorization
OTA update triggered for unknown firmwareFirmware tamperingUnauthorized firmware update pushed to devices
Bridge state offline unexpectedlyGateway attackZigbee coordinator taken offline

Z-Wave Specific Monitoring

Z-Wave hubs typically provide less granular logging. Key approaches:

GatewayLog SourceCollection Method
Z-Wave JS/var/log/zwave-js.logrsyslog file monitoring
SmartThingsSmartThings APIREST API polling
HubitatMaker APIREST API polling
Home Assistant Z-Wavehome-assistant.log with Z-Wave JS integrationrsyslog file monitoring

Troubleshooting

  • No MQTT events: Verify Zigbee2MQTT is running and connected to the MQTT broker. Check mosquitto_sub -t '#' -v to confirm MQTT is operational.
  • Missing device join events: Ensure permit_join was true when the device was paired. Join events are only logged during active pairing.
  • High volume from state changes: Motion sensors and temperature sensors generate frequent state updates. Filter to log only security-relevant devices (locks, alarms, cameras) if volume is excessive.
  • Zigbee2MQTT log file not found: Verify log_output includes file in configuration.yaml and the log_directory path exists with write permissions.
  • Z-Wave limited logging: Z-Wave protocol logging is inherently less detailed than Zigbee. Focus on gateway-level events (device join/leave, commands) rather than protocol-level data.
  • Network key exposure: The Zigbee network encryption key in configuration.yaml must be protected. Restrict file permissions: chmod 600 /opt/zigbee2mqtt/data/configuration.yaml.

Contact kyra@seekerslab.com for integration support.