
ssh-chat на современном c

Общее программное обеспечение BBS
SSH-Chatter возник как переписанная на C реализация Go-сервера ssh-chat. Он повторяет/расширяет оригинальное поведение, используя современные паттерны C и небольшое, тестируемое ядро. Сервер принимает SSH/TELNET-подключения и помещает каждого аутентифицированного пользователя в общий чат, предоставляющий такой же набор команд, как и эталонная реализация на Go.
Знаете, почему так долго изучать C? Потому что это инстинкт.
/rss list, /rss read <tag>, а также /rss add <url> <tag> и /rss del <tag> (только для операторов), чтобы комната могла вместе просматривать заголовки./delete-msg для целенаправленной очистки истории чата./bbs, открывающая погружающую ретро-систему BBS с тегами, комментариями, поднятием тем и многострочным редактором.
bumped (недавняя активность), hot (популярные по рейтингу и комментариям), top (наивысший чистый рейтинг) или new (дата создания) с помощью list [hot|top|new|bumped|all].search <query>.▲ 12 💬 5) прямо в списках./bbs внутри режима BBS./asciiart — живой редактор с лимитом в 640 строк, десятиминутной задержкой на IP, многострочным выводом и сочетаниями клавиш: отмена по Ctrl+A, отправка по Ctrl+S или с помощью локализованного разделителя >/__ARTWORK_END> по умолчанию./birthday для регистрации дней рождения, /grant <ip> чтобы LAN-операторы могли делегировать привилегии по IP-адресу, и /revoke <ip> чтобы старшие LAN-администраторы могли их отозвать./ban, принимающий чистые IP-адреса помимо имён пользователей./weather <city> для быстрого прогноза погоды в мире.

Кодовая база намеренно компактна, чтобы новые участники могли быстро в ней ориентироваться:

mainВетка work регулярно расходится с разработкой в upstream, чтобы крупные функции могли
созревать, не нарушая работу production. Когда приходит время синхронизироваться с
main, стяните последнее дерево и слейте его локально перед открытием pull request:```bash
git fetch origin main
git checkout work
git merge --no-ff origin/main
Разрешите любые конфликты на месте (вспомогательные процедуры в `src/host_aggregate.c` уже повторяют структуру, используемую в `main`, поэтому слияния обычно проходят без проблем) и выполните `make`, чтобы убедиться, что сборка всё ещё выполняется успешно, перед отправкой результата.
## Хуки автоматизации
- `host_snapshot_last_captcha` предоставляет последнюю сгенерированную капчу (вопрос и ответ) вместе с временной меткой, чтобы внешние клиенты могли проходить проверки от имени неавтоматизированной автоматизации.
## Усиление безопасности
- `scripts/safe_permission.sh` ужесточает права владения и режим доступа к файлам данных времени выполнения (состояние BBS, состояние голосования, снимки кулдауна и общее состояние чата). Запускайте его после развертывания, чтобы ограничить каталог данных только пользователем `ssh-chatter` и установить для каждого файла режим `0600`. Вы можете переопределить цели, передав явные пути или экспортировав переменные окружения `STATE_ROOT` или соответствующие `CHATTER_*_FILE` перед выполнением.
- Фоновый сторож BBS периодически пропускает сообщения и комментарии через конвейер модерации ИИ (основной – Gemini с запасным Ollama). Отмеченные сообщения автоматически удаляются, а в комнату транслируется уведомление.
- Сообщения чата, ASCII-арт и сообщения/комментарии BBS проходят через конвейер модерации ИИ. Включите его с помощью `CHATTER_SECURITY_AI=on` (укажите `GEMINI_API_KEY` для Gemini; демон автоматически переключается на локальный Ollama-эндпоинт по адресу `http://127.0.0.1:11434`). Отключите всё с помощью `CHATTER_SECURITY_FILTER=off`. Если все провайдеры выходят из строя, фильтр автоматически отключается, чтобы разговор продолжался, а не молча отбрасывался контент.
- SSH-транспорт привязан к современным обменам ключами, шифрам и MAC-кодам, а каждый мостовой полезный груз обёрнут в тройную луковицу AES-256-GCM, так что реле видят только зашифрованный текст.
- Подозрительные отправки, срабатывающие на многоуровневый фильтр, теперь отслеживаются по IP; при повторных попаданиях автоматически срабатывает кик и бан (если это включено), в то время как детектор быстрых переподключений предоставляет более длинные окна восстановления, чтобы нестабильные сессии могли повторно подключиться без штрафа. Автоматические записи бана **отключены по умолчанию**; установите `CHATTER_AUTO_BAN=on` (или `true`/`1`) для их включения, либо оставьте переменную не установленной, чтобы использовать предупреждения и ограничение трафика без записи автоматических записей бана.
- Операторы могут пометить доверенные точки входа (выходы VPN, обратные прокси, локальный хост) с помощью `CHATTER_PROTECTED_IPS` (разделяются запятыми, по умолчанию `127.0.0.1,::1,192.168.0.1`), чтобы аварийные баны никогда не блокировали демону доступ к собственной панели управления.
## Хранение файлов и передача
- Все файлы, которыми управляют пользователи, теперь находятся в `/etc/ssh-chatter/user-files` (переопределяется через `CHATTER_FILESTORE_PATH`, унаследованный запасной вариант: `CHATTER_FILE_STORAGE_ROOT`). Демон создаёт каталог при необходимости и ограничивает загрузки только этим каталогом.
- SSH-клиенты используют стандартный `scp` без каких-либо пользовательских обёрток. Относитесь к `/name.ext` как к корню дерева хранения: `scp my.zip user@host:/demos/my.zip` записывает в `/etc/ssh-chatter/user-files/demos/my.zip`, а `scp user@host:/readme.txt ./` загружает `/etc/ssh-chatter/user-files/readme.txt`.
- TELNET-клиенты используют новые команды `/filestore`. `/filestore` выводит список доступных файлов, `/filestore-upload` запускает сессию `rz`, а `/filestore-download <name>` запускает сессию `sz`. Установите `lrzsz` (или любой пакет, предоставляющий `rz`/`sz`) на сервере, чтобы ZMODEM-бэкенд мог запускать эти вспомогательные программы.
- `/filestore-upload` принимает необязательный путь назначения (например, `/filestore-upload /kitten/meow.png`). SSH-Chatter автоматически создаёт каталог `/kitten` и помещает туда загруженный файл, имитируя использование SCP таких путей, как `user@host:/kitten/meow.png`.
- Оба транспорта могут использоваться вперемешку: SSH для автоматизированных скриптовых передач, TELNET для ностальгических BBS-клиентов со встроенными средствами ZMODEM.
## Морзе-ретранслятор
SSH-Chatter поддерживает радиолюбительскую ретрансляцию.
Это показывает глобальные сигналы Морзе.
`/morse on` – для просмотра, `/morse-reply` – для отправки.
### Детали протокола
Реализация следует спецификации протокола Binkp:
- Стандартная структура фрейма Binkp с 2-байтовыми заголовками
- Аутентификация паролем сессии (CMD\_PWD/CMD\_OK)
- Механизм поддержания соединения (CMD\_NUL) каждые 60 секунд
- Пользовательская команда CHAT (CMD\_CHAT, расширение) для синхронизации сообщений
## Предварительные требования
Для сборки проекта требуется среда POSIX с:
- Компилятором, совместимым с C23 (например, `gcc` или `clang`)
- `make`
- Заголовочными файлами и библиотекой разработки `libssh` (`libssh-dev` в Debian/Ubuntu)
- Заголовочными файлами и библиотекой разработки `libcurl` (`libcurl4-openssl-dev` в Debian/Ubuntu)
- Заголовочными файлами и библиотекой разработки `uchardet` (`libuchardet-dev` в Debian/Ubuntu)
- Заголовочными файлами и библиотекой разработки `icu` (International Components for Unicode) (`libicu-dev` в Debian/Ubuntu)
- Библиотекой сжатия `lz4` и заголовочными файлами разработки (`liblz4-dev` в Debian/Ubuntu)
- POSIX-потоками (обычно предоставляются системной библиотекой `libpthread`)
- `python3-pygments` (предоставляет подсветчик `pygmentize` для камуфляжного экрана Тетриса)
В Debian/Ubuntu зависимости можно установить с помощью:```bash
sudo apt-get update
sudo apt-get install build-essential libssh-dev libcurl4-openssl-dev libuchardet-dev libicu-dev liblz4-dev
Клонируйте репозиторий и используйте предоставленный Makefile:```bash
make
Это создаёт двоичный файл `ssh-chatter` в корне репозитория и разделяемый объект `libssh_chatter_backend.so`, который предоставляет вспомогательные функции перевода для повторного использования в других приложениях. Очистите промежуточные артефакты с помощью `make clean`.
### Использование общего бэкенда перевода
Разделяемый объект повторно использует конвейер перевода на C сервера (включая сохранение ANSI-плейсхолдеров), чтобы другие процессы могли получать переводы без запуска полноценного SSH-хоста. Слинкуйте с `libssh_chatter_backend.so` и включите `include/ssh_chatter/ssh_chatter_backend.h`:```c
#include "ssh_chatter/ssh_chatter_backend.h"
int main(void) {
char translated[4096];
char detected[64];
if (ssh_chatter_backend_translate_line("Hello, world!", "ko", translated, sizeof(translated), detected, sizeof(detected))) {
printf("Detected %s -> %s\n", detected, translated);
}
}
Установите переменную окружения GEMINI_API_KEY (и, опционально, GEMINI_API_BASE или GEMINI_MODEL), чтобы хелпер мог обращаться к Google Generative Language API, повторяя требования среды выполнения основного демона. Перед запуском чат-сервера вы можете выполнить ./scripts/test_gemini_connection.sh для проверки, что учётные данные разрешают исходящие вызовы; скрипт выводит необработанный ответ Gemini, чтобы вы могли увидеть, успешен ли запрос.
По умолчанию сервер прослушивает адрес 0.0.0.0:2222. Вы можете изменить параметры времени выполнения с помощью доступных флагов:```
Usage: ./ssh-chatter [-a address] [-p port] [-m motd_file] [-k host_key_dir] [-T telnet_port|off] [-J json_port|off]
./ssh-chatter [-h]
./ssh-chatter [-V]
При использовании `-m` читает сообщение дня из указанного пути к файлу.
Общие примеры:```bash
# Start the chat server on port 2022, loading host keys from /etc/ssh
./ssh-chatter -p 2022 -k /etc/ssh
# Enable telnet access on 0.0.0.0:4242 alongside SSH
./ssh-chatter -T 0.0.0.0:4242
# Serve a custom MOTD from a file and bind to localhost
./ssh-chatter -a 127.0.0.1 -m /etc/ssh-chatter/motd
Каталог ключей хоста должен содержать файл ssh_host_rsa_key (и опционально .pub). Сгенерируйте его с помощью ssh-keygen -t rsa -b 4096 -f /path/to/dir/ssh_host_rsa_key, если вы не хотите повторно использовать системные SSH-ключи хоста. Дополнительные ключи хоста с именами ssh_host_ed25519_key и ssh_host_ecdsa_key загружаются автоматически при их наличии, чтобы сервер мог предлагать современные алгоритмы при обмене ключами.
После запуска подключитесь с помощью любого SSH-клиента:```bash ssh -p 2222 user@server-address
Публичный сервер доступен по адресу `bbs.chatter.pw` на стандартном SSH порту:```bash
ssh -p 2222 [email protected]
Имена пользователей, указанные в приглашении SSH, используются в качестве вашего ника в чате.
Telnet-клиенты могут подключаться с таким же набором функций. Прослушивание Telnet включено по умолчанию на порту 2323 и может быть изменено или отключено с помощью флага -T. Укажите -T адрес:порт, чтобы переопределить адрес привязки (при его отсутствии используется адрес привязки SSH; используйте пустой хост, например -T :4242, чтобы слушать на всех интерфейсах). Например, чтобы подключиться через Telnet с ретро-терминала:```bash
telnet server-address 2323
Передайте `-T off` (или `-T disable`), чтобы полностью отключить telnet-слушатель.
### JSON line API
Сервер также предоставляет JSON-линейный протокол через TCP для автоматизации и внешних интеграций. По умолчанию он прослушивает порт `34567` и может быть отключён или перенастроен с помощью `-J`:```bash
# Disable the JSON API
./ssh-chatter -J off
# Bind JSON API on a custom port
./ssh-chatter -J 0.0.0.0:45678
Каждый запрос представляет собой один JSON-объект, завершающийся символом \n. Ответы и события чата также являются JSON-объектами, разделёнными символами новой строки. API поддерживает общий чат и потоки /poll, /vote, /image, /video, /audio, /files и /asciiart.
Полезные данные событий (сервер → клиент)```json {"type":"event","event":"message","payload":{"id":123,"username":"alice","message":"hello","created_at":1710000000,"system":false,"preserve_whitespace":false,"attachment":{"type":"none","target":"","caption":""}}}
**Примеры запросов (клиент → сервер)**```json
{"type":"chat","id":1,"username":"alice","message":"안녕하세요"}
{"type":"image","id":2,"username":"alice","url":"https://example.com/cat.png","caption":"cat"}
{"type":"asciiart","id":3,"username":"alice","message":" /\\_/\\\\n( o.o )\\\\n > ^ <"}
{"type":"poll","id":4,"username":"op","is_operator":true,"question":"Favorite color?","options":["red","blue","green"]}
{"type":"poll","id":5,"username":"bob","action":"vote","choice":2}
{"type":"vote","id":6,"username":"op","label":"weekend","question":"Plan?","options":["hike","rest"],"allow_multiple":true}
{"type":"vote","id":7,"username":"bob","label":"weekend","action":"vote","choice":1}
Ответы возвращают id и включают status, message и необязательные объекты result:```json
{"type":"response","id":4,"status":"ok","message":"poll started","result":{"poll":{"active":true,"allow_multiple":false,"id":10,"question":"Favorite color?","options":[{"index":1,"text":"red","votes":0},{"index":2,"text":"blue","votes":0}]}}}
Для рабочего примера смотрите `scripts/json_api_example.py`:```bash
python3 scripts/json_api_example.py --url tcp://127.0.0.1:34567 --save /tmp/json_api_output.txt
Предоставляется вспомогательный скрипт для автоматизации установки в системах, использующих systemd:```bash
sudo ./scripts/install_chatter_service.sh
Что делает скрипт:
1. Компилирует проект (`make`).
2. Устанавливает полученный бинарный файл в `/usr/local/bin/ssh-chatter`.
3. Создаёт выделенного системного пользователя и группу `ssh-chatter` (если они ещё не существуют).
4. Создаёт `/var/lib/ssh-chatter` для состояния выполнения (включая ключ хоста SSH) и `/etc/ssh-chatter` для конфигурационных файлов.
5. Генерирует ключ хоста RSA по умолчанию в `/var/lib/ssh-chatter/ssh_host_rsa_key`, если он отсутствует.
6. Создаёт MOTD по умолчанию в `/etc/ssh-chatter/motd` и файл переопределения `/etc/ssh-chatter/chatter.env` для настройки на основе переменных окружения.
7. Записывает `/etc/systemd/system/chatter.service`, перезагружает `systemd`, включает службу и запускает её немедленно.
Полученный юнит `chatter.service` запускает сервер с разумными настройками по умолчанию и предоставляет возможность `CAP_NET_BIND_SERVICE`, чтобы непривилегированная учётная запись службы могла привязываться к привилегированным портам при необходимости.
### Настройка службы
Вы можете изменить настройки по умолчанию, отредактировав `/etc/ssh-chatter/chatter.env` и перезапустив службу:```bash
sudo systemctl edit chatter.service # or edit the environment file directly
sudo systemctl restart chatter.service
Поддерживаемые переменные окружения:
CHATTER_BIND_ADDRESS – IP-адрес для привязки (по умолчанию 0.0.0.0).CHATTER_PORT – TCP-порт, доступный клиентам (по умолчанию 2222).CHATTER_MOTD_FILE – путь к файлу сообщения дня (по умолчанию /etc/ssh-chatter/motd).CHATTER_HOST_KEY_DIR – каталог, содержащий ssh_host_rsa_key (по умолчанию /var/lib/ssh-chatter).CHATTER_EXTRA_ARGS – дополнительные аргументы, добавляемые к вызову ssh-chatter.CHATTER_VOTE_FILE – путь к файлу состояния голосования (по умолчанию vote_state.dat).Фрагменты кода для маскировки:
Для функции маскировки Tetris среде выполнения требуются файлы фрагментов кода в /var/lib/ssh-chatter/.
Этот репозиторий теперь включает готовые к использованию примеры в ./camouflage/ (c.txt, cpp.txt, java.txt, go.txt, js.txt, ts.txt, rust.txt).
Скопируйте их в каталог выполнения один раз во время настройки:```bash
sudo install -d /var/lib/ssh-chatter
sudo cp camouflage/*.txt /var/lib/ssh-chatter/
Вы можете редактировать любой скопированный файл, чтобы настроить то, что отображается, когда активен экран камуфляжа.
Поддержка перевода теперь основана на Google Gemini API. Установите следующие параметры в `chatter.env` (или в окружении), чтобы включить его:
- `GEMINI_API_KEY` – Секретный ключ API, используемый для аутентификации запросов перевода.
- `GEMINI_API_BASE` – Необязательное переопределение базового URL API (по умолчанию `https://generativelanguage.googleapis.com/v1beta`).
- `GEMINI_MODEL` – Необязательное переопределение имени модели Gemini (по умолчанию `gemini-2.5-flash`).
Когда перевод активен, чат доставляет каждое сообщение немедленно на исходном языке и дополняет его отступом с переводом, как только приходит ответ Gemini. Сводки реакций используют тот же стиль подписи, так что обновления появляются непосредственно под сообщением, на которое они ссылаются.
Если встроенные вставки подписей кажутся резкими, вы можете заранее зарезервировать небольшой буфер пустых строк с помощью `/chat-spacing <0-5>`. Эта настройка влияет только на потоки живого чата — содержимое доски объявлений продолжает переводиться без резервирования, так что вы можете настроить интервал для своего сеанса, не влияя на длинные сообщения.
Ваши настройки перевода и выбора языка сохраняются в `chatter_state.dat`, так что будущие сеансы автоматически восстанавливают ту же конфигурацию при повторном подключении.
Если вы предпочитаете установить без немедленного запуска службы, запустите скрипт с `SKIP_START=1`.
Команды управления службой:```bash
sudo systemctl status chatter.service
sudo systemctl restart chatter.service
sudo systemctl disable --now chatter.service
-m или конфигурационный файл, управляемый сервисом./help для подключенных клиентов./ban, /poke)./weather/vote и одновариантные /vote-single, включая /elect <label> <choice> как текстовую сокращенную форму голосования./bbs, с тегами, комментариями, поднятием тем и интерактивным редактором, завершающимся терминатором, учитывающим локаль (по умолчанию >/__BBS_END>).Приветствуются сообщения об ошибках и запросы на изменение. Пожалуйста, прикладывайте шаги для воспроизведения ошибок и убедитесь, что make завершается успешно перед отправкой изменений.
| Путь | Описание |
|---|
src/main.c | Разбор командной строки и загрузка процесса (адрес привязки, порт, MOTD, каталог ключей хоста). |
src/host_aggregate.c, include/ssh_chatter/host.h | Реализация хоста чата — жизненный цикл сессий, обработка MOTD и точки подключения для будущей логики рассылки сообщений. |
src/host | Модульные подсистемы хоста, компилируемые в одну единицу трансляции через src/host_aggregate.c. |
include/ssh_chatter | Общие заголовочные файлы для демона, стресс-инструментов и бэкенда перевода. |
include/ssh_chatter/contexts | Определения session_ctx_t и связанных структур, инкапсулирующих состояние каждого подключения. |
data/banner/banner | Пример приветственного баннера, на который можно указать через CHATTER_WELCOME_BANNER. |
scripts/install_chatter_service.sh | Удобный скрипт установки: собирает бинарник, устанавливает его в /usr/local/bin и настраивает systemd-юнит (chatter.service). |
scripts/install_dependencies.sh | Минимальный установщик пакетов для сборки на Debian/Ubuntu. |
CHATTER_GEMINI_COOLDOWN_FILE – путь к файлу состояния перезарядки Gemini (по умолчанию gemini_cooldown.dat).CHATTER_SECURITY_FILTER – установите в off/false/0, чтобы отключить многоуровневый фильтр безопасности (включён по умолчанию).CHATTER_SECURITY_AI – установите в on/true/1, чтобы включить модерацию на основе ИИ (отключена по умолчанию).CHATTER_FILESTORE_PATH – переопределить путь к хранилищу управляемых файлов (по умолчанию /etc/ssh-chatter/user-files).CHATTER_FILE_STORAGE_ROOT – устаревший запасной путь к хранилищу управляемых файлов.CHATTER_MAX_ALLOC_BYTES – верхняя граница для одной попытки непрерывного выделения памяти во внутреннем менеджере памяти. По умолчанию нет предела (SIZE_MAX). Устанавливайте это значение, только если хотите ввести жёсткое ограничение на одно выделение. Установите в 0, unlimited, inf или infinity, чтобы явно снять любое ограничение./asciiart с черновиками до 640 строк, десятиминутной задержкой на публикацию с одного IP, многострочной доставкой и сочетаниями Ctrl+A/Ctrl+S./game со встроенными играми tetris (перекодирован с оригинальной советской реализации на C) и liargame, обе приостанавливаются через /suspend! или Ctrl+Z.