feat(security): deploy OpenCanary honeypot on VLAN 50 with Gotify and Discord alerting
This commit is contained in:
251
scripts/deploy_opencanary.py
Normal file
251
scripts/deploy_opencanary.py
Normal file
@@ -0,0 +1,251 @@
|
||||
import paramiko
|
||||
import sys
|
||||
import json
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
key_path = r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet'
|
||||
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
c.connect("140.44.4.71", username="root", key_filename=key_path, timeout=10)
|
||||
|
||||
def run(cmd):
|
||||
stdin, stdout, stderr = c.exec_command(cmd)
|
||||
out = stdout.read().decode('utf-8', errors='ignore').strip()
|
||||
err = stderr.read().decode('utf-8', errors='ignore').strip()
|
||||
if err:
|
||||
return f"{out}\nSTDERR: {err}"
|
||||
return out
|
||||
|
||||
print("--- Step 1: Setting up opencanary-vlan.service ---")
|
||||
vlan_svc = """[Unit]
|
||||
Description=OpenCanary VLAN 50 Subinterface
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/sbin/ip link add link eth0 name eth0.50 type vlan id 50
|
||||
ExecStart=/sbin/ip link set eth0.50 up
|
||||
ExecStop=/sbin/ip link del eth0.50
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /etc/systemd/system/opencanary-vlan.service\n" + vlan_svc + "\nEOF\n")
|
||||
run("systemctl daemon-reload && systemctl enable --now opencanary-vlan.service")
|
||||
print("VLAN interface status:\n", run("ip -br link show eth0.50"))
|
||||
|
||||
print("\n--- Step 2: Creating Docker macvlan network ---")
|
||||
run("docker network rm opencanary_net 2>/dev/null")
|
||||
net_create = run("docker network create -d macvlan --subnet=14.4.4.0/25 --gateway=14.4.4.1 -o parent=eth0.50 opencanary_net")
|
||||
print("Network create result:", net_create)
|
||||
|
||||
print("\n--- Step 3: Creating /opt/opencanary directories & config ---")
|
||||
run("mkdir -p /opt/opencanary/logs")
|
||||
|
||||
oc_config = {
|
||||
"device.node_id": "snarfnet-honeypot-vlan50",
|
||||
"ip.ignorelist": [],
|
||||
"logtype.ignorelist": [],
|
||||
"git.enabled": True,
|
||||
"git.port": 9418,
|
||||
"ftp.enabled": True,
|
||||
"ftp.port": 21,
|
||||
"ftp.banner": "FTP server ready",
|
||||
"http.banner": "Apache/2.4.52 (Ubuntu)",
|
||||
"http.enabled": True,
|
||||
"http.port": 80,
|
||||
"http.skin": "nasLogin",
|
||||
"httpproxy.enabled": True,
|
||||
"httpproxy.port": 8080,
|
||||
"httpproxy.skin": "squid",
|
||||
"logger": {
|
||||
"class": "PyLogger",
|
||||
"kwargs": {
|
||||
"formatters": {
|
||||
"plain": {
|
||||
"format": "%(message)s"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
"file": {
|
||||
"class": "logging.FileHandler",
|
||||
"filename": "/var/tmp/opencanary.log"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql.enabled": True,
|
||||
"mysql.port": 3306,
|
||||
"mysql.banner": "5.7.42-0ubuntu0.18.04.1",
|
||||
"ssh.enabled": True,
|
||||
"ssh.port": 22,
|
||||
"ssh.version": "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10",
|
||||
"rdp.enabled": True,
|
||||
"rdp.port": 3389,
|
||||
"telnet.enabled": True,
|
||||
"telnet.port": 23,
|
||||
"telnet.banner": "\\r\\nUbuntu 22.04 LTS\\r\\nlogin: ",
|
||||
"mssql.enabled": True,
|
||||
"mssql.version": "2016",
|
||||
"mssql.port": 1433,
|
||||
"vnc.enabled": True,
|
||||
"vnc.port": 5000
|
||||
}
|
||||
|
||||
config_json = json.dumps(oc_config, indent=4)
|
||||
c.exec_command("cat << 'EOF' > /opt/opencanary/opencanary.conf\n" + config_json + "\nEOF\n")
|
||||
print("opencanary.conf written.")
|
||||
|
||||
print("\n--- Step 4: Creating Gotify Alert Watcher daemon ---")
|
||||
watcher_script = """#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
LOG_FILE = "/opt/opencanary/logs/opencanary.log"
|
||||
GOTIFY_URL = "http://127.0.0.1:8090/message?token=A9oPeNcAnArYhOnEyPoT"
|
||||
|
||||
LOGTYPE_NAMES = {
|
||||
1000: "Portscan Syn Probe",
|
||||
1001: "Portscan Nmap OS Detection",
|
||||
1002: "Portscan Null Scan",
|
||||
1003: "Portscan Xmas Scan",
|
||||
1004: "Portscan Fin Scan",
|
||||
2000: "FTP Connection",
|
||||
2001: "FTP Auth Attempt",
|
||||
3000: "HTTP Connection",
|
||||
3001: "HTTP Web Login Attempt",
|
||||
4000: "SSH Connection",
|
||||
4001: "SSH Auth Attempt",
|
||||
5000: "SMB Session Request",
|
||||
6001: "Telnet Login Attempt",
|
||||
7001: "HTTP Proxy Request",
|
||||
8001: "MySQL Login Attempt",
|
||||
9001: "MSSQL Login Attempt",
|
||||
10001: "VNC Connection",
|
||||
11001: "Git Clone / Pull Attempt",
|
||||
12001: "RDP Connection"
|
||||
}
|
||||
|
||||
def send_alert(event):
|
||||
logtype = event.get("logtype", 0)
|
||||
service_name = LOGTYPE_NAMES.get(logtype, f"Canary Event {logtype}")
|
||||
src_host = event.get("src_host", "Unknown IP")
|
||||
src_port = event.get("src_port", "Unknown Port")
|
||||
dst_port = event.get("dst_port", "")
|
||||
logdata = event.get("logdata", {})
|
||||
|
||||
title = f"🚨 [Honeypot Alert] {service_name} from {src_host}"
|
||||
|
||||
details = []
|
||||
details.append(f"• Attacker IP: {src_host}:{src_port}")
|
||||
if dst_port:
|
||||
details.append(f"• Targeted Port: {dst_port}")
|
||||
details.append(f"• Decoy IP: 14.4.4.99 (VLAN 50 Smart Home)")
|
||||
|
||||
if isinstance(logdata, dict):
|
||||
if "USERNAME" in logdata:
|
||||
details.append(f"• Username attempted: {logdata.get('USERNAME')}")
|
||||
if "PASSWORD" in logdata:
|
||||
details.append(f"• Password attempted: {logdata.get('PASSWORD')}")
|
||||
if "PATH" in logdata:
|
||||
details.append(f"• Path: {logdata.get('PATH')}")
|
||||
if "USERAGENT" in logdata:
|
||||
details.append(f"• User-Agent: {logdata.get('USERAGENT')}")
|
||||
elif logdata:
|
||||
details.append(f"• Payload: {str(logdata)[:200]}")
|
||||
|
||||
body = "\\n".join(details)
|
||||
|
||||
payload = {
|
||||
"title": title,
|
||||
"message": body,
|
||||
"priority": 8
|
||||
}
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(
|
||||
GOTIFY_URL,
|
||||
data=json.dumps(payload).encode('utf-8'),
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as r:
|
||||
pass
|
||||
print(f"[Alert Sent] {title}")
|
||||
except Exception as e:
|
||||
print(f"[Alert Error] {e}")
|
||||
|
||||
def main():
|
||||
print("OpenCanary Gotify Watcher started...")
|
||||
# Ensure log file exists
|
||||
if not os.path.exists(LOG_FILE):
|
||||
open(LOG_FILE, 'a').close()
|
||||
|
||||
with open(LOG_FILE, 'r') as f:
|
||||
# Seek to end on startup
|
||||
f.seek(0, os.SEEK_END)
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
time.sleep(0.5)
|
||||
continue
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
event = json.loads(line)
|
||||
send_alert(event)
|
||||
except Exception as e:
|
||||
# Non-JSON log line
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
"""
|
||||
|
||||
c.exec_command("cat << 'EOF' > /opt/opencanary/alert_watcher.py\n" + watcher_script + "\nEOF\n")
|
||||
run("chmod +x /opt/opencanary/alert_watcher.py")
|
||||
|
||||
watcher_svc = """[Unit]
|
||||
Description=OpenCanary Gotify Alert Watcher
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 /opt/opencanary/alert_watcher.py
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
"""
|
||||
c.exec_command("cat << 'EOF' > /etc/systemd/system/opencanary-watcher.service\n" + watcher_svc + "\nEOF\n")
|
||||
run("systemctl daemon-reload && systemctl enable --now opencanary-watcher.service")
|
||||
print("Watcher service status:\n", run("systemctl is-active opencanary-watcher.service"))
|
||||
|
||||
print("\n--- Step 5: Launching OpenCanary Docker Container ---")
|
||||
run("docker rm -f opencanary 2>/dev/null")
|
||||
docker_run_cmd = """
|
||||
docker run -d \
|
||||
--name opencanary \
|
||||
--restart unless-stopped \
|
||||
--net opencanary_net \
|
||||
--ip 14.4.4.99 \
|
||||
-v /opt/opencanary/opencanary.conf:/root/.opencanary.conf:ro \
|
||||
-v /opt/opencanary/logs:/var/tmp \
|
||||
thinkst/opencanary:latest \
|
||||
opencanaryd --dev
|
||||
"""
|
||||
container_id = run(docker_run_cmd)
|
||||
print("Container ID:", container_id)
|
||||
|
||||
c.close()
|
||||
|
||||
Reference in New Issue
Block a user