#!/usr/bin/env bash
# ═══════════════════════════════════════════════════════════════════════
# UniSOC Honeypot — Install PRO v2 (Cowrie + xrdp + medium-interaction)
# ═══════════════════════════════════════════════════════════════════════
#
# Composants :
#   1. SSH admin → port 22222 (au lieu de 22)
#   2. Cowrie SSH+Telnet medium-interaction (ports 22 + 23)
#      → faux shell, ~120 commandes émulées, capture wget/curl payloads
#      → userdb cohérent avec les faux fichiers Mots-de-passe-admin.docx
#      → /root/.bash_history préchargé pour donner des pistes
#   3. xrdp + XFCE thémé Windows-like (port 3389)
#      → user admin/admin login → vrai desktop avec icônes Veeam/Comptes/Schémas
#      → capture session : ffmpeg vidéo + screenshots toutes les 5s
#   4. Faux Veeam Backup v10 HTTPS (port 443) + cert auto-signé
#   5. Faux ProFTPD 1.3.5 (port 21) — CVE-2015-3306 simulée
#   6. Samba avec audit + 4 partages (Comptabilite/Informatique/RH/Direction)
#   7. ~250 fichiers leurres réalistes (Excel/PDF/Word avec canary tokens)
#   8. inotify watcher sur /srv/samba et /srv/ftp
#   9. SSH tarpit port 26 (ralentit brute force)
#  10. OpenCanary fake services (MSSQL:1433 MySQL:3306 VNC:5900 Redis:6379)
#
# Usage :
#   curl -sL https://client.unisoc.fr/downloads/honeypot/install-pro-v2.sh | bash
set -euo pipefail

LOG=/var/log/unisoc-canary-install.log
exec > >(tee -a "$LOG") 2>&1
echo "[$(date -u +%FT%TZ)] === UniSOC Canary PRO v2 install start ==="

if [ "$(id -u)" -ne 0 ]; then
    echo "ERREUR : exécuter en root"; exit 1
fi
export DEBIAN_FRONTEND=noninteractive

# ───────────────────────────────────────────────────────────────────────
# 1. Dépendances
# ───────────────────────────────────────────────────────────────────────
echo "[1/11] Dépendances système..."
apt-get update
apt-get install -y --no-install-recommends \
    python3 python3-pip python3-venv python3-pyasn1-modules \
    python3-openpyxl python3-docx python3-reportlab \
    rsyslog libssl-dev libffi-dev libpcap-dev build-essential sudo \
    samba samba-vfs-modules \
    xrdp xfce4 xfce4-goodies xfce4-terminal dbus-x11 \
    xorg xserver-xorg-video-dummy \
    ffmpeg xdotool xinput \
    libreoffice-writer libreoffice-calc \
    firefox-esr feh fonts-liberation \
    git curl jq ca-certificates iproute2 \
    inotify-tools \
    chrony at

# NTP synchronisation : tous les events doivent être eurodatés cohérents avec le SOC.
# Source primaire : ntp.unisoc.fr (notre serveur dédié pour cohérence cross-tenants).
# Fallbacks publics au cas où ntp.unisoc.fr est down (résilience).
cat > /etc/chrony/conf.d/unisoc.conf <<'EOF'
# UniSOC honeypot — synchro horloge (cohérence ts SOC = critique pour corrélation)
# Primary : serveur NTP UniSOC (chrony Stratum 4)
server ntp.unisoc.fr iburst prefer
# Fallbacks publics (si ntp.unisoc.fr inaccessible)
server time.cloudflare.com iburst
pool pool.ntp.org iburst maxsources 3
makestep 1.0 3
rtcsync
EOF
systemctl enable --now chrony 2>/dev/null || systemctl enable --now chronyd 2>/dev/null || true

# ───────────────────────────────────────────────────────────────────────
# 2. SSH admin → port 22222
# ───────────────────────────────────────────────────────────────────────
echo "[2/11] SSH admin → port 22222..."
sed -i -E 's/^[#]?Port .+/Port 22222/' /etc/ssh/sshd_config
grep -q "^Port 22222" /etc/ssh/sshd_config || echo "Port 22222" >> /etc/ssh/sshd_config
systemctl restart ssh

# ───────────────────────────────────────────────────────────────────────
# 3. OpenCanary (services NON couverts par Cowrie/xrdp/Veeam/Samba)
# ───────────────────────────────────────────────────────────────────────
echo "[3/11] OpenCanary (services périphériques)..."
id -u opencanary >/dev/null 2>&1 || useradd --system --create-home --shell /bin/false opencanary
if [ ! -d /opt/opencanary/venv ]; then
    python3 -m venv /opt/opencanary/venv
    /opt/opencanary/venv/bin/pip install --upgrade pip --quiet
    # opencanary core - obligatoire
    /opt/opencanary/venv/bin/pip install --quiet opencanary
    # scapy + pcapy-ng requièrent libpcap-dev — best-effort, ne casse pas l'install
    /opt/opencanary/venv/bin/pip install --quiet scapy 2>/dev/null || echo "  scapy install KO (non bloquant)"
    /opt/opencanary/venv/bin/pip install --quiet pcapy-ng 2>/dev/null || echo "  pcapy-ng install KO (non bloquant)"
fi

mkdir -p /etc/opencanary /var/log/opencanary
HOSTNAME_FAKE="${HOSTNAME:-srvdomaine}"
cat > /etc/opencanary/opencanaryd.conf <<EOF
{
    "device.node_id": "unisoc-canary-${HOSTNAME_FAKE}",
    "ip.ignorelist": [],
    "git.enabled": false,
    "ftp.enabled": false,
    "http.enabled": false,
    "https.enabled": false,
    "ssh.enabled": false,
    "smb.enabled": false,
    "telnet.enabled": false,
    "mysql.enabled": true, "mysql.port": 3306,
    "mssql.enabled": true, "mssql.port": 1433,
    "redis.enabled": true, "redis.port": 6379,
    "vnc.enabled": true, "vnc.port": 5900,
    "snmp.enabled": false,
    "logger": {"class": "PyLogger", "kwargs": {"handlers": {
        "file": {"class": "logging.FileHandler", "filename": "/var/log/opencanary/opencanary.log"}
    }}}
}
EOF
chown -R opencanary:opencanary /var/log/opencanary /etc/opencanary

# OpenCanary cherche son config dans /etc/opencanaryd/opencanary.conf (note le 'd' sur le dir)
mkdir -p /etc/opencanaryd
cp /etc/opencanary/opencanaryd.conf /etc/opencanaryd/opencanary.conf

# On bypass le wrapper opencanaryd (qui appelle sudo et casse en non-root) — twistd direct
cat > /etc/systemd/system/opencanary.service <<'EOF'
[Unit]
Description=UniSOC OpenCanary
After=network-online.target

[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/opt/opencanary
ExecStart=/opt/opencanary/venv/bin/twistd --nodaemon --pidfile= --umask=0022 --uid=opencanary --gid=opencanary -y /opt/opencanary/venv/bin/opencanary.tac
Restart=always
RestartSec=10
ReadWritePaths=/var/log/opencanary
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
EOF

# ───────────────────────────────────────────────────────────────────────
# 4. Cowrie SSH/Telnet medium-interaction
# ───────────────────────────────────────────────────────────────────────
echo "[4/11] Cowrie SSH/Telnet medium-interaction..."

# Free up ports 22 + 23 (en plus du SSH déjà déplacé sur 22222)
# Le sshd écoute sur 22222 maintenant, donc 22 est libre.

if ! id -u cowrie >/dev/null 2>&1; then
    useradd --system --home-dir /opt/cowrie --create-home --shell /bin/bash cowrie
fi

if [ ! -d /opt/cowrie/cowrie-env ]; then
    # Le user cowrie a /opt/cowrie comme home → on retire ce home, on clone à la place.
    rm -rf /opt/cowrie
    cd /opt
    git clone --depth 1 https://github.com/cowrie/cowrie.git cowrie 2>&1 | tail -3
    chown -R cowrie:cowrie /opt/cowrie
    cd /opt/cowrie
    runuser -u cowrie -- python3 -m venv cowrie-env
    runuser -u cowrie -- /opt/cowrie/cowrie-env/bin/pip install --upgrade pip --quiet
    runuser -u cowrie -- /opt/cowrie/cowrie-env/bin/pip install --quiet -r requirements.txt
    # Pip install editable pour enregistrer cowrie comme plugin twistd (sinon "Unknown command: cowrie")
    runuser -u cowrie -- /opt/cowrie/cowrie-env/bin/pip install --quiet -e /opt/cowrie
fi

# Conf Cowrie : SSH:22 Telnet:23, hostname srvdomaine
cat > /opt/cowrie/etc/cowrie.cfg <<EOF
[honeypot]
hostname = srvdomaine
log_path = /var/log/cowrie
download_path = /var/log/cowrie/downloads
share_path = /opt/cowrie/share/cowrie
state_path = /opt/cowrie/var/lib/cowrie
etc_path = /opt/cowrie/etc
contents_path = /opt/cowrie/honeyfs
txtcmds_path = /opt/cowrie/share/cowrie/txtcmds
ttylog = true
ttylog_path = /var/log/cowrie/tty
auth_class = UserDB
data_path = /opt/cowrie/var/lib/cowrie
backend = shell

[shell]
filesystem = /opt/cowrie/share/cowrie/fs.pickle
processes = /opt/cowrie/share/cowrie/cmdoutput.json
arch = linux-x64-lsb
kernel_version = 5.15.0-89-generic
kernel_build_string = #99-Ubuntu SMP Thu Sep 14 15:32:37 UTC 2023
hardware_platform = x86_64
operating_system = GNU/Linux

[ssh]
enabled = true
listen_endpoints = tcp:22:interface=0.0.0.0
version = SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6
sftp_enabled = true
forwarding = true

[telnet]
enabled = true
listen_endpoints = tcp:23:interface=0.0.0.0

[output_jsonlog]
enabled = true
logfile = /var/log/cowrie/cowrie.json
epoch_timestamp = false

[output_textlog]
enabled = true
logfile = /var/log/cowrie/cowrie.log
EOF
chown cowrie:cowrie /opt/cowrie/etc/cowrie.cfg

# Userdb cohérent avec Mots-de-passe-admin.docx + dico bot top
cat > /opt/cowrie/etc/userdb.txt <<'EOF'
admin:x:admin
admin:x:admin1234
admin:x:Tagada000
admin:x:Password1
admin:x:1234
admin:x:Admin@123
root:x:root
root:x:toor
root:x:123456
root:x:admin
root:x:Password1
root:x:!root
root:x:P@ssw0rd
Administrateur:x:P@ssw0rd-AD-2024!
veeam_admin:x:V33m!Backup#2025
sa:x:S@P-2024!Pwd
oracle:x:oracle
postgres:x:postgres
mysql:x:mysql
test:x:test
ftp:x:ftp
ubnt:x:ubnt
pi:x:raspberry
guest:x:guest
EOF
chown cowrie:cowrie /opt/cowrie/etc/userdb.txt

# Bash history préchargé qui donne des pistes à l'attaquant
mkdir -p /opt/cowrie/honeyfs/root /opt/cowrie/honeyfs/home/admin
cat > /opt/cowrie/honeyfs/root/.bash_history <<'EOF'
ssh administrateur@dc01.corp.local
ssh administrateur@dc02-bkp.corp.local
mount -t cifs //srvdomaine/Comptabilite /mnt/comptabilite -o user=admin
ls /mnt/comptabilite/Archives/2025/12-Decembre/
crontab -l
cd /var/backups/veeam
ls -la
zcat veeam-backup-2026-01-15.vbk | head -100
ssh veeam_admin@srv-veeam
sudo -i
cat /etc/cron.d/backup-daily
psql -U sa -h srv-erp -d production
mysql -u root -p
docker ps
systemctl restart smbd
tail -f /var/log/auth.log
exit
EOF

cat > /opt/cowrie/honeyfs/home/admin/.bash_history <<'EOF'
cd /mnt/comptabilite
ls -la Archives/
cat Salaires.xlsx | head
ssh dc01
exit
EOF

# Faux /etc/passwd pour cat /etc/passwd
cat > /opt/cowrie/honeyfs/etc/passwd <<'EOF'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
admin:x:1000:1000:Administrateur,,,:/home/admin:/bin/bash
postgres:x:108:113:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
mysql:x:109:115:MySQL Server,,,:/nonexistent:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
veeam_admin:x:1001:1001:Veeam Backup Service,,,:/home/veeam:/bin/bash
sa:x:1002:1002:SAP B1 Service Account,,,:/home/sa:/bin/bash
EOF

cat > /etc/systemd/system/cowrie.service <<'EOF'
[Unit]
Description=Cowrie SSH/Telnet Honeypot (UniSOC)
After=network-online.target

[Service]
Type=simple
User=cowrie
Group=cowrie
WorkingDirectory=/opt/cowrie
Environment=COWRIE_VIRTUAL_ENV=/opt/cowrie/cowrie-env
ExecStart=/opt/cowrie/cowrie-env/bin/twistd --nodaemon --pidfile= --umask=0022 cowrie
Restart=always
RestartSec=10
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
EOF
mkdir -p /var/log/cowrie /opt/cowrie/var/lib/cowrie /opt/cowrie/var/run
chown -R cowrie:cowrie /var/log/cowrie /opt/cowrie/var

# ───────────────────────────────────────────────────────────────────────
# 5. xrdp + XFCE thémé Windows-like (port 3389)
# ───────────────────────────────────────────────────────────────────────
echo "[5/11] xrdp + XFCE thémé Windows..."

# User admin/admin pour login RDP
if ! id -u rdpadmin >/dev/null 2>&1; then
    useradd -m -s /bin/bash -c "Administrateur" rdpadmin
    echo 'rdpadmin:admin' | chpasswd
fi

# Session XFCE
cat > /home/rdpadmin/.xsession <<'EOF'
#!/bin/sh
exec startxfce4
EOF
chmod +x /home/rdpadmin/.xsession
chown rdpadmin:rdpadmin /home/rdpadmin/.xsession

# Faux desktop avec icônes Windows-like
mkdir -p /home/rdpadmin/Desktop
cat > /home/rdpadmin/Desktop/Veeam-Backup.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Veeam Backup & Replication
Icon=applications-system
Exec=firefox-esr --kiosk https://localhost:443/
Terminal=false
Categories=System;
EOF

cat > /home/rdpadmin/Desktop/Comptes-admin.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Comptes Administrateur (CONFIDENTIEL)
Icon=dialog-password
Exec=libreoffice --writer /srv/samba/informatique/Comptes-Admin/Mots-de-passe-admin.docx
Terminal=false
Categories=Office;
EOF

cat > /home/rdpadmin/Desktop/Schemas-reseau.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Schémas réseau
Icon=network-workgroup
Exec=xdg-open /srv/samba/informatique/Reseau/Schema-reseau-2026.pdf
Terminal=false
Categories=Network;
EOF

cat > /home/rdpadmin/Desktop/Documents-partages.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Documents partagés
Icon=folder-remote
Exec=xfce4-terminal -e "smbclient //localhost/Comptabilite -N"
Terminal=false
Categories=Network;
EOF

cat > /home/rdpadmin/Desktop/SAP-Business-One.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=SAP Business One
Icon=applications-finance
Exec=xfce4-terminal -e "echo 'Connexion à srv-erp.corp.local...' ; sleep 3 ; echo 'Erreur : impossible de joindre le serveur SAP B1.' ; sleep 5"
Terminal=false
Categories=Office;
EOF

chown -R rdpadmin:rdpadmin /home/rdpadmin/Desktop
chmod +x /home/rdpadmin/Desktop/*.desktop

# Wallpaper Windows-like simple (génère un fond blue gradient avec hostname)
cat > /usr/local/bin/generate-wallpaper.sh <<'EOF'
#!/bin/bash
# Si imagemagick dispo, on génère un wallpaper "Win10-like"
which convert >/dev/null && convert -size 1920x1080 \
    gradient:'#0078D7-#005A9E' \
    -gravity center -pointsize 48 -fill '#FFFFFF80' \
    -annotate +0+400 'CORP - srvdomaine' \
    /usr/share/backgrounds/unisoc-canary.jpg 2>/dev/null || true
EOF
chmod +x /usr/local/bin/generate-wallpaper.sh
mkdir -p /usr/share/backgrounds
apt-get install -y --no-install-recommends imagemagick 2>&1 | tail -1
/usr/local/bin/generate-wallpaper.sh

# Configure XFCE par défaut pour rdpadmin
runuser -u rdpadmin -- mkdir -p /home/rdpadmin/.config/xfce4/xfconf/xfce-perchannel-xml
cat > /home/rdpadmin/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-desktop" version="1.0">
  <property name="backdrop" type="empty">
    <property name="screen0" type="empty">
      <property name="monitor0" type="empty">
        <property name="image-path" type="string" value="/usr/share/backgrounds/unisoc-canary.jpg"/>
        <property name="image-style" type="int" value="3"/>
        <property name="last-image" type="string" value="/usr/share/backgrounds/unisoc-canary.jpg"/>
      </property>
    </property>
  </property>
</channel>
EOF
chown -R rdpadmin:rdpadmin /home/rdpadmin/.config

# Capture session : screenshots toutes les 5s + log connexions
mkdir -p /var/log/opencanary/rdp-captures
cat > /opt/rdp-session-recorder.sh <<'EOF'
#!/usr/bin/env bash
# Quand une session xrdp démarre, on prend des screenshots toutes les 5s.
LOG_DIR="/var/log/opencanary/rdp-captures"
LOG="/var/log/opencanary/rdp-fake.log"
mkdir -p "$LOG_DIR"

# Wait for X session
sleep 8
DISPLAY_NUM=$(ps aux | grep -E "Xorg.*:\d+" | grep -v grep | grep -oE ':[0-9]+' | head -1)
[ -z "$DISPLAY_NUM" ] && exit 0

USER_LOGGED=$(who | grep -E "$DISPLAY_NUM" | awk '{print $1}' | head -1)
SRC_IP=$(who | grep -E "$DISPLAY_NUM" | awk '{print $5}' | tr -d '()' | head -1)

echo "{\"ts\":\"$(date -u +%FT%TZ)\",\"logtype\":18000,\"action\":\"rdp_session_start\",\"user\":\"$USER_LOGGED\",\"src_ip\":\"$SRC_IP\",\"node_id\":\"unisoc-canary-rdp\"}" >> "$LOG"

# Loop screenshots
while ps aux | grep -q "[X]org.*$DISPLAY_NUM"; do
    TS=$(date +%Y%m%dT%H%M%S)
    DISPLAY=$DISPLAY_NUM xwd -root -silent 2>/dev/null | convert xwd:- "$LOG_DIR/${SRC_IP:-unknown}-${TS}.png" 2>/dev/null || true
    sleep 5
done

echo "{\"ts\":\"$(date -u +%FT%TZ)\",\"logtype\":18001,\"action\":\"rdp_session_end\",\"user\":\"$USER_LOGGED\",\"src_ip\":\"$SRC_IP\",\"node_id\":\"unisoc-canary-rdp\"}" >> "$LOG"
EOF
chmod +x /opt/rdp-session-recorder.sh

cat > /etc/systemd/system/rdp-recorder.service <<'EOF'
[Unit]
Description=UniSOC RDP session recorder
After=xrdp.service

[Service]
Type=simple
# Le script attend une session X, exit s'il n'y en a pas. On le relance régulièrement
# au lieu de Restart=always (qui hammer la machine).
ExecStart=/bin/bash -c "while :; do /opt/rdp-session-recorder.sh; sleep 30; done"
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target
EOF

# Configure xrdp
sed -i 's/^port=.*/port=3389/' /etc/xrdp/xrdp.ini 2>/dev/null || true
# Désactive use_compression pour clarté logs
systemctl enable --now xrdp

# ───────────────────────────────────────────────────────────────────────
# 6. Faux Veeam Backup v10 HTTPS
# ───────────────────────────────────────────────────────────────────────
echo "[6/11] Faux Veeam Backup v10 HTTPS..."
mkdir -p /etc/ssl/veeam-fake /var/www/veeam-fake
cd /etc/ssl/veeam-fake
[ ! -f veeam.key ] && openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
    -keyout veeam.key -out veeam.crt \
    -subj "/C=FR/ST=Ile-de-France/L=Paris/O=Corp Inc/OU=IT/CN=veeam.corp.local" 2>/dev/null

cat > /var/www/veeam-fake/index.html <<'HTMLEOF'
<!DOCTYPE html>
<html lang="fr"><head><meta charset="UTF-8"><title>Veeam Backup & Replication 10.0</title>
<style>
body{font-family:'Segoe UI',Tahoma,sans-serif;background:linear-gradient(135deg,#00B33C 0%,#007E2C 100%);min-height:100vh;margin:0;display:flex;align-items:center;justify-content:center}
.lb{background:#fff;padding:40px;border-radius:4px;box-shadow:0 4px 16px rgba(0,0,0,.3);width:380px}
.lo{text-align:center;margin-bottom:24px}.lo h1{color:#00B33C;margin:0;font-size:26px;font-weight:600}
.lo .s{color:#555;font-size:13px;margin-top:4px}
.v{color:#888;font-size:11px;text-align:center;margin-bottom:20px;border-bottom:1px solid #eee;padding-bottom:14px}
form{display:flex;flex-direction:column;gap:12px}label{font-size:12px;color:#333;font-weight:600}
input{padding:10px 12px;border:1px solid #ccc;border-radius:2px;font-size:14px}input:focus{border-color:#00B33C;outline:none}
button{background:#00B33C;color:#fff;border:none;padding:11px;border-radius:2px;font-size:14px;font-weight:600;cursor:pointer;margin-top:8px}
.ft{text-align:center;color:#888;font-size:11px;margin-top:18px}
.er{background:#ffe5e5;color:#c00;padding:10px;border-radius:2px;font-size:13px;margin-bottom:12px;display:none}
</style></head><body>
<div class="lb"><div class="lo"><h1>Veeam</h1><div class="s">Backup &amp; Replication</div></div>
<div class="v">Version 10.0.1.4854 — Build 2020-04-14</div>
<div id="err" class="er">Identifiants incorrects.</div>
<form action="/login" method="POST" onsubmit="setTimeout(()=>document.getElementById('err').style.display='block',800);">
<label for="domain">Domaine</label><input type="text" id="domain" name="domain" value="CORP" required>
<label for="user">Utilisateur</label><input type="text" id="user" name="user" placeholder="ex: veeam_admin" required autofocus>
<label for="pwd">Mot de passe</label><input type="password" id="pwd" name="pwd" required>
<button type="submit">Se connecter</button></form>
<div class="ft">© 2010-2020 Veeam Software<br>Licensed to: Corp Inc — Enterprise Edition</div></div>
</body></html>
HTMLEOF

cat > /opt/veeam-fake-server.py <<'PYEOF'
#!/usr/bin/env python3
import http.server,ssl,socketserver,json,urllib.parse,time
from datetime import datetime,timezone
LOG="/var/log/opencanary/veeam-fake.log"
class H(http.server.SimpleHTTPRequestHandler):
    def log_message(self,f,*a):pass
    def _l(self,a,d):
        e={"ts":datetime.now(timezone.utc).isoformat(),"src_ip":self.client_address[0],"src_port":self.client_address[1],"action":a,"path":self.path,"user_agent":self.headers.get("User-Agent",""),"data":d,"logtype":3001,"node_id":"unisoc-canary-veeam"}
        with open(LOG,"a") as f:f.write(json.dumps(e)+"\n")
    def do_GET(self):
        if self.path in("/","/index.html","/login.aspx"):
            with open("/var/www/veeam-fake/index.html","rb") as f:c=f.read()
            self.send_response(200);self.send_header("Content-Type","text/html; charset=utf-8")
            self.send_header("Server","Microsoft-IIS/10.0");self.send_header("X-Powered-By","ASP.NET");self.end_headers()
            self.wfile.write(c);self._l("GET_login_page",{})
        else:self.send_response(404);self.end_headers();self._l("GET_404",{"path":self.path})
    def do_POST(self):
        n=int(self.headers.get("Content-Length",0));b=self.rfile.read(n).decode("utf-8",errors="replace")
        p=urllib.parse.parse_qs(b)
        self._l("POST_login_attempt",{"domain":(p.get("domain")or[""])[0],"user":(p.get("user")or[""])[0],"pwd":(p.get("pwd")or[""])[0]})
        time.sleep(1.5);self.send_response(401);self.send_header("Content-Type","text/html");self.end_headers()
        self.wfile.write(b"<html><body>Login failed</body></html>")
ctx=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain(certfile="/etc/ssl/veeam-fake/veeam.crt",keyfile="/etc/ssl/veeam-fake/veeam.key")
httpd=socketserver.TCPServer(("0.0.0.0",443),H)
httpd.socket=ctx.wrap_socket(httpd.socket,server_side=True)
print("Veeam fake on :443");httpd.serve_forever()
PYEOF
chmod +x /opt/veeam-fake-server.py

cat > /etc/systemd/system/veeam-fake.service <<'EOF'
[Unit]
Description=UniSOC Fake Veeam HTTPS
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/veeam-fake-server.py
Restart=always
RestartSec=10
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF

# ───────────────────────────────────────────────────────────────────────
# 7. Faux ProFTPD 1.3.5 (port 21)
# ───────────────────────────────────────────────────────────────────────
echo "[7/11] Faux ProFTPD 1.3.5 (port 21)..."
cat > /opt/proftpd-fake-server.py <<'PYEOF'
#!/usr/bin/env python3
import socket,threading,json
from datetime import datetime,timezone
LOG="/var/log/opencanary/ftp-fake.log"
BANNER=b"220 ProFTPD 1.3.5 Server (Corp FTP) [::ffff:0.0.0.0]\r\n"
def lo(d):
    with open(LOG,"a") as f:f.write(json.dumps(d)+"\n")
def h(c,a):
    st={"u":None}
    try:
        c.sendall(BANNER)
        lo({"ts":datetime.now(timezone.utc).isoformat(),"src_ip":a[0],"logtype":4000,"action":"ftp_connect","node_id":"unisoc-canary-ftp"})
        while True:
            d=c.recv(1024)
            if not d:break
            cmd=d.decode("utf-8",errors="replace").strip()
            v=cmd.split(" ",1)[0].upper();ar=cmd.split(" ",1)[1] if " " in cmd else ""
            lo({"ts":datetime.now(timezone.utc).isoformat(),"src_ip":a[0],"logtype":4001,"action":"ftp_command","command":v,"argument":ar,"node_id":"unisoc-canary-ftp"})
            if v=="USER":st["u"]=ar;c.sendall(f"331 Password required for {ar}.\r\n".encode())
            elif v=="PASS":
                lo({"ts":datetime.now(timezone.utc).isoformat(),"src_ip":a[0],"logtype":4002,"action":"ftp_login_attempt","username":st.get("u"),"password":ar,"node_id":"unisoc-canary-ftp"})
                c.sendall(b"530 Login incorrect.\r\n")
            elif v=="QUIT":c.sendall(b"221 Goodbye.\r\n");break
            elif v=="SYST":c.sendall(b"215 UNIX Type: L8\r\n")
            elif v=="FEAT":c.sendall(b"211-Features:\r\n EPRT\r\n EPSV\r\n MDTM\r\n PASV\r\n REST STREAM\r\n SIZE\r\n TVFS\r\n UTF8\r\n211 End\r\n")
            elif v=="PWD":c.sendall(b'257 "/" is current directory.\r\n')
            elif v in("CPFR","CPTO","SITE"):c.sendall(b"350 OK.\r\n")
            else:c.sendall(b"500 Command not understood.\r\n")
    except:pass
    finally:
        try:c.close()
        except:pass
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(("0.0.0.0",21));s.listen(50);print("Fake ProFTPD on :21")
while True:
    c,a=s.accept();threading.Thread(target=h,args=(c,a),daemon=True).start()
PYEOF
chmod +x /opt/proftpd-fake-server.py
cat > /etc/systemd/system/proftpd-fake.service <<'EOF'
[Unit]
Description=Fake ProFTPD 1.3.5
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/proftpd-fake-server.py
Restart=always
RestartSec=10
AmbientCapabilities=CAP_NET_BIND_SERVICE
User=nobody
[Install]
WantedBy=multi-user.target
EOF

# ───────────────────────────────────────────────────────────────────────
# 8. Samba avec audit + partages
# ───────────────────────────────────────────────────────────────────────
echo "[8/11] Samba audit + partages..."
mkdir -p /srv/samba/{comptabilite,informatique,RH,Direction}
chmod -R 755 /srv/samba

cat > /etc/samba/smb.conf <<'EOF'
[global]
   workgroup = CORP
   server string = %h server (Samba %v)
   netbios name = SRVDOMAINE
   security = user
   map to guest = Bad User
   guest account = nobody
   log file = /var/log/samba/log.%m
   max log size = 5000
   log level = 1 vfs:1
   server min protocol = NT1
   ntlm auth = yes
   server smb encrypt = off
   load printers = no
   printing = bsd
   printcap name = /dev/null
   disable spoolss = yes

[Comptabilite]
   path = /srv/samba/comptabilite
   browseable = yes
   read only = no
   guest ok = yes
   create mask = 0644
   directory mask = 0755
   vfs objects = full_audit
   full_audit:prefix = %u|%I|%S
   full_audit:success = open openat read pread write pwrite mkdir rmdir unlink rename
   full_audit:failure = open
   full_audit:facility = local5
   full_audit:priority = NOTICE

[Informatique]
   path = /srv/samba/informatique
   browseable = yes
   read only = no
   guest ok = yes
   vfs objects = full_audit
   full_audit:prefix = %u|%I|%S
   full_audit:success = open openat read pread write pwrite
   full_audit:facility = local5
   full_audit:priority = NOTICE

[RH]
   path = /srv/samba/RH
   browseable = yes
   read only = no
   guest ok = yes
   vfs objects = full_audit
   full_audit:prefix = %u|%I|%S
   full_audit:success = open openat read pread write pwrite
   full_audit:facility = local5
   full_audit:priority = NOTICE

[Direction]
   path = /srv/samba/Direction
   browseable = yes
   read only = no
   guest ok = yes
   vfs objects = full_audit
   full_audit:prefix = %u|%I|%S
   full_audit:success = open openat read pread write pwrite
   full_audit:facility = local5
   full_audit:priority = NOTICE
EOF

cat > /etc/rsyslog.d/30-samba-audit.conf <<'EOF'
local5.* /var/log/opencanary/samba-audit.log
& stop
EOF
systemctl restart rsyslog
systemctl enable --now smbd nmbd

# ───────────────────────────────────────────────────────────────────────
# 9. Génération fichiers leurres
# ───────────────────────────────────────────────────────────────────────
echo "[9/11] Génération fichiers leurres..."
curl -sL https://client.unisoc.fr/downloads/honeypot/generate_fake_files.py -o /opt/generate_fake_files.py
chmod +x /opt/generate_fake_files.py
python3 /opt/generate_fake_files.py 2>&1 | tail -5

# ───────────────────────────────────────────────────────────────────────
# 10. inotify file watcher
# ───────────────────────────────────────────────────────────────────────
echo "[10/11] inotify watcher..."
cat > /opt/file-watcher.sh <<'EOF'
#!/usr/bin/env bash
inotifywait -m -r -e open,access,modify,delete --format '%T|%w%f|%e|%U' --timefmt '%Y-%m-%dT%H:%M:%S' \
    /srv/samba 2>/dev/null | while IFS='|' read ts path event _; do
    echo "{\"ts\":\"$ts\",\"logtype\":5001,\"action\":\"file_$event\",\"path\":\"$path\",\"node_id\":\"unisoc-canary-fwatch\"}" >> /var/log/opencanary/file-watcher.log
done
EOF
chmod +x /opt/file-watcher.sh
cat > /etc/systemd/system/file-watcher.service <<'EOF'
[Unit]
Description=UniSOC honeypot file watcher
After=smbd.service
[Service]
Type=simple
ExecStart=/opt/file-watcher.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF

# ───────────────────────────────────────────────────────────────────────
# 11. SSH Tarpit port 26
# ───────────────────────────────────────────────────────────────────────
echo "[11/11] SSH tarpit port 26..."
cat > /opt/ssh-tarpit.py <<'PYEOF'
#!/usr/bin/env python3
import socket,threading,random,time,json
from datetime import datetime,timezone
LOG="/var/log/opencanary/ssh-tarpit.log"
def h(c,a):
    with open(LOG,"a") as f:
        f.write(json.dumps({"ts":datetime.now(timezone.utc).isoformat(),"src_ip":a[0],"src_port":a[1],"logtype":18002,"action":"ssh_tarpit","node_id":"unisoc-canary-tarpit"})+"\n")
    try:
        for _ in range(300):c.send(bytes([random.randint(33,126)]));time.sleep(1)
    except:pass
    finally:
        try:c.close()
        except:pass
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(("0.0.0.0",26));s.listen(50);print("SSH tarpit on :26")
while True:
    c,a=s.accept();threading.Thread(target=h,args=(c,a),daemon=True).start()
PYEOF
chmod +x /opt/ssh-tarpit.py
cat > /etc/systemd/system/ssh-tarpit.service <<'EOF'
[Unit]
Description=UniSOC SSH Tarpit
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/ssh-tarpit.py
Restart=always
RestartSec=10
User=nobody
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF

# ───────────────────────────────────────────────────────────────────────
# 11b. HTTP Honeytrap port 80 — faux dashboard "BackupServer v3.2" + 25 routes piégées
# ───────────────────────────────────────────────────────────────────────
echo "[11c/12] Cert TLS auto-renew (self-signed par défaut, Let's Encrypt opt-in)..."
curl -sL https://client.unisoc.fr/downloads/honeypot/cert-renew.sh -o /opt/cert-renew.sh
chmod 755 /opt/cert-renew.sh
# 1er run pour avoir un cert disponible immédiatement
/opt/cert-renew.sh || true
# Cron hebdo dimanche 3h07
( crontab -l 2>/dev/null | grep -v cert-renew.sh ; echo "7 3 * * 0 /opt/cert-renew.sh" ) | crontab -

echo "[11b/12] HTTP Honeytrap port 80 (BackupServer leurre)..."
curl -sL https://client.unisoc.fr/downloads/honeypot/http-honeytrap.py -o /opt/http-honeytrap.py
chmod 755 /opt/http-honeytrap.py
cat > /etc/systemd/system/http-honeytrap.service <<'EOF'
[Unit]
Description=UniSOC HTTP Honeytrap (faux dashboard BackupServer v3.2 + 25 routes piégées)
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/http-honeytrap.py
Restart=always
RestartSec=10
User=opencanary
Group=opencanary
AmbientCapabilities=CAP_NET_BIND_SERVICE
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target
EOF

# ───────────────────────────────────────────────────────────────────────
# 12. OS fingerprint spoofing — nmap -O verra "Windows Server 2016+"
# ───────────────────────────────────────────────────────────────────────
echo "[12/12] OS fingerprint spoofing (Linux → Windows)..."
cat > /etc/sysctl.d/99-unisoc-os-spoof.conf <<'EOF'
# Mimick Windows Server 2016/2019/2022 TCP/IP stack signature
# pour tromper nmap -O / xprobe2 / p0f.
net.ipv4.ip_default_ttl = 128
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_dsack = 0
net.ipv4.tcp_fack = 0
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_ecn = 0
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ratelimit = 0
net.ipv4.icmp_ratemask = 0
net.ipv4.tcp_synack_retries = 2
EOF
sysctl --system 2>&1 | grep -E "^net\.|kernel\." | tail -5 || true

# iptables : force TTL=128 sur tous les paquets sortants (Linux 64 → Windows 128)
apt-get install -y --no-install-recommends iptables iptables-persistent 2>&1 | tail -2 || true

# Si la chaîne mangle TTL n'existe pas déjà, on l'ajoute (idempotent)
if ! iptables -t mangle -L POSTROUTING -n 2>/dev/null | grep -q "TTL set to 128"; then
    iptables -t mangle -A POSTROUTING -j TTL --ttl-set 128 2>/dev/null || true
fi

# Persiste les règles iptables
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4 2>/dev/null || true

# IPv6 désactivé par défaut sur les Windows historiques — on désactive aussi
cat > /etc/sysctl.d/98-disable-ipv6.conf <<'EOF'
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
sysctl --system 2>/dev/null | tail -3 || true

# Hostname et resolv coherence avec Windows AD
echo "127.0.0.1   srvdomaine srvdomaine.corp.local localhost" > /etc/hosts
echo "::1         srvdomaine srvdomaine.corp.local localhost ip6-localhost ip6-loopback" >> /etc/hosts

# ───────────────────────────────────────────────────────────────────────
# Démarrage de tout
# ───────────────────────────────────────────────────────────────────────
echo
echo "[+] Démarrage des services..."
systemctl daemon-reload

# ───────────────────────────────────────────────────────────────────────
# 13. License gate — au prochain boot, license_check.py vérifiera la licence
#     et activera/désactivera les services. À l'install, on les enable juste
#     pour cette première session ; license_check les éteindra au reboot
#     suivant si pas de licence valide.
# ───────────────────────────────────────────────────────────────────────
mkdir -p /opt/unisoc-honeypot-agent /etc/unisoc-honeypot-agent /var/lib/unisoc-honeypot-agent
chmod 700 /etc/unisoc-honeypot-agent /var/lib/unisoc-honeypot-agent
curl -sL https://client.unisoc.fr/downloads/honeypot/agent/license_check.py \
    -o /opt/unisoc-honeypot-agent/license_check.py 2>/dev/null || true
chmod 755 /opt/unisoc-honeypot-agent/license_check.py 2>/dev/null || true

cat > /etc/systemd/system/unisoc-honeypot-license-check.service <<'EOF'
[Unit]
Description=UniSOC Honeypot License Check (gates services until activation)
After=network-online.target chrony.service
Before=opencanary.service cowrie.service veeam-fake.service ssh-tarpit.service rdp-recorder.service smbd.service proftpd-fake.service file-watcher.service xrdp.service
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /opt/unisoc-honeypot-agent/license_check.py
RemainAfterExit=yes
StandardOutput=append:/var/log/unisoc-honeypot-license.log
StandardError=append:/var/log/unisoc-honeypot-license.log

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable unisoc-honeypot-license-check

# Démarrage initial sans licence (mode "test" pour cette session) — au prochain
# reboot, license_check.py évaluera la licence et coupera les services si pas de licence valide
systemctl enable --now opencanary cowrie veeam-fake proftpd-fake ssh-tarpit file-watcher rdp-recorder http-honeytrap

sleep 6

echo
echo "═══════════════════════════════════════════════════════════════════"
echo "[+] Status des services :"
for svc in ssh xrdp opencanary cowrie smbd veeam-fake proftpd-fake ssh-tarpit file-watcher rdp-recorder; do
    state=$(systemctl is-active "$svc" 2>/dev/null || echo "?")
    echo "  $svc: $state"
done

echo
echo "[+] Ports en écoute :"
ss -tlnp 2>/dev/null | awk '/LISTEN/ {print "  " $4}' | sort -u | head -25

echo
echo "═══════════════════════════════════════════════════════════════════"
echo "[$(date -u +%FT%TZ)] UniSOC Canary PRO v2 installé."
echo
echo "  SSH ADMIN (réel)  : ssh root@<IP> -p 22222"
echo "  SSH/Telnet HONEY  : 22 + 23  (Cowrie medium-interaction — userdb cohérent)"
echo "  RDP (xrdp)        : 3389  user=rdpadmin / mdp=admin → faux desktop XFCE"
echo "  Veeam HTTPS       : 443  cert auto-signé"
echo "  ProFTPD 1.3.5     : 21   banner CVE-2015-3306 simulée"
echo "  Samba (4 shares)  : 139, 445"
echo "  MSSQL/MySQL/VNC/Redis : 1433, 3306, 5900, 6379  (OpenCanary)"
echo "  SSH Tarpit        : 26"
echo
echo "  Logs centralisés : /var/log/opencanary/  +  /var/log/cowrie/cowrie.json"
echo "  Capture RDP      : /var/log/opencanary/rdp-captures/<ip>-<ts>.png"
echo
echo "═══════════════════════════════════════════════════════════════════"
