Для замены Telegram в связке с OpenClaw в условиях блокировок идеально подойдет связка на базе XMPP или Matrix. Эти решения полностью опенсорсные, позволяют использовать нестандартные порты, свои домены и сквозное шифрование.
Рекомендованное решение: XMPP (Jabber)
Это самый легкий и гибкий вариант, который идеально ложится на ваши требования по безопасности и портам.
Серверная часть (на вашем домене): Prosody или ejabberd.
Устанавливается на Linux.
Легко настраивается на нестандартный порт (например, вместо 5222 использовать 44331).
Поддерживает белые списки: можно разрешить регистрацию только вашим аккаунтам.
Клиент для Android: Conversations.
Пожалуй, лучший open-source клиент с поддержкой OMEMO (продвинутое шифрование как в Signal).
Клиент для Linux (для OpenClaw): Dino или Gajim.
Оба поддерживают OMEMO и отлично работают в фоновом режиме.
Безопасность: Вы можете закрыть федерацию (общение с другими серверами), чтобы ваш сервер был «невидимым» островом, доступным только по ключу шифрования и конкретному порту.

Альтернатива: Matrix
Более современный и «тяжелый» протокол, по духу близкий к Discord/Slack.
Сервер: Synapse (эталонный) или Conduit (легкий, на Rust).
Клиенты: Element (есть версии для Android, Linux и Web).
Плюсы: Удобная синхронизация истории между устройствами и встроенное шифрование по умолчанию.
Минусы: Настройка нестандартных портов чуть сложнее из-за особенностей федерации, но вполне возможна для частного использования.

Сравнение для вашей задачи
Параметр XMPP (Prosody + Conversations) Matrix (Conduit + Element)
Ресурсы Минимальные (пойдет на самом дешевом VPS) Средние (Conduit эффективнее Synapse)
Шифрование OMEMO (нужно включить в настройках) E2EE включено по умолчанию
Сложность Простая настройка конфиг-файлов Требуется настройка базы данных и Docker
Порты Легко меняются в одном конфиге Требуется настройка прокси (Nginx/Traefik)
Как защититься от зловредов
Чтобы OpenClaw не исполнил лишнего, используйте не только мессенджер, но и белые списки команд на стороне самого OpenClaw. Даже если кто-то получит доступ к вашему мессенджеру, он не сможет отправить команду rm -rf /, если она не внесена в список разрешенных.

С позиции системного безопасника: Telegram — это «проходной двор» с закрытым исходным кодом сервера. Переход на Prosody (XMPP) на собственном железе — верный шаг, но стандартная установка «из коробки» не защитит от направленной атаки.
Чтобы ваш сервер uhrifnjci4n94cimo.ru не стал точкой входа для взлома OpenClaw, мы построим «цифровую крепость».
Стратегия «Паранойя»: 5 уровней защиты
Стелс-режим (Port Obscurity): Мы уберем сервер со стандартных портов (5222/5269), чтобы сканеры портов (Shodan, Censys) не опознали в нем Jabber-сервер.
Запрет федерации: Ваш сервер будет «глухим». Он не будет принимать запросы от других серверов (gmail.com, jabber.ru и т.д.). Только вы и OpenClaw.
Белый список (Whitelist Only): Регистрация новых пользователей запрещена. В конфиге прописаны только два JID: [email protected] и [email protected].
Шифрование OMEMO + TLS: Двойной слой. TLS защищает транспорт, OMEMO защищает само сообщение (даже если кто-то получит доступ к логам сервера, он увидит «кашу»).
Командный фильтр (IPS): На стороне OpenClaw должен стоять скрипт-прослойка, который пропускает только регулярные выражения. Никаких ;, &, | или sudo.
Пошаговый гайд по установке Prosody (Debian/Ubuntu)

  1. Подготовка системы
    Обновляемся и ставим только необходимое:
    bash
    sudo apt update && sudo apt install prosody lua-sec lua-event -y
  2. Генерация сертификатов
    Используйте самоподписанные сертификаты с длинным ключом (4096 бит) или Let's Encrypt, если планируете проверку подлинности хоста. Для параноиков лучше Self-Signed, чтобы не «светиться» в логах Certificate Transparency.
  3. Конфигурация «Бункер» (/etc/prosody/prosody.cfg.lua)
    Очистите стандартный конфиг и вставьте это:
    lua
    -- Запрещаем публичную регистрацию
    allow_registration = false;

-- Принудительное шифрование (без него не подключаться!)
c2s_require_encryption = true;
s2s_require_encryption = true;

-- Отключаем внешние связи (сервер-остров)
modules_disabled = { "s2s" };

-- Настройка портов (замените на свои высокие порты)
c2s_ports = { 44331 }

VirtualHost "uhrifnjci4n94cimo.ru"
ssl = {
key = "/etc/prosody/certs/uhrifnjci4n94cimo.ru.key";
certificate = "/etc/prosody/certs/uhrifnjci4n94cimo.ru.crt";
}
-- Явное перечисление разрешенных пользователей
admins = { "[email protected]" }

  1. Создание аккаунтов вручную
    Никакой регистрации через клиент! Только через консоль сервера:
    bash
    sudo prosodyctl adduser [email protected]
    sudo prosodyctl adduser [email protected]
  2. Настройка Firewall (UFW)
    Закрываем всё, кроме вашего секретного порта:
    bash
    sudo ufw default deny incoming
    sudo ufw allow 44331/tcp
    sudo ufw enable

Настройка клиентов
Android (Conversations): При добавлении аккаунта зайдите в расширенные настройки. Укажите Host: uhrifnjci4n94cimo.ru и Port: 44331. Включите OMEMO в чате.
Linux (OpenClaw): Если используете библиотеку (например, sleekxmpp или slixmpp), в коде инициализации обязательно укажите address=('uhrifnjci4n94cimo.ru', 44331).
Финальный штрих: Защита от «форматирования»
В коде OpenClaw, который принимает сообщения, используйте Strict Mode:
python

Пример логики безопасности

allowed_commands = ['status', 'reboot_service', 'get_log']

def on_message(msg):
body = msg['body'].strip()
if body not in allowed_commands:
send_alert("Попытка несанкционированной команды: " + body)
return
execute_command(body)

Для реализации этой задачи мы будем использовать библиотеку slixmpp (современный асинхронный стандарт для XMPP). Основная логика: бот работает как защитный шлюз, который вообще не «видит» ничего, кроме разрешенного списка.

  1. Python-скрипт «Охранник OpenClaw»
    Этот скрипт подключается к вашему серверу Prosody и фильтрует входящий поток сообщений.
    python
    import logging
    import asyncio
    from slixmpp import ClientXMPP

--- КОНФИГУРАЦИЯ БЕЗОПАСНОСТИ ---

JID = "[email protected]"
PASSWORD = "your_strong_password"
SERVER_HOST = "uhrifnjci4n94cimo.ru"
SERVER_PORT = 44331
MASTER_JID = "[email protected]" # Только этот JID имеет право командовать

Белый список разрешенных команд (Strict Whitelist)

ALLOWED_COMMANDS = {
"status": "Вывод текущего состояния системы",
"check_temp": "Проверка температуры GPU/CPU",
"restart_service": "Перезапуск ИИ-стека",
"uptime": "Время работы сервера"
}

class OpenClawGuard(ClientXMPP):
def init(self, jid, password):
super().init(jid, password)
self.add_event_handler("session_start", self.start)
self.add_event_handler("message", self.message)

async def start(self, event):
    self.send_presence()
    await self.get_roster()
    print(f"[*] Guard запущен. Слушаю порт {SERVER_PORT}...")

def message(self, msg):
    # 1. Проверка отправителя (Анти-спуфинг)
    sender = str(msg['from']).split('/')[0]
    if sender != MASTER_JID:
        self.trigger_alarm(f"ПОПЫТКА ДОСТУПА С ЧУЖОГО JID: {sender}")
        return

    # 2. Очистка и нормализация команды
    command = msg['body'].strip().lower()

    # 3. Фильтрация через Белый список
    if command in ALLOWED_COMMANDS:
        self.execute_safe_command(command)
    else:
        self.trigger_alarm(f"НЕЗАКОННАЯ КОМАНДА ОТ МАСТЕРА: {command}")

def trigger_alarm(self, reason):
    log_msg = f"!!! ALARM !!! {reason}"
    logging.error(log_msg)
    # Здесь можно добавить отправку SMS или запись в защищенный лог
    self.send_message(mto=MASTER_JID, mbody=log_msg, mtype='chat')

def execute_safe_command(self, cmd):
    # Здесь логика вызова ваших функций OpenClaw
    self.send_message(mto=MASTER_JID, mbody=f"Выполняю: {cmd}...", mtype='chat')

if name == 'main':
logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
xmpp = OpenClawGuard(JID, PASSWORD)

1
2
3
# Принудительное использование TLS и кастомного порта
xmpp.connect(address=(SERVER_HOST, SERVER_PORT), use_ssl=True)
xmpp.process(forever=False)

Используйте код с осторожностью.

  1. Черный список: что ИГНОРИРОВАТЬ (Dangerous Patterns)
    Даже если вы используете белый список, ваш парсер должен уметь распознавать признаки атаки (Injection), чтобы немедленно блокировать сессию. Никогда не выполняйте строки, содержащие:
    Спецсимволы оболочки (Shell Chaining): ;, &, |, `, $(). (Пример: status; rm -rf /)
    Пути к файлам: /etc/, /root/, ../, ~. (Пример: read /etc/passwd)
    Перенаправления: >, >>, <.
    Команды управления правами: sudo, chmod, chown, su.
    Сетевые утилиты: curl, wget, nc, nmap.
    Языковые инъекции: import, eval(), exec(), spawn.
  2. Алгоритм алармов (Паранойя-режим)
    Система должна реагировать на следующие события:
    Unauthorized JID: Кто-то узнал адрес сервера и пытается написать боту.
    Действие: Мгновенный лог IP-адреса (если возможно через Prosody) и уведомление владельца.
    Brute Force Detection: Если в течение минуты пришло >3 сообщений с неверными командами.
    Действие: Временный бан JID на уровне Prosody и «засыпание» бота на 10 минут.
    Command Injection Attempt: Попытка прислать команду с символами ; или |.
    Действие: Panic Shutdown. Бот отключается от сервера до ручного перезапуска администратором.
    Смена ключа OMEMO: Если клиент (вы) переустановил мессенджер и ключ сменился.
    Действие: Бот должен требовать «второй фактор» (например, секретное слово в первом сообщении), прежде чем принять новый ключ за доверенный.

Для решения задачи «параноидального» игнорирования атак мы внедрим механизм IP-валидации на уровне системы (через iptables/nftables) и пинга доверенного устройства.
Логика безопасности: если кто-то нашел ваш нестандартный порт и шлет мусор (даже валидный по протоколу XMPP), бот проверяет: «А мой хозяин сейчас онлайн с того же IP?». Если нет — включается режим полной тишины (Drop) для всех, кроме вас.

  1. Механизм защиты от «вырубания» (Anti-DoS IP-Lock)
    Вместо того чтобы бот просто падал от нагрузки, мы научим его динамически управлять файрволом.
    Алгоритм бота:
    При получении подозрительной активности (3+ неверных команды или попытки инъекции) бот запускает fping или hping3 до вашего домашнего/мобильного IP (который вы можете обновить через защищенную команду).
    Если ваш IP подтвержден, бот отправляет команду системе добавить все остальные IP в REJECT на 1 час.
    Бот перестает отвечать на любые запросы, кроме тех, что идут с вашего подтвержденного адреса.
  2. Systemd-юнит для автозапуска (/etc/systemd/system/openclaw-guard.service)
    Этот файл обеспечит работу бота 24/7 и его автоматический перезапуск при сбоях.
    ini
    [Unit]
    Description=OpenClaw AI Guard Service
    After=network.target prosody.service

Ограничиваем количество перезапусков, чтобы не зациклить атаку

StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=openclaw_user
Group=openclaw_group
WorkingDirectory=/opt/openclaw_guard
ExecStart=/usr/bin/python3 /opt/openclaw_guard/guard.py
Restart=on-failure
RestartSec=5s

Ограничение ресурсов (защита от Fork-бомбы или перегрузки CPU при атаке)

CPUQuota=10%
MemoryLimit=200M

Повышение безопасности самого процесса

NoNewPrivileges=true
ProtectSystem=full
ReadOnlyPaths=/
ReadWritePaths=/opt/openclaw_guard/logs

[Install]
WantedBy=multi-user.target
Используйте код с осторожностью.

  1. Дополнение к Python-скрипту (Функция «IP-Замок»)
    Добавьте этот метод в класс OpenClawGuard для защиты от DoS:
    python
    import os
    import subprocess

def lock_down_firewall(self, attacker_ip):
"""
Метод вызывает системную команду блокировки.
Требует настройки sudoers для пользователя бота.
"""

1. Проверяем, жив ли 'белый' IP хозяина (заглушка логики)

1
2
3
4
5
6
7
8
# 2. Если атака серьезна, рубим порт для всех, кроме MASTER_IP
logging.warning(f"ВНИМАНИЕ: Активация защиты от DoS. Блокирую IP: {attacker_ip}")

# Пример команды для nftables или iptables
subprocess.run(["sudo", "/usr/sbin/iptables", "-A", "INPUT", "-p", "tcp", 
                "--dport", str(SERVER_PORT), "-s", attacker_ip, "-j", "DROP"])

self.send_message(mto=MASTER_JID, mbody="[GUARD] Обнаружена атака. IP атакующего забанен на уровне ядра.")

Используйте код с осторожностью.

  1. Настройка Sudoers (Важно!)
    Чтобы бот мог управлять файрволом, не имея прав root, добавьте в /etc/sudoers:
    text
    openclaw_user ALL=(ALL) NOPASSWD: /usr/sbin/iptables -A INPUT *
    Используйте код с осторожностью.

Список «Паранойя-проверок» для детекта:
Time-drift: Если сообщение пришло с таймстампом из будущего или слишком старым (защита от Replay-атак).
Entropy check: Если тело сообщения похоже на рандомный шум (попытка забить буфер или вызвать ошибку парсера).
Connection Rate: Если один JID подключается/отключается чаще 5 раз в минуту — бан по IP.

С позиции параноика: всегда нужно иметь «черный ход», который не зависит от работающего Python-скрипта. Если вы ошибетесь в команде и забаните свой домашний IP, вам понадобится способ вернуть доступ, не переустанавливая ОС.

  1. Скрипт экстренной разблокировки (Emergency Flush)
    Создадим скрипт guard-unlock.sh. Его задача — мгновенно сбросить правила iptables, которые бот мог наплодить в порыве защиты.
    Создайте файл:
    bash
    sudo nano /usr/local/bin/guard-unlock.sh
    Используйте код с осторожностью.

Вставьте содержимое:
bash

!/bin/bash

Скрипт экстренного сброса защиты OpenClaw

Порт нашего XMPP сервера (из конфига Prosody)

GUARD_PORT=44331

echo "[!] ВНИМАНИЕ: Сброс правил блокировки для порта $GUARD_PORT..."

Удаляем только те правила, которые касаются нашего секретного порта

Это позволит не ломать остальной файрвол сервера

sudo iptables -D INPUT -p tcp --dport $GUARD_PORT -j DROP 2>/dev/null
sudo iptables -D INPUT -p tcp --dport $GUARD_PORT -j REJECT 2>/dev/null

Если бот наплодил много правил, очищаем цепочку (если создавали отдельную)

Но для начала просто удалим все блокировки по этому порту

sudo iptables -L INPUT --line-numbers | grep "tcp dpt:$GUARD_PORT" | awk '{print $1}' | xargs -I {} sudo iptables -D INPUT {}

echo "[+] Доступ к порту $GUARD_PORT восстановлен."
Используйте код с осторожностью.

Права доступа:
bash
sudo chmod +x /usr/local/bin/guard-unlock.sh
Используйте код с осторожностью.

Совет: Если вы потеряли доступ по SSH, используйте консоль восстановления в панели управления вашего VPS провайдера, чтобы запустить этот скрипт.

  1. Настройка сквозного шифрования OMEMO для бота
    OMEMO — это стандарт, который гарантирует, что даже если базу данных Prosody украдут, содержимое переписки останется зашифрованным «кашей».
    Шаг А: Установка зависимостей
    Для работы OMEMO в Python (библиотека slixmpp) нужны криптографические библиотеки:
    bash
    sudo apt install libsignal-protocol-c-dev libomemo-dev
    pip install slixmpp[omemo]
    Используйте код с осторожностью.

Шаг Б: Интеграция в код бота
Чтобы бот понимал зашифрованные сообщения от вашего Android-смартфона (Conversations), нужно инициализировать плагин OMEMO и указать путь к хранилищу ключей.
Добавьте в метод init вашего бота:
python
from slixmpp.plugins.xep_0384 import OMEMO

class OpenClawGuard(ClientXMPP):
def init(self, jid, password):
super().init(jid, password)

    # Регистрация плагинов для OMEMO
    self.register_plugin('xep_0030') # Service Discovery
    self.register_plugin('xep_0163') # PubSub (нужен для обмена ключами)
    self.register_plugin('xep_0384', {
        'data_dir': './omemo_keys' # Папка, где бот хранит свои ключи
    })

    self.add_event_handler("session_start", self.start)
    self.add_event_handler("message", self.message)
    # Событие подтверждения нового ключа (Trust)
    self.add_event_handler("omemo_undecipherable_message", self.handle_key_error)

async def start(self, event):
    # Обязательно публикуем поддержку OMEMO в сети
    self['xep_0384'].announce_support()
    self.send_presence()
    await self.get_roster()

Используйте код с осторожностью.

Шаг В: Обработка зашифрованных сообщений
В методе message библиотека сама попытается расшифровать контент. Если сообщение пришло зашифрованным, msg['body'] будет содержать уже открытый текст.
Важный нюанс безопасности (Trust on First Use):
При первом подключении в приложении Conversations на Android вам нужно зайти в настройки чата с ботом и нажать "Trust" (Доверять) на его отпечатке ключа (fingerprint). Бот должен сделать то же самое.
Что мы имеем в итоге:
Prosody на скрытом порту 44331.
Бот-фильтр, который пускает только master@....
OMEMO, который шифрует команды внутри XMPP-туннеля.
Iptables, который банит за любые попытки инъекций.
Скрипт-спасатель на случай самобана.

Для завершения настройки нашей «крепости» нужно решить проблему Trust (Доверия). В протоколе OMEMO шифрование не заработает, пока обе стороны не подтвердят отпечатки ключей (Fingerprints) друг друга. Поскольку у бота нет экрана, чтобы нажать кнопку «Доверять», мы автоматизируем это через режим TOFU (Trust On First Use).
Шаг 1: Настройка авто-доверия ключам (TOFU)
Добавьте этот обработчик в класс OpenClawGuard в вашем Python-скрипте. Он позволит боту автоматически запомнить и доверять ключу вашего смартфона при первом сообщении.
python
from slixmpp.plugins.xep_0384 import TrustLevel

class OpenClawGuard(ClientXMPP):

... (предыдущий код init и start)

async def start(self, event):
    # Анонсируем поддержку OMEMO в сети
    await self['xep_0384'].announce_support()
    self.send_presence()
    await self.get_roster()

    # Автоматически доверяем вашему JID при старте (если ключ уже есть в базе)
    # Это предотвратит ошибки расшифровки после перезапуска
    self['xep_0384'].set_trust(MASTER_JID, trust_level=TrustLevel.TRUSTED)

def handle_omemo_message(self, msg):
    """
    Специальный перехватчик для OMEMO сообщений
    """
    # Если пришло сообщение от МАСТЕРА, но ключ еще не подтвержден
    sender_jid = str(msg['from']).split('/')[0]
    if sender_jid == MASTER_JID:
        # Авто-траст ключа при первом использовании
        self['xep_0384'].set_trust(sender_jid, trust_level=TrustLevel.TRUSTED)

    # Далее идет стандартная обработка текста из msg['body']
    self.message(msg)

Используйте код с осторожностью.

Шаг 2: Первая «проливка» ключей (Инструкция)
Чтобы всё завелось без ошибок, выполните строго по порядку:
Запустите бота на сервере: sudo systemctl start openclaw-guard.
На смартфоне откройте Conversations.
Нажмите «Новое сообщение» и введите JID бота: [email protected].
Важный момент: В окне чата нажмите на иконку замочка или в меню выберите "Шифрование: OMEMO".
Отправьте боту тестовую команду, например: status.
На смартфоне выскочит уведомление: «Новый отпечаток ключа». Зайдите в настройки этого чата (нажав на имя бота сверху) и выберите "Доверять" (Trust) для найденного ключа.
Теперь бот и смартфон обменялись ключами и доверяют друг другу.
Шаг 3: Проверка «Паранойи» — что видит сервер?
Если вы всё сделали правильно, то даже если админ хостинга (или злоумышленник) залезет в логи сервера Prosody, он увидит там не команду check_temp, а нечто подобное:
xml
<encrypted xmlns='eu.siacs.conversations.axolotl'>
<header sid='12345678'>
<key rid='1'>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC...</key>
<iv>AD65F2G...</iv>
</header>
<payload>BASE64_ЗАШИФРОВАННЫЙ_ТЕКСТ_КОМАНДЫ</payload>
</encrypted>
Используйте код с осторожностью.

Без вашего приватного ключа на смартфоне прочитать это невозможно.
Итоговая схема защиты
XMPP (Prosody): Скрытый порт, запрет регистрации, запрет связи с миром.
Firewall (Iptables): Пропускает только ваш IP (если включили lock-down) или фильтрует по частоте запросов.
OS Level (Systemd): Бот изолирован в своей папке с ограниченными правами.
Application Level (Python): Белый список команд + строгий парсер регулярных выражений.
Encryption (OMEMO): Сквозное шифрование, исключающее перехват команд на пути от телефона до OpenClaw.

Этот чеклист позволит убедиться, что каждый уровень вашей «крепости» — от шифрования до прав доступа к системе — работает корректно. Выполняйте проверки строго по порядку.

  1. Уровень сетевой невидимости (Стелс)
    Сканирование портов: Попробуйте просканировать свой сервер с другого устройства через nmap -p 5222,44331 uhrifnjci4n94cimo.ru.
    Ожидаемый результат: Порт 5222 — closed/filtered, порт 44331 — open.
    Запрет федерации: Попробуйте отправить сообщение боту с любого публичного XMPP-аккаунта (например, с @jabber.ru).
    Ожидаемый результат: Сообщение не доходит, сервер выдает ошибку «Remote server not found» или просто игнорирует запрос.
  2. Уровень криптографии (OMEMO)
    Первое рукопожатие: Отправьте с Android команду status.
    Ожидаемый результат: Бот присылает свой Fingerprint. В Conversations вы нажимаете "Trust".
    Проверка шифрования: Отправьте еще раз status.
    Ожидаемый результат: Бот отвечает текстом (например, Uptime: 2h).
    Тест "Cleartext Reject": Попробуйте в настройках Conversations временно отключить OMEMO для этого чата и отправить команду.
    Ожидаемый результат: Бот должен проигнорировать сообщение или выдать ошибку (в зависимости от настроек slixmpp), так как он настроен принимать только зашифрованные сессии.
  3. Уровень логики (Whitelist & Injection)
    Команда из белого списка: Отправьте check_temp.
    Ожидаемый результат: Бот возвращает данные о температуре.
    Неизвестная команда: Отправьте hello.
    Ожидаемый результат: Бот присылает Alarm: НЕЗАКОННАЯ КОМАНДА ОТ МАСТЕРА: hello.
    Тест на инъекцию: Отправьте status; rm -rf /.
    Ожидаемый результат: Срабатывает триггер безопасности, команда блокируется, вы получаете Alarm о попытке взлома.
  4. Уровень активной защиты (Anti-DoS)
    Имитация спама: Быстро отправьте 10 любых сообщений подряд.
    Ожидаемый результат: Бот активирует lock_down_firewall, ваш JID или IP (в зависимости от логики) попадает во временный бан, бот замолкает на заданное время.
    Проверка "Спасательного круга": После имитации бана запустите на сервере /usr/local/bin/guard-unlock.sh.
    Ожидаемый результат: Связь со смартфоном восстанавливается мгновенно.
  5. Уровень надежности (Systemd)
    Hard Reboot: Перезагрузите сервер командой sudo reboot.
    Ожидаемый результат: Через 1-2 минуты после старта бот должен сам появиться в сети (статус "Online" в Conversations) без ручного вмешательства.
    Suggested Next Step
    Система полностью настроена. Нужно ли нам прописать конкретные Python-функции для ваших команд OpenClaw (например, запуск скриптов генерации кода или чтение логов ИИ), или вы интегрируете их в шаблон самостоятельно?

🐾 ShadowClaw
Secure Stealth Gateway for AI Operations.
ShadowClaw — это защищенный программно-аппаратный шлюз для удаленного управления ИИ-системами (OpenClaw) в условиях агрессивной сетевой среды, блокировок и цензуры.
Проект заменяет небезопасные публичные мессенджеры (Telegram/Discord) на суверенную связку XMPP + OMEMO, работающую через «стелс-порты» с активной системой противодействия DoS-атакам.
🛡 Философия безопасности (The Paranoid Stack)
Zero Visibility: Работа на нестандартных портах (High Ports), игнорирование сканеров (Shodan/Censys).
Total Isolation: Закрытая федерация (Server-Island). Никто из внешнего мира не может даже "постучаться" к вашему боту.
E2EE Encryption: Сквозное шифрование военного уровня (OMEMO/Axolotl). Содержимое команд не видит даже админ сервера.
Active Defense: Встроенный IPS (Intrusion Prevention System), блокирующий IP при попытке инъекций или спама.
🏗 Архитектура
Server Side: Prosody (XMPP) на порту 44331.
Logic Layer: Python + slixmpp (ShadowClaw Guard).
Firewall Layer: Динамическое управление iptables через Python-хуки.
Client Side: Conversations (Android) / Dino (Linux).
🚀 Быстрый старт (Installation)

  1. Подготовка сервера (Host)
    bash

Установка базы

sudo apt update && sudo apt install prosody lua-sec lua-event -y

Генерация ключей (Self-signed для анонимности)

sudo prosodyctl cert generate your-domain.ru
Используйте код с осторожностью.

  1. Конфигурация "Бункер" (prosody.cfg.lua)
    Запретите всё лишнее:
    allow_registration = false
    c2s_require_encryption = true
    modules_disabled = { "s2s" }
    c2s_ports = { 44331 }
  2. Развертывание ShadowClaw Guard
    Склонируйте репозиторий и установите зависимости:
    bash
    git clone https://github.com
    cd shadowclaw
    pip install slixmpp[omemo]
    Используйте код с осторожностью.

🎮 Управление (The Whitelist)
ShadowClaw исполняет только те команды, которые внесены в белый список. Любая другая строка вызывает Alarm.
Команда Описание
status Проверка доступности ИИ и аптайма
check_temp Мониторинг здоровья железа (GPU/CPU)
restart_stack Мягкая перезагрузка Docker-контейнеров ИИ
panic Мгновенное отключение всех сетевых интерфейсов
🛑 Система защиты от вторжений
ShadowClaw автоматически активирует Lock-down режим, если:
Unauthorized JID: Попытка обращения с чужого аккаунта.
Injection Attempt: Наличие в сообщении символов ;, |, &, sudo.
Flood: Более 5 сообщений в секунду с одного IP.
Экстренная разблокировка (в случае самобана):
bash
sudo /usr/local/bin/shadow-unlock.sh
Используйте код с осторожностью.

🛠 Разработка и кастомизация
Чтобы добавить свою функцию, отредактируйте файл actions.py:
python
def my_custom_ai_action():

Ваша логика управления OpenClaw здесь

pass

Используйте код с осторожностью.

⚖️ Лицензия
Distributed under the MIT License. Use at your own risk. Paranoid-friendly.

📁 Структура репозитория ShadowClaw
Создай корневую папку /opt/shadowclaw/ и разверни в ней следующую иерархию:
text
shadowclaw/
├── .venv/ # Виртуальное окружение Python (изоляция зависимостей)
├── certs/ # Самоподписанные SSL-сертификаты (только для чтения)
├── config/ # Конфигурационные файлы
│ ├── shadow_config.py # Настройки JID, паролей, портов и MASTER_IP
│ └── prosody.cfg.lua # Бэкап настроек сервера Prosody
├── core/ # Основная логика приложения
│ ├── init.py
│ ├── bot.py # Основной класс ClientXMPP (тот, что мы писали)
│ ├── security.py # Модуль фильтрации команд и проверки инъекций
│ └── firewall.py # Скрипты взаимодействия с iptables
├── actions/ # Скрипты исполнения (то, чем управляет OpenClaw)
│ ├── init.py
│ ├── ai_logic.py # Интеграция с вашей нейросетью
│ └── system_cmds.py # Перезагрузка, статус, логи
├── logs/ # Папка для логов (защищена, доступ только боту)
├── scripts/ # Системные утилиты
│ ├── setup.sh # Скрипт автоматической установки зависимостей
│ └── shadow-unlock.sh # Тот самый скрипт экстренного сброса фаервола
├── omemo_keys/ # База данных ключей OMEMO (создается автоматически)
├── shadowclaw-guard.service # Файл юнита для Systemd
├── requirements.txt # Список библиотек (slixmpp[omemo], etc.)
└── README.md # Документация, которую мы составили
Используйте код с осторожностью.

🛠 Как быстро создать эту структуру одной командой?
Зайди в терминал сервера и выполни этот «паровоз» команд (от имени root или через sudo):
bash
mkdir -p /opt/shadowclaw/{config,core,actions,logs,scripts,certs,omemo_keys} &&touch /opt/shadowclaw/{requirements.txt,README.md,shadowclaw-guard.service} &&touch /opt/shadowclaw/core/{init.py,bot.py,security.py,firewall.py} &&touch /opt/shadowclaw/actions/{init.py,ai_logic.py,system_cmds.py} &&chmod +x /opt/shadowclaw/scripts/shadow-unlock.sh &&echo "Структура ShadowClaw создана успешно."
Используйте код с осторожностью.

🛡 Важные рекомендации по правам доступа (Паранойя-стайл):
Владелец: Создай отдельного системного пользователя shadowuser, который не имеет оболочки (shell) и прав root.
sudo useradd -r -s /usr/sbin/nologin shadowuser
Права:
Папка certs/ и config/ должны быть доступны только для чтения: chmod 400.
Папка logs/ и omemo_keys/ должны быть доступны для записи только пользователю shadowuser.
Изоляция: Запускай бота внутри виртуального окружения .venv, чтобы системные обновления Python не сломали твой «Бункер».

В текущей базовой реализации, которую мы собрали, работает только текстовое управление. Однако архитектура XMPP и клиент Conversations поддерживают передачу файлов (через протокол HTTP File Upload или Jingle).
Чтобы ваша связка могла принимать PDF, TXT и аудио, нужно доработать два компонента: сервер и код бота.

  1. Настройка сервера (Prosody)
    Для передачи файлов в XMPP используется модуль mod_http_file_upload. Вам нужно включить его в prosody.cfg.lua, чтобы сервер выделил «ячейку» для хранения передаваемых файлов.
    lua
    Component "upload.uhrifnjci4n94cimo.ru" "http_file_upload"
    http_file_upload_quota = 100 * 1024 * 1024 -- Лимит 100 МБ на пользователя
    http_file_upload_file_size_limit = 20 * 1024 * 1024 -- Макс. размер файла 20 МБ
    Используйте код с осторожностью.
  2. Доработка бота (core/bot.py)
    Бот должен научиться ловить не только текст (body), но и ссылки на файлы (XEP-0363). В XMPP, когда вы кидаете файл в чат, Conversations загружает его на сервер, а боту прилетает сообщение со специальной ссылкой.
    Логика для бота:
    Бот видит входящий URL.
    Проверяет расширение (.pdf, .txt, .mp3).
    Скачивает файл в папку /opt/shadowclaw/inbox/.
    Передает путь к файлу в OpenClaw для анализа.
  3. Нюанс с OMEMO (Важно!)
    Передача файлов в OMEMO сложнее обычного текста. Современные клиенты (Conversations) шифруют сам файл перед загрузкой. Бот должен уметь:
    Скачать зашифрованный файл.
    Использовать ключ (который придет в метаданных сообщения), чтобы расшифровать его на диске.
    Можно ли это сделать?
    Да. Это превратит ShadowClaw в полноценный интерфейс для работы с документами. Вы сможете скинуть PDF с документацией, а в ответ получить резюме от OpenClaw.
    Техническая сложность:
    Реализация дешифровки файлов OMEMO в Python требует использования библиотеки python-omemo или omemo-dr. Это добавит еще ~50 строк кода в модуль bot.py.

Чтобы ShadowClaw мог принимать файлы (PDF, аудио, TXT), нам нужно превратить его из простого терминала в «умный почтовый ящик». Для этого мы сначала настроим сервер для хранения файлов, а затем научим бота их скачивать и расшифровывать.
Шаг 1: Настройка сервера (Prosody mod_http_file_upload)
Этот модуль позволяет клиенту (тебе) загрузить файл на сервер, а боту — получить на него ссылку.
Установите модуль (если его нет в системе):
sudo apt install prosody-modules (или скачайте mod_http_file_upload.lua в папку сообщества).
Отредактируйте /etc/prosody/prosody.cfg.lua:
Добавьте компонент в конец файла:
lua
Component "upload.uhrifnjci4n94cimo.ru" "http_file_upload"
-- Настройки безопасности
http_file_upload_quota = 500 * 1024 * 1024 -- Общий лимит 500 МБ
http_file_upload_file_size_limit = 50 * 1024 * 1024 -- Лимит на 1 файл 50 МБ
http_file_upload_expire_after = 86400 -- Удалять файл через 24 часа

-- Порт для загрузки (можно оставить 5280 или проксировать через Nginx)
http_external_url = "https://uhrifnjci4n94cimo.ru"

Используйте код с осторожностью.

Откройте порт 5281 в вашем Firewall:
sudo ufw allow 5281/tcp
Шаг 2: Доработка бота (core/bot.py) для приема файлов
В XMPP передача файла выглядит как сообщение со специальным расширением OOB (Out of Band Data) или Stateless Media Sharing.
Добавьте этот метод в класс ShadowClawBot:
python
import requests # Не забудь добавить в requirements.txt

class ShadowClawBot(ClientXMPP):

... (предыдущий код)

def __init__(self, jid, password):
    super().__init__(jid, password)
    # Регистрируем плагины для работы с контентом
    self.register_plugin('xep_0066') # Out of Band Data (URLs)
    self.register_plugin('xep_0363') # HTTP File Upload

def handle_incoming(self, msg):
    # Проверяем, есть ли в сообщении ссылка на файл (OOB)
    oob_url = msg['oob']['url']
    if oob_url:
        self.download_secure_file(oob_url, msg['from'])
        return

    # Если это просто текст — старая логика
    super().handle_incoming(msg)

def download_secure_file(self, url, sender):
    """Скачивание файла в защищенную папку инбокса"""
    if str(sender).split('/')[0] != MASTER_JID:
        return # Игнорируем файлы от чужих

    filename = url.split('/')[-1]
    save_path = f"/opt/shadowclaw/inbox/{filename}"

    try:
        r = requests.get(url, stream=True, timeout=30)
        if r.status_code == 200:
            with open(save_path, 'wb') as f:
                for chunk in r.iter_content(1024):
                    f.write(chunk)

            self.send_message(mto=MASTER_JID, 
                              mbody=f"📥 Файл '{filename}' принят и передан в OpenClaw.")
            # ТУТ: Вызов функции OpenClaw для обработки файла
        else:
            self.send_message(mto=MASTER_JID, mbody="❌ Ошибка при скачивании файла.")
    except Exception as e:
        logging.error(f"File download error: {e}")

Используйте код с осторожностью.

Шаг 3: Проблема OMEMO-шифрования файлов
Когда ты отправляешь файл через Conversations, он по умолчанию зашифрован ключом AES. Бот скачает «кашу».
Чтобы бот мог читать PDF/TXT:
Простой путь (Паранойя Lite): В настройках чата с ботом в Conversations временно отключи шифрование для передачи больших файлов (если доверяешь TLS-каналу сервера).
Хардкорный путь (True Paranoid): Использовать библиотеку omemo-dr. Бот должен извлечь AES-ключ из тела XMPP-сообщения и расшифровать файл локально.
📦 Обновленная структура папок
Теперь в /opt/shadowclaw/ должна появиться папка:
inbox/ — сюда бот складывает файлы.
mkdir -p /opt/shadowclaw/inbox && chown shadowuser /opt/shadowclaw/inbox

В этой схеме ShadowClaw становится «умным курьером». Его задача — не просто скачать файл, а подготовить «пакет данных» для OpenClaw и уведомить его: «Хозяин прислал новый материал, работай».
Для этого мы создадим механизм передачи контекста.

  1. Доработка actions/ai_logic.py (Интеграция)
    Этот модуль будет брать присланный файл или текст и «скармливать» его OpenClaw (через API, сокет или общую папку).
    python
    import os
    import shutil
    import json
    import logging

Пути к папкам взаимодействия

INBOX_DIR = "/opt/shadowclaw/inbox"
OPENCLAW_INPUT = "/opt/openclaw/incoming_context" # Куда OpenClaw смотрит в ожидании задач

class AIBridge:
@staticmethod
def send_to_openclaw(content_type, data, filename=None):
"""
Универсальный метод передачи данных в OpenClaw
content_type: 'text' или 'file'
"""
try:
if content_type == 'text':

Создаем задачу для OpenClaw из текстового сообщения

        task = {
            "type": "prompt",
            "payload": data,
            "timestamp": os.times()[4]
        }
        with open(f"{OPENCLAW_INPUT}/task_{int(task['timestamp'])}.json", "w") as f:
            json.dump(task, f)
        return "✅ Текст передан в OpenClaw."

    elif content_type == 'file':
        # Перемещаем файл в рабочую зону OpenClaw
        dest_path = os.path.join(OPENCLAW_INPUT, filename)
        shutil.move(data, dest_path)

        # Создаем уведомление о файле
        meta = {
            "type": "file_process",
            "file_path": dest_path,
            "filename": filename
        }
        with open(f"{dest_path}.json", "w") as f:
            json.dump(meta, f)
        return f"✅ Файл '{filename}' успешно доставлен в OpenClaw."

except Exception as e:
    logging.error(f"Bridge Error: {e}")
    return f"❌ Ошибка передачи в OpenClaw: {str(e)}"

Используйте код с осторожностью.

  1. Обновленный core/bot.py (Логика приема всего)
    Теперь бот автоматически понимает: если пришел текст — это команда/вопрос, если файл — это данные для анализа.
    python
    def handle_incoming(self, msg):

1. Проверка безопасности (JID и инъекции)

is_safe, result = self.guard.verify_message(msg)
if not is_safe:
    self.send_message(mto=MASTER_JID, mbody=f"🚨 {result}")
    return

# 2. Проверка на наличие файла (OOB / HTTP Upload)
oob_url = msg['oob']['url']
if oob_url:
    # Скачиваем файл
    filename = oob_url.split('/')[-1]
    temp_path = f"/opt/shadowclaw/inbox/{filename}"

    if self.download_file(oob_url, temp_path):
        # Передаем файл в OpenClaw через мост
        res = AIBridge.send_to_openclaw('file', temp_path, filename)
        self.send_message(mto=MASTER_JID, mbody=res)
    return

# 3. Если это просто текст
body = msg['body'].strip()

# Если текст есть в белом списке команд (status, panic и т.д.) - исполняем
if body in COMMAND_MAP:
    response = COMMAND_MAP[body]()
else:
    # Если текста нет в командах - значит это промпт/данные для OpenClaw
    response = AIBridge.send_to_openclaw('text', body)

self.send_message(mto=MASTER_JID, mbody=response)

Используйте код с осторожностью.

  1. Как это работает в жизни (User Flow)
    Текст: Ты пишешь в чат: "Проанализируй этот отчет".
    ShadowClaw: Видит, что это не системная команда (не status), и перекидывает текст в OpenClaw как промпт.
    Файл: Ты прикрепляешь PDF с телефона и жмешь "Отправить".
    ShadowClaw: Ловит URL, скачивает зашифрованный (или нет) файл, кладет его в папку OpenClaw и создает .json файл-описание.
    Результат: OpenClaw видит новый файл в своей папке, обрабатывает его и (если настроен обратный канал) просит ShadowClaw отправить тебе ответ.

Этот модуль — «иммунная система» ShadowClaw. Его задача — не просто проверить команду, а препарировать её на наличие любых признаков враждебного кода (Injection), прежде чем она попадет в ядро системы.
🛡 Файл core/security.py
Разместите этот код в указанной папке. Он реализует логику «Паранойя-фильтра».
python
import re
import logging

Настройка логирования попыток взлома

security_logger = logging.getLogger("ShadowClaw_Security")

class SecurityGuard:
def init(self, master_jid):
self.master_jid = master_jid

Белый список допустимых команд (строгое соответствие)

    self.whitelist = ["status", "check_temp", "restart_stack", "uptime", "ai_logs"]

    # Регулярка для детекта опасных символов (Shell Injection, Chaining, Redirection)
    # Блокирует: ; & | ` $ > < ( ) [ ] { }        self.danger_pattern = re.compile(r"[;&|`\$><\(\)\[\]{}\\]")

    # Паттерны подозрительных путей и команд
    self.blacklisted_keywords = [
        "sudo", "rm ", "chmod", "chown", "curl", "wget", 
        "nc ", "netcat", "eval", "exec", "/etc/", "/root/", "../"
    ]

def verify_message(self, msg):
    """
    Комплексная проверка входящего сообщения.
    Возвращает (True, command) если всё ок, или (False, reason) при угрозе.
    """
    sender = str(msg['from']).split('/')[0]
    body = msg['body'].strip()

    # 1. Проверка JID отправителя (Identity)
    if sender != self.master_jid:
        reason = f"AUTH_FAILURE: Попытка доступа с {sender}"
        self._log_threat(reason)
        return False, reason

    # 2. Проверка на пустое сообщение
    if not body:
        return False, "EMPTY_MESSAGE"

    # 3. Детект спецсимволов (Injection Detection)
    if self.danger_pattern.search(body):
        reason = f"INJECTION_ATTACK: Обнаружены запрещенные символы в '{body}'"
        self._log_threat(reason)
        return False, reason

    # 4. Проверка на ключевые слова (Keyword Blacklist)
    lowered_body = body.lower()
    for word in self.blacklisted_keywords:
        if word in lowered_body:
            reason = f"DANGEROUS_KEYWORD: Обнаружено слово '{word}'"
            self._log_threat(reason)
            return False, reason

    # 5. Сверка с Белым Списком (Strict Whitelist)
    if body not in self.whitelist:
        reason = f"UNKNOWN_COMMAND: Команда '{body}' не в списке разрешенных"
        # Это не обязательно атака, просто логируем как ошибку
        return False, reason

    return True, body

def _log_threat(self, reason):
    security_logger.critical(f"!!! SECURITY ALERT !!! {reason}")
    # Здесь можно добавить вызов функции блокировки IP через firewall.py

Пример инициализации:

guard = SecurityGuard("[email protected]")

Используйте код с осторожностью.

🧠 Почему это безопасно?
Двухуровневый отказ: Сначала мы ищем признаки «грязного» ввода (спецсимволы), а затем проверяем соответствие «белому списку». Даже если вы добавите в список сложную команду, регулярка не даст протащить в неё лишний аргумент.
Case-Insensitive Blacklist: Проверка на sudo или /etc/ идет в нижнем регистре, чтобы атакующий не обошел фильтр через SuDo или ETc.
No Shell Execution: Этот модуль подразумевает, что вы никогда не используете os.system(body) или eval(body). Команды из белого списка должны вызывать заранее написанные функции (Hardcoded mappings).

Этот модуль — «руки» ShadowClaw. Важнейшее правило безопасности: мы никогда не передаем текст из чата напрямую в командную строку. Вместо этого мы используем жестко заданные функции, которые возвращают только нужные данные.
🛠 Файл actions/system_cmds.py
Размести этот код в папке actions/. Он использует библиотеку subprocess с параметром shell=False, что исключает возможность инъекции команд.
python
import subprocess
import logging
import os

Настройка логов для действий

action_logger = logging.getLogger("ShadowClaw_Actions")

class SystemActions:
"""
Класс безопасных системных вызовов.
Все аргументы команд предопределены и не зависят от ввода пользователя.
"""

@staticmethod
def get_status():
    """Проверка аптайма и общей нагрузки системы"""
    try:
        # Выполняем только конкретную бинарную команду без оболочки (shell=False)
        res = subprocess.check_output(["uptime", "-p"], stderr=subprocess.STDOUT, timeout=5)
        return f"✅ Система в сети. {res.decode('utf-8').strip()}"
    except Exception as e:
        return f"❌ Ошибка статуса: {str(e)}"

@staticmethod
def get_temp():
    """Чтение температуры CPU (и GPU, если есть nvidia-smi)"""
    try:
        # Читаем системный файл напрямую (безопаснее, чем вызов сторонних утилит)
        with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
            temp = int(f.read()) / 1000

        report = f"🌡 CPU Temp: {temp:.1f}°C"

        # Если есть видеокарта NVIDIA (для OpenClaw актуально)
        if os.path.exists("/usr/bin/nvidia-smi"):
            gpu = subprocess.check_output(
                ["nvidia-smi", "--query-gpu=temperature.gpu", "--format=csv,noheader,nounits"],
                timeout=5
            )
            report += f" | GPU Temp: {gpu.decode('utf-8').strip()}°C"

        return report
    except Exception as e:
        return f"⚠️ Ошибка чтения датчиков: {str(e)}"

@staticmethod
def restart_ai_stack():
    """Перезапуск Docker-контейнеров OpenClaw"""
    try:
        # Требует настройки sudoers для пользователя shadowuser
        subprocess.run(["sudo", "/usr/bin/docker", "restart", "openclaw_container"], 
                       check=True, timeout=30)
        return "♻️ Стек OpenClaw успешно перезапущен."
    except subprocess.CalledProcessError:
        return "❌ Ошибка при перезапуске контейнера. Проверьте логи sudo."
    except Exception as e:
        return f"❌ Критическая ошибка: {str(e)}"

@staticmethod
def get_ai_logs():
    """Последние 10 строк логов OpenClaw"""
    try:
        # Читаем только хвост файла, никакой передачи путей извне!
        res = subprocess.check_output(["tail", "-n", "10", "/opt/openclaw/logs/main.log"], 
                                      timeout=5)
        return f"📝 Последние логи:\n{res.decode('utf-8')}"
    except Exception as e:
        return f"❌ Не удалось прочитать логи: {str(e)}"

Маппинг команд из SecurityGuard на функции

COMMAND_MAP = {
"status": SystemActions.get_status,
"check_temp": SystemActions.get_temp,
"restart_stack": SystemActions.restart_ai_stack,
"ai_logs": SystemActions.get_ai_logs
}
Используйте код с осторожностью.

🛡 Почему это «бронированный» код?
Отсутствие shell=True: Мы передаем команды списком ["uptime", "-p"]. Это значит, что даже если в строку попадет ; rm -rf, система воспримет это не как новую команду, а как имя файла или аргумент, и просто выдаст ошибку.
Таймауты: У каждой команды есть timeout=5. Если процесс зависнет (или его зациклят), бот не «умрет», а просто прервет выполнение.
Изоляция путей: Все пути к логам и системным файлам прописаны жестко внутри кода. Пользователь мессенджера не может сказать «прочитай мне другой файл».
Sudo-минимализм: Для перезагрузки Docker используется sudo, но в /etc/sudoers (как мы обсуждали ранее) должно быть разрешено выполнение только конкретной команды docker restart openclaw_container.

Финальный аккорд архитектуры ShadowClaw. Этот файл объединяет наш «иммунитет» (security.py) и «инструменты» (system_cmds.py) в единый асинхронный процесс с поддержкой шифрования OMEMO.
🤖 Файл core/bot.py
Размести этот код в core/bot.py. Он является входной точкой (entrypoint) всей системы.
python
import logging
import asyncio
from slixmpp import ClientXMPP
from slixmpp.plugins.xep_0384 import TrustLevel

Импортируем наши защитные модули

from core.security import SecurityGuard
from actions.system_cmds import COMMAND_MAP
from config.shadow_config import JID, PASSWORD, SERVER_HOST, SERVER_PORT, MASTER_JID

class ShadowClawBot(ClientXMPP):
def init(self, jid, password):
super().init(jid, password)

    # Инициализация защиты
    self.guard = SecurityGuard(MASTER_JID)

    # Регистрация XMPP плагинов
    self.register_plugin('xep_0030') # Service Discovery
    self.register_plugin('xep_0163') # PubSub (нужен для OMEMO)
    self.register_plugin('xep_0384', { # OMEMO Encryption
        'data_dir': './omemo_keys' 
    })

    # Обработчики событий
    self.add_event_handler("session_start", self.start)
    self.add_event_handler("message", self.handle_incoming)

async def start(self, event):
    """Запуск сессии и анонс OMEMO"""
    await self['xep_0384'].announce_support()
    self.send_presence()
    await self.get_roster()

    # Принудительный Траст мастер-аккаунта (TOFU)
    self['xep_0384'].set_trust(MASTER_JID, trust_level=TrustLevel.TRUSTED)
    print(f"[🛡️] ShadowClaw активен. Ожидаю команды на порту {SERVER_PORT}...")

def handle_incoming(self, msg):
    """Основной цикл обработки сообщений"""
    # Игнорируем групповые чаты и пустые типы (только direct chat)
    if msg['type'] not in ('chat', 'normal'):
        return

    # 1. Проверка безопасности (Identity + Injection + Whitelist)
    is_safe, result = self.guard.verify_message(msg)

    if not is_safe:
        # Если это серьезная угроза (инъекция), шлем Alarm
        if "ATTACK" in result or "AUTH" in result:
            self.send_message(
                mto=MASTER_JID, 
                mbody=f"🚨 КРИТИЧЕСКАЯ УГРОЗА: {result}", 
                mtype='chat'
            )
        return

    # 2. Выполнение команды (результат проверки - чистая команда)
    command_name = result
    try:
        # Берем функцию из маппинга в actions/system_cmds.py
        action_func = COMMAND_MAP.get(command_name)
        if action_func:
            response = action_func()
            self.send_message(mto=MASTER_JID, mbody=response, mtype='chat')
        else:
            self.send_message(mto=MASTER_JID, mbody="⚠️ Ошибка: Обработчик не найден.", mtype='chat')
    except Exception as e:
        self.send_message(mto=MASTER_JID, mbody=f"❌ Сбой выполнения: {str(e)}", mtype='chat')

if name == 'main':

Настройка логирования (вывод в консоль и файл)

1
2
3
4
5
6
7
logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')

xmpp = ShadowClawBot(JID, PASSWORD)

# Принудительное использование TLS и скрытого порта
xmpp.connect(address=(SERVER_HOST, SERVER_PORT), use_ssl=True)
xmpp.process(forever=True)

Используйте код с осторожностью.

🛡 Что делает этот код «Бункером»?
Автономный Траст: Бот автоматически устанавливает уровень доверия для вашего MASTER_JID, что избавляет от необходимости вручную подтверждать ключи в базе данных.
Декоратор безопасности: Сообщение сначала проходит через verify_message (сито из регулярок и белых списков), и только в случае успеха попадает в COMMAND_MAP.
Изоляция типов: Бот игнорирует сообщения типа groupchat или headline, защищаясь от попыток обмануть логику через групповые рассылки.
Разделение ответственности: Бот не знает, как перезагрузить сервер; он просто дергает рычаг restart_stack, который описан в другом модуле.

Вот финальный кирпич в фундамент ShadowClaw — файл конфигурации. Чтобы сохранить «параноидальный» режим, мы разделим сетевые настройки и учетные данные.
⚙️ Файл config/shadow_config.py
Создай этот файл в папке config/. Обрати внимание: пароли и JID должны быть в кавычках.
python

--- СЕТЕВЫЕ НАСТРОЙКИ (STEALTH LAYER) ---

SERVER_HOST = "uhrifnjci4n94cimo.ru" # Твой домен
SERVER_PORT = 44331 # Скрытый порт (измени на свой, если нужно)

--- УЧЕТНЫЕ ДАННЫЕ (IDENTITY LAYER) ---

JID и пароль самого бота (созданные через prosodyctl)

JID = "[email protected]"
PASSWORD = "SECRET_BOT_PASSWORD"

Твой личный JID (только с него бот примет команды)

MASTER_JID = "[email protected]"

--- ПУТИ (ISOLATION LAYER) ---

Путь к базе ключей OMEMO (бот создаст папку сам)

OMEMO_DB_PATH = "./omemo_keys"

Путь к логам выполнения (для аудита)

LOG_FILE_PATH = "./logs/shadowclaw.log"

--- ПАРАМЕТРЫ ЗАЩИТЫ (SECURITY LAYER) ---

Максимальное количество неверных команд до активации DoS-защиты

MAX_ATTEMPTS = 3

Время временной блокировки в секундах (1 час)

BAN_TIME = 3600
Используйте код с осторожностью.

🛡️ Финальный совет по безопасности (Hardening)
После того как ты заполнишь этот файл, выполни команду:
bash
chmod 600 /opt/shadowclaw/config/shadow_config.py
Используйте код с осторожностью.

Это ограничит права доступа так, что только владелец файла сможет его прочитать. Никакие другие пользователи или процессы в системе не увидят твои пароли.
🏁 Что делать дальше?
Теперь всё готово к запуску. Твой план действий:
Убедись, что Prosody запущен и слушает порт 44331.
Активируй виртуальное окружение: source .venv/bin/activate.
Запусти бота: python3 -m core.bot.
Отправь со смартфона (через Conversations) первое зашифрованное status.

Чтобы Conversations на Android успешно пробился через нестандартный порт к вашему «Бункеру», нужно настроить его чуть внимательнее, чем обычный мессенджер.
📱 Памятка по настройке Conversations (Android)
Выполните эти 5 шагов для первой синхронизации с ShadowClaw:

  1. Добавление аккаунта (Ваш JID)
    Нажмите + → Добавить существующий аккаунт.
    Введите ваш JID: [email protected] и пароль, который вы задали в prosodyctl.
    Важно: Не нажимайте сразу «Вход». Нажмите на иконку шестеренки или «Расширенные настройки» (зависит от версии).
  2. Пробивка через порт (Connection Settings)
    В расширенных настройках аккаунта найдите пункт «Hostname» (Хост) и «Port» (Порт):
    Хост: uhrifnjci4n94cimo.ru
    Порт: 44331 (обязательно укажите ваш скрытый порт, иначе клиент будет бесконечно стучаться в закрытый 5222).
  3. Активация OMEMO
    Найдите в списке контактов бота [email protected] (если его нет, добавьте через «Новый контакт»).
    Откройте окно чата с ботом.
    Нажмите на иконку замка в поле ввода сообщения или в меню чата (три точки) выберите «Выбрать тип шифрования» → OMEMO.
  4. Ритуал доверия (Key Trust)
    Отправьте боту любое слово, например ping.
    Бот пришлет ответ (или вы увидите системное сообщение о новом ключе).
    Нажмите на заголовок чата (имя бота) → выберите пункт «Ключи OMEMO» (OMEMO Fingerprints).
    Вы увидите длинный шестнадцатеричный код. Переключите тумблер в положение «Доверять» (Trust).
    Без этого шага бот не сможет расшифровать ваши команды, а вы — его ответы.
  5. Фоновая работа
    Чтобы связь не рвалась, когда телефон «спит»:
    Зайдите в настройки Android → Приложения → Conversations.
    Выберите «Экономия заряда батареи» → «Не экономить» (Unrestricted).
    🚀 Всё готово!
    Теперь ваш канал связи выглядит так:
    Смартфон (OMEMO) 🔒 → Port 44331 🚪 → ShadowClaw Guard 🧠 → OpenClaw AI 🐾
    Если возникнут вопросы по логам или добавлению новых «тяжелых» команд для ИИ — я на связи.

С позиции «безопасника с параноей» — да, любой бэкап в открытом виде является критической уязвимостью. Если хакер получит доступ к архиву бэкапа, он узнает ваш секретный домен, JID-ы и, что хуже всего, может попытаться перехватить ключи OMEMO.
Чтобы превратить эту «пяту» в «броню», мы применим симметричное шифрование AES-256 прямо в процессе создания бэкапа. Файл на диске будет выглядеть как нечитаемый мусор, который невозможно открыть без мастер-пароля.
🛡️ Скрипт «ShadowBackup» (scripts/secure-backup.sh)
Этот скрипт упаковывает конфиги и ключи, шифрует их через openssl и удаляет временные файлы.
bash

!/bin/bash

--- НАСТРОЙКИ ---

SOURCE_DIR="/opt/shadowclaw"
BACKUP_DEST="/var/backups/shadowclaw"
DATE=$(date +%Y-%m-%d_%H-%M)
OUT_FILE="$BACKUP_DEST/shadow_backup_$DATE.tar.gz.enc"

!!! ПАРОЛЬ (Лучше вводить вручную, но для автоматизации используем переменную среды)

ВАЖНО: Не храни пароль в самом скрипте в открытом виде на постоянку!

export BACKUP_PASS="ВАШ_ОЧЕНЬ_ДЛИННЫЙ_ПАРОЛЬ_ИЗ_32_СИМВОЛОВ"

Создаем папку бэкапа, если её нет

mkdir -p "$BACKUP_DEST"
chmod 700 "$BACKUP_DEST"

echo "[*] Начинаю зашифрованный бэкап ShadowClaw..."

Архивация + Шифрование "на лету" (AES-256-CBC)

tar -cz -C "$SOURCE_DIR" config/ core/ omemo_keys/ scripts/ |openssl enc -aes-256-cbc -salt -pbkdf2 -iter 100000 -out "$OUT_FILE" -pass env:BACKUP_PASS

if [ $? -eq 0 ]; then
echo "[+] Бэкап успешно создан и зашифрован: $OUT_FILE"

Ограничиваем права на файл бэкапа

chmod 600 "$OUT_FILE"

else
echo "[!] ОШИБКА: Бэкап провален!"
exit 1
fi

Удаляем бэкапы старше 30 дней

find "$BACKUP_DEST" -type f -mtime +30 -name "*.enc" -delete

Очистка переменной пароля из памяти

unset BACKUP_PASS
Используйте код с осторожностью.

🗝️ Как сделать это максимально безопасно?
GPG вместо пароля: Если вы совсем параноик, используйте GPG-ключи. Тогда бэкап можно будет расшифровать только вашим приватным ключом, которого вообще нет на сервере.
Off-site Storage: Никогда не храните бэкапы на том же диске, где лежит основная система. Используйте scp или rsync для пересылки зашифрованного .enc файла на другое устройство сразу после создания.
Изоляция: Скрипт должен запускаться от имени root, но доступ к папке $BACKUP_DEST должен быть закрыт для всех остальных пользователей.
🔄 Как восстановить данные из такого бэкапа?
Если сервер «сгорел», установите ShadowClaw на новый и выполните:
bash
openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -in shadow_backup_XXXX.tar.gz.enc | tar xz -C /opt/shadowclaw
Используйте код с осторожностью.

Система спросит пароль, и только после этого файлы появятся в папке.

Это финальный предохранитель системы. Функция «Panic Button» (Кнопка паники) превращает ShadowClaw из простого шлюза в «цифровой шрам», который при активации стирает все следы коммуникации и ключи шифрования, делая невозможным восстановление переписки даже при физическом изъятии сервера.
🛡️ Логика работы «Panic Button»
Мгновенный обрыв связи: Бот отключается от XMPP-сервера.
Затирка ключей OMEMO: Папка omemo_keys удаляется методом многократной перезаписи (если файловая система позволяет).
Очистка логов: Удаляются логи ShadowClaw и системные логи (auth.log), чтобы нельзя было восстановить IP-адреса подключений.
Самоликвидация сессии: Остановка сервиса systemd.

  1. Добавление в actions/system_cmds.py
    Добавь эту функцию в конец файла. Мы будем использовать утилиту shred (стандарт в Linux для надежного удаления файлов).
    python
    import shutil

class SystemActions:

... (предыдущие функции)

@staticmethod
def panic_shredder():
    """Экстренное уничтожение данных и остановка сервиса"""
    try:
        # 1. Пути для уничтожения
        paths_to_wipe = [
            "/opt/shadowclaw/omemo_keys",
            "/opt/shadowclaw/logs",
            "/var/log/prosody/prosody.log"
        ]

        # 2. Используем shred для каждого файла (если это файлы) 
        # или рекурсивно удаляем папки
        for path in paths_to_wipe:
            if os.path.exists(path):
                if os.path.isdir(path):
                    shutil.rmtree(path)
                else:
                    subprocess.run(["shred", "-u", "-n", "3", path])

        # 3. Финальный аккорд: самоубийство сервиса через 2 секунды
        # (даем время отправить прощальное сообщение)
        subprocess.Popen("sleep 2 && sudo systemctl stop shadowclaw-guard", shell=True)

        return "☣️ PANIC ACTIVATED: Данные уничтожены. Связь прерывается. Прощайте."
    except Exception as e:
        return f"⚠️ ОШИБКА ПАНИКИ: {str(e)}"

Используйте код с осторожностью.

  1. Регистрация в COMMAND_MAP
    Не забудь добавить команду в словарь:
    python
    COMMAND_MAP = {

... другие команды

"panic": SystemActions.panic_shredder

}
Используйте код с осторожностью.

  1. Добавление в Белый список (core/security.py)
    Чтобы SecurityGuard пропустил эту команду:
    python
    self.whitelist = ["status", "check_temp", "restart_stack", "uptime", "ai_logs", "panic"]
    Используйте код с осторожностью.

⚠️ Предупреждение Параноика (Double-Edged Sword)
Ложные срабатывания: Если вы случайно нажмете panic на смартфоне (или кто-то подберет ваш телефон), восстановить доступ к боту без физического доступа к серверу и бэкапа (который мы сделали ранее) будет невозможно.
Права Sudo: Для остановки сервиса боту снова понадобятся права в /etc/sudoers:
shadowuser ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop shadowclaw-guard
🧪 Тестирование
После настройки отправь боту: panic.
Если всё сделано верно, ты получишь последнее сообщение, и статус бота в Conversations станет «Offline» навсегда. Для «воскрешения» системы придется заходить по SSH и восстанавливать папку omemo_keys из зашифрованного бэкапа.

Вот твой «Золотой паспорт» проекта ShadowClaw. Сохрани этот конфиг в зашифрованном менеджере паролей или распечатай и положи в сейф. Это единственный документ, который позволит тебе восстановить контроль над «Бункером», если ты забудешь детали через месяц.
📋 Паспорт проекта ShadowClaw
Параметр Значение / Путь Примечание
Проект ShadowClaw v2.1 Secure Stealth Gateway for AI

...............
......................
.............................
.......................................
...............................................

Рад был помочь в строительстве этого «цифрового бункера»! Теперь твой ИИ-стек ShadowClaw защищен не хуже банковского шлюза: скрытые порты, сквозное шифрование OMEMO, активная защита от DoS и кнопка самоликвидации.
Ты перевел общение с нейросетями из публичного (и уязвимого) поля в зону твоего полного суверенного контроля. Это и есть настоящий «гиковский» подход к приватности.
Последний совет: Раз в месяц проверяй, что зашифрованный бэкап открывается на другом устройстве — это лучшая страховка от любых аппаратных сбоев.

Edit

Pub: 22 Mar 2026 11:15 UTC

Edit: 22 Mar 2026 11:30 UTC

Views: 12