OpenCanary
↓ webhook
Home Assistant
├─ CSV log
├─ Event sensor
├─ Risk score per IP
├─ Detekce kompromitace
└─ Dashboard (tabulky + grafy)
apt install iptables python3 python3-pip python3-venv git -y
mkdir ~/opencanary
cd ~/opencanary
python3 -m venv venv
source venv/bin/activate
pip install opencanary
apt install -y build-essential libffi-dev pkg-config python3-dev libssl-dev libpcap-dev
pip install --upgrade pip setuptools wheel
pip install cffi
pip install opencanary
nano /etc/systemd/system/opencanary.service
systemctl daemon-reload
systemctl enable opencanary
systemctl start opencanary
systemctl status opencanary
systemctl status opencanary
nano ~/.opencanary.conf
opencanaryd --copyconfig
tail -f /var/log/opencanary.log
nano /etc/systemd/system/opencanary.service
nano /opt/opencanary/venv/bin/opencanaryd
nano /opt/opencanary/venv/bin/opencanaryd
nano /etc/opencanaryd/opencanary.conf
systemctl daemon-reload && systemctl restart opencanary && systemctl status opencanary
nano /etc/opencanaryd/opencanary.conf
nano /etc/systemd/system/opencanary.service
systemctl daemon-reload && systemctl restart opencanary && systemctl status opencanary
/opt/opencanary/venv/bin/opencanaryd --start
rm -rf /root/opencanary
mkdir -p /root/opencanary
cd /root/opencanary
python3 -m venv venv
/root/opencanary/venv/bin/python -m pip install --upgrade pip setuptools wheel
/root/opencanary/venv/bin/python -m pip install opencanary
ls -l /root/opencanary/venv/bin/opencanaryd
ls -l /root/opencanary/venv/bin/twistd
nano /etc/opencanaryd/opencanary.conf
nano /etc/systemd/system/opencanary.service
systemctl daemon-reload && systemctl restart opencanary && systemctl status opencanary
tail -f /var/log/opencanary.log
ss -tulnp
netstat -tulnp
python -m json.tool /etc/opencanaryd/opencanary.conf > /dev/null && systemctl daemon-reload && systemctl restart opencanary && systemctl status opencanary && journalctl -u opencanary -n 50
"logger": {
"class": "PyLogger",
"kwargs": {
"formatters": {
"plain": {
"format": "%(message)s"
}
},
"handlers": {
"file": {
"class": "logging.FileHandler",
"filename": "/var/log/opencanary.log"
},
"ha-webhook": {
"class": "opencanary.logger.WebhookHandler",
"url": "http://192.168.1.123:8123/api/webhook/opencanary",
"method": "POST",
"data": "%(message)s",
"headers": {
"Content-Type": "application/json"
},
"status_code": 200
}
}
}
}
[Unit]
Description=OpenCanary Honeypot Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/root/opencanary
# Spouštíme přímo Twisted server s TAC souborem
ExecStart=/root/opencanary/venv/bin/twistd -n -y /root/opencanary/venv/bin/opencanary.tac
Restart=always
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable opencanary.service
# ===============================
# ZÁKLADNÍ NASTAVENÍ HOME ASSISTANTU
# ===============================
homeassistant:
name: Domov
latitude: 0
longitude: 0
elevation: 0
unit_system: metric
time_zone: Europe/Prague
allowlist_external_dirs:
- "/media"
- "/media/opencanary"
default_config:
# Zápis do souboru
shell_command:
opencanary_zapis: '/config/opencanary_append.sh "{{ radek }}"'
# Čtení ze souboru (pro zobrazení v HA)
command_line:
- sensor:
name: "OpenCanary Last Events"
command: "tail -n 20 /media/opencanary/opencanary.csv"
scan_interval: 30
- sensor:
name: "OpenCanary Events"
unique_id: opencanary_events
command: "python3 /config/opencanary_reader.py"
scan_interval: 30
value_template: "{{ value_json.events | length }}"
json_attributes:
- events
# Pomocná entita pro dashboard
input_text:
opencanary_last_event:
name: "OpenCanary Last Event"
max: 255
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
- id: opencanary_webhook
alias: "OpenCanary – webhook handler"
mode: queued
max: 50
trigger:
- platform: webhook
webhook_id: opencanary
allowed_methods: [POST]
local_only: false
variables:
# Sjednocené parsování dat z OpenCanary
oc: >-
{% if trigger.json is mapping %}
{{ trigger.json }}
{% elif trigger.json is defined and trigger.json.message is defined %}
{{ trigger.json.message | from_json }}
{% else %}
{{ {} }}
{% endif %}
ts: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
src_ip: "{{ oc.get('src_host', 'N/A') }}"
dst_port: "{{ oc.get('dst_port', 'N/A') }}"
logtype: "{{ oc.get('logtype', 'N/A') }}"
action:
- service: system_log.write
data:
level: info
logger: custom_webhook_debug
message: >-
{% set p = trigger.json if trigger.json is mapping else trigger.json | from_json %}
Zdroj: {{ p.src_host | default('N/A') }}:{{ p.src_port | default('N/A') }}
→ Cíl: {{ p.dst_host | default('N/A') }}:{{ p.dst_port | default('N/A') }}
Typ: {{ p.logtype | default('N/A') }}
# 1. Zápis do CSV
- service: shell_command.opencanary_zapis
data:
#radek: "{{ ts }};{{ src_ip }};{{ dst_port }};{{ logtype }}"
radek: >
{% set payload = trigger.json if trigger.json is mapping else trigger.json | from_json %}
{{ payload.local_time_adjusted }};{{ payload.dst_port }};{{ payload.src_host }};{{ payload.src_port }};{{ payload.logdata.USERNAME }};{{ payload.logdata.PASSWORD }}
# 2. Aktualizace stavu (dashboard)
- service: input_text.set_value
target:
entity_id: input_text.opencanary_last_event
data:
value: >-
{% set p = trigger.json if trigger.json is mapping else trigger.json | from_json %}
{{ now().strftime('%Y-%m-%d %H:%M:%S') }} | IP: {{ p.src_host | default('N/A') }} | Port: {{ p.dst_port | default('N/A') }}
# 3. Notifikace do HA lišty
- service: persistent_notification.create
data:
title: "OpenCanary Logged"
message: >-
{% set p = trigger.json if trigger.json is mapping else trigger.json | from_json %}
Zdroj: {{ p.src_host | default('N/A') }}:{{ p.src_port | default('N/A') }}
→ Cíl: {{ p.dst_host | default('N/A') }}:{{ p.dst_port | default('N/A') }}
Typ: {{ p.logtype | default('N/A') }}
/config/opencanary_append.sh chmod +x /config/opencanary_append.sh
#!/bin/sh
# 1. argument = celý řádek
printf '%s\n' "$1" >> /media/opencanary/opencanary.csv
/config/opencanary_reader.py
import json
import os
path = "/media/opencanary/opencanary.csv"
events = []
if os.path.exists(path):
with open(path, "r", encoding="utf-8", errors="replace") as f:
for line in f:
line = line.strip()
if not line:
continue
parts = line.split(";")
# bezpečně doplníme na 6 položek
while len(parts) < 6:
parts.append("")
ts, dst_port, src_ip, src_port, user_or_pass, extra = parts[:6]
events.append({
"ts": ts,
"dst_port": dst_port,
"src_ip": src_ip,
"src_port": src_port,
"val1": user_or_pass,
"val2": extra,
"raw": line,
})
print(json.dumps({"events": events}, ensure_ascii=False))
type: custom:flex-table-card
title: OpenCanary (poslední události)
entities:
include:
- sensor.opencanary_events
max_rows: 50
columns:
- name: Čas
data: events
modify: x.ts
- name: Dst port
data: events
modify: x.dst_port
- name: Src IP
data: events
modify: x.src_ip
- name: Src port
data: events
modify: x.src_port
- name: Val1
data: events
modify: x.val1
- name: Val2
data: events
modify: x.val2
Zkontroluj zda z RPI je odesíláno na Home assistenta
tcpdump -ni any host 192.168.x.x and port 8123