
ssh-chat en c moderne

Logiciel BBS général
SSH-Chatter a commencé comme une réimplémentation en C du serveur Go ssh-chat. Il reflète/étend le comportement original tout en utilisant des motifs C modernes et un noyau petit et testable. Le serveur écoute les connexions SSH/TELNET et place chaque utilisateur authentifié dans un salon de discussion partagé qui expose la même interface de commandes que l'implémentation de référence en Go.
Savez-vous pourquoi il faut si longtemps pour comprendre le C ? Parce que c'est un instinct.
/rss list, /rss read <tag>, plus /rss add <url> <tag> et /rss del <tag> (opérateurs seulement) pour que le salon puisse parcourir les titres ensemble./delete-msg pour un nettoyage ciblé de l'historique du chat./bbs déverrouillant un système de babillard rétro immersif avec tags, commentaires, bumping et un composeur multi-lignes.
bumped (activité récente), hot (tendance selon le score et les commentaires), top (score net de votes positifs le plus élevé) ou new (date de création) en utilisant list [hot|top|new|bumped|all].search <query>.▲ 12 💬 5) directement dans les listes./bbs en mode BBS./asciiart avec une limite de 640 lignes, un temps de recharge de dix minutes par adresse IP, une sortie multi-lignes et des raccourcis clavier pour annuler avec Ctrl+A et soumettre avec Ctrl+S ou la valeur par défaut >/__ARTWORK_END> adaptée à la locale./birthday pour enregistrer les anniversaires, /grant <ip> pour que les opérateurs LAN puissent déléguer les privilèges par adresse, et /revoke <ip> pour que les administrateurs LAN principaux puissent les révoquer./ban qui acceptent les adresses IP brutes en plus des noms d'utilisateur./weather <city> pour des prévisions météorologiques mondiales rapides.

La base de code est intentionnellement compacte pour que les nouveaux contributeurs puissent la naviguer rapidement :

mainLa branche work diverge régulièrement du développement amont afin que les fonctionnalités plus importantes puissent incuber sans interrompre le trafic de production. Lorsqu'il est temps de se synchroniser avec main, tirez l'arbre le plus récent et fusionnez-le localement avant d'ouvrir une pull request :```bash
git fetch origin main
git checkout work
git merge --no-ff origin/main
Résolvez les conflits sur place (les routines d'aide `src/host_aggregate.c` reflètent déjà la disposition utilisée sur `main`, donc les fusions sont généralement simples) et exécutez `make` pour confirmer que la construction réussit toujours avant de pousser le résultat.
## Hooks d'automatisation
- `host_snapshot_last_captcha` expose l'invite et la réponse du captcha généré le plus récemment ainsi qu'un horodatage afin que des clients externes puissent passer les défis pour le compte d'une automatisation non supervisée.
## Durcissement de la sécurité
- `scripts/safe_permission.sh` renforce la propriété et le mode des fichiers de données d'exécution (état du BBS, état des votes, instantanés de cooldown et état général des discussions). Exécutez-le après le déploiement pour confiner le répertoire de données à `ssh-chatter` et garantir que chaque fichier est défini sur `0600`. Remplacez les cibles en passant des chemins explicites ou en exportant les variables d'environnement `STATE_ROOT` ou les `CHATTER_*_FILE` correspondantes avant l'exécution.
- Un chien de garde BBS en arrière-plan alimente périodiquement les publications et commentaires via le pipeline de modération IA (Gemini principal avec repli sur Ollama). Les publications signalées sont supprimées automatiquement et un avis est diffusé dans la salle.
- Les messages de chat, l'art ASCII et les publications/commentaires BBS passent par un pipeline de modération IA. Activez-le avec `CHATTER_SECURITY_AI=on` (définissez `GEMINI_API_KEY` pour Gemini ; le daemon bascule automatiquement sur le point de terminaison local Ollama à `http://127.0.0.1:11434`). Désactivez tout avec `CHATTER_SECURITY_FILTER=off`. Si tous les fournisseurs échouent, le filtre se désactive automatiquement pour maintenir le flux des conversations au lieu de supprimer silencieusement le contenu.
- Le transport SSH est verrouillé sur des échanges de clés, des chiffrements et des MAC modernes, et chaque charge utile de pont est enveloppée dans un oignon triple AES-256-GCM, de sorte que les relais ne voient que du texte chiffré.
- Les soumissions suspectes qui déclenchent le filtre en couches sont désormais suivies par IP ; des coups répétés déclenchent un kick et un bannissement automatiques lorsqu'ils sont activés, tandis que le détecteur de reconnexion rapide permet des fenêtres de récupération plus longues afin que les sessions réseau instables puissent se reconnecter sans être pénalisées. Les entrées de bannissement automatique sont **désactivées par défaut** ; définissez `CHATTER_AUTO_BAN=on` (ou `true`/`1`) pour les activer, ou laissez la variable non définie pour conserver les avertissements et la limitation sans écrire d'entrées de bannissement automatique.
- Les opérateurs peuvent marquer les points d'entrée de confiance (sorties VPN, proxies inverses, localhost) avec `CHATTER_PROTECTED_IPS` (séparés par des virgules, par défaut `127.0.0.1,::1,192.168.0.1`) afin que les bannissements d'urgence ne verrouillent jamais le daemon en dehors de son propre plan de contrôle.
## Stockage de fichiers et transferts
- Tous les fichiers gérés par l'utilisateur résident désormais sous `/etc/ssh-chatter/user-files` (remplacez avec `CHATTER_FILESTORE_PATH`, repli hérité : `CHATTER_FILE_STORAGE_ROOT`). Le daemon crée le répertoire si nécessaire et maintient les téléchargements confinés à celui-ci.
- Les clients SSH utilisent `scp` standard sans wrapper personnalisé. Traitez `/name.ext` comme la racine de l'arborescence de stockage : `scp my.zip user@host:/demos/my.zip` écrit dans `/etc/ssh-chatter/user-files/demos/my.zip` tandis que `scp user@host:/readme.txt ./` télécharge `/etc/ssh-chatter/user-files/readme.txt`.
- Les clients TELNET utilisent les nouvelles commandes `/filestore`. `/filestore` liste les fichiers disponibles, `/filestore-upload` démarre une session `rz`, et `/filestore-download <name>` démarre une session `sz`. Installez `lrzsz` (ou tout package fournissant `rz`/`sz`) sur le serveur afin que le backend ZMODEM puisse lancer ces aides.
- `/filestore-upload` accepte une destination optionnelle (par exemple `/filestore-upload /kitten/meow.png`). SSH-Chatter crée automatiquement le répertoire `/kitten` et y place le fichier téléchargé, reflétant la façon dont SCP utilise des chemins comme `user@host:/kitten/meow.png`.
- Les deux transports peuvent être mélangés : SSH pour les transferts scriptés non supervisés, TELNET pour les clients BBS nostalgiques avec outils ZMODEM intégrés.
## Relais Morse
SSH-Chatter prend en charge le relais radioamateur.
Cela montre les signaux morse globaux.
`/morse on` pour voir, `/morse-reply` pour envoyer.
### Détails du protocole
L'implémentation suit la spécification du protocole Binkp :
- Structure de trame Binkp standard avec en-têtes de 2 octets
- Authentification par mot de passe de session (CMD\_PWD/CMD\_OK)
- Mécanisme de maintien en vie (CMD\_NUL) toutes les 60 secondes
- Commande CHAT personnalisée (CMD\_CHAT, extension) pour la synchronisation des messages
## Prérequis
La construction du projet nécessite un environnement POSIX avec :
- Un compilateur compatible C23 (par exemple `gcc` ou `clang`)
- `make`
- En-têtes de développement et bibliothèque `libssh` (`libssh-dev` sur Debian/Ubuntu)
- En-têtes de développement et bibliothèque `libcurl` (`libcurl4-openssl-dev` sur Debian/Ubuntu)
- En-têtes de développement et bibliothèque `uchardet` (`libuchardet-dev` sur Debian/Ubuntu)
- En-têtes de développement et bibliothèque `icu` (International Components for Unicode) (`libicu-dev` sur Debian/Ubuntu)
- Bibliothèque de compression `lz4` et en-têtes de développement (`liblz4-dev` sur Debian/Ubuntu)
- Threads POSIX (généralement fournis par le système `libpthread`)
- `python3-pygments` (fournit le surligneur `pygmentize` pour l'écran de camouflage Tetris)
Sur Debian/Ubuntu, les dépendances peuvent être installées avec :```bash
sudo apt-get update
sudo apt-get install build-essential libssh-dev libcurl4-openssl-dev libuchardet-dev libicu-dev liblz4-dev
Clonez le dépôt et utilisez le Makefile fourni :```bash
make
Cela produit un binaire `ssh-chatter` à la racine du dépôt et un objet partagé `libssh_chatter_backend.so` qui expose les aides à la traduction pour être réutilisées dans d'autres applications. Nettoyez les artefacts intermédiaires avec `make clean`.
### Utilisation du backend de traduction partagé
L'objet partagé réutilise le pipeline de traduction C du serveur (y compris la préservation des espaces réservés ANSI) afin que d'autres processus puissent obtenir des traductions sans lancer l'hôte SSH complet. Liez avec `libssh_chatter_backend.so` et incluez `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);
}
}
Définissez GEMINI_API_KEY (et éventuellement GEMINI_API_BASE ou GEMINI_MODEL) dans l'environnement pour que l'assistant puisse atteindre l'API Google Generative Language, reflétant les exigences d'exécution du démon principal. Vous pouvez exécuter ./scripts/test_gemini_connection.sh avant de lancer le serveur de chat pour vérifier que les identifiants autorisent les appels sortants ; le script affiche la réponse brute de Gemini afin que vous puissiez voir si la requête a réussi.
Le serveur écoute par défaut sur 0.0.0.0:2222. Vous pouvez ajuster les paramètres d'exécution avec les options disponibles :```
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]
Lorsqu'il est fourni, `-m` lit le message du jour à partir du chemin de fichier spécifié. Exemples courants :```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
Le répertoire des clés d'hôte doit contenir un fichier ssh_host_rsa_key (et optionnellement .pub). Générez-en un avec ssh-keygen -t rsa -b 4096 -f /path/to/dir/ssh_host_rsa_key si vous ne souhaitez pas réutiliser les clés d'hôte SSH de votre système. Des clés d'hôte supplémentaires nommées ssh_host_ed25519_key et ssh_host_ecdsa_key sont chargées automatiquement lorsqu'elles sont présentes, afin que le serveur puisse proposer des algorithmes modernes lors de l'échange de clés.
Une fois en cours d'exécution, connectez-vous avec n'importe quel client SSH :```bash ssh -p 2222 user@server-address
Le serveur public est disponible à l'adresse `bbs.chatter.pw` sur le port SSH par défaut :```bash
ssh -p 2222 [email protected]
Les noms d'utilisateur fournis à l'invite SSH sont utilisés comme votre pseudo dans le chat.
Les clients Telnet peuvent rejoindre avec le même ensemble de fonctionnalités. L'écoute Telnet est activée par défaut sur le port 2323 et peut être ajustée ou désactivée avec le drapeau -T. Fournissez -T adresse:port pour remplacer l'adresse de liaison (elle hérite de la liaison SSH lorsqu'elle est omise ; utilisez un hôte vide comme -T :4242 pour écouter sur toutes les interfaces). Par exemple, pour rejoindre via telnet depuis un terminal rétro :```bash
telnet server-address 2323
Passer `-T off` (ou `-T disable`) pour désactiver complètement l'écouteur telnet.
### API ligne JSON
Le serveur expose également un protocole ligne JSON via TCP pour l'automatisation et les intégrations externes. Il écoute sur le port `34567` par défaut et peut être désactivé ou reconfiguré avec `-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
Chaque requête est un objet JSON unique terminé par \n. Les réponses et les événements de chat sont des objets JSON, également délimités par des retours à la ligne. L'API prend en charge le chat général et les flux /poll, /vote, /image, /video, /audio, /files et /asciiart.
Payloads d'événements (serveur → client)```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":""}}}
**Exemples de requêtes (client → serveur)**```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}
Les réponses renvoient le id et incluent status, message, et éventuellement des objets 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}]}}}
Pour un exemple exécutable, voir `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
Un script d'assistance est fourni pour automatiser l'installation sur les systèmes qui utilisent systemd :```bash
sudo ./scripts/install_chatter_service.sh
Ce que fait le script :
1. Compile le projet (`make`).
2. Installe le binaire résultant dans `/usr/local/bin/ssh-chatter`.
3. Crée un utilisateur et un groupe système dédié `ssh-chatter` (s'ils n'existent pas déjà).
4. Crée `/var/lib/ssh-chatter` pour l'état d'exécution (incluant la clé d'hôte SSH) et `/etc/ssh-chatter` pour les fichiers de configuration.
5. Génère une clé d'hôte RSA par défaut dans `/var/lib/ssh-chatter/ssh_host_rsa_key` si elle est absente.
6. Crée un MOTD par défaut dans `/etc/ssh-chatter/motd` et un fichier de remplacement `/etc/ssh-chatter/chatter.env` pour le réglage basé sur l'environnement.
7. Écrit `/etc/systemd/system/chatter.service`, recharge `systemd`, active le service, et le démarre immédiatement.
L'unité `chatter.service` résultante démarre le serveur avec des valeurs par défaut raisonnables et accorde la capacité `CAP_NET_BIND_SERVICE` afin que le compte de service non root puisse se lier aux ports privilégiés si nécessaire.
### Personnalisation du service
Vous pouvez ajuster les valeurs par défaut en modifiant `/etc/ssh-chatter/chatter.env` et en redémarrant le service :```bash
sudo systemctl edit chatter.service # or edit the environment file directly
sudo systemctl restart chatter.service
Les variables d'environnement prises en charge incluent :
CHATTER_BIND_ADDRESS – Adresse IP à lier (par défaut 0.0.0.0).CHATTER_PORT – Port TCP exposé aux clients (par défaut 2222).CHATTER_MOTD_FILE – Chemin vers le fichier du message du jour (par défaut /etc/ssh-chatter/motd).CHATTER_HOST_KEY_DIR – Répertoire contenant ssh_host_rsa_key (par défaut /var/lib/ssh-chatter).CHATTER_EXTRA_ARGS – Arguments supplémentaires ajoutés à l'invocation de ssh-chatter.CHATTER_VOTE_FILE – Chemin vers le fichier d'état du vote (par défaut vote_state.dat).Extraits de code de camouflage :
Pour la fonction de camouflage Tetris, l'exécution attend des fichiers d'extraits de code dans /var/lib/ssh-chatter/.
Ce dépôt inclut désormais des exemples prêts à l'emploi sous ./camouflage/ (c.txt, cpp.txt, java.txt, go.txt, js.txt, ts.txt, rust.txt).
Copiez-les dans le répertoire d'exécution une fois lors de la configuration :```bash
sudo install -d /var/lib/ssh-chatter
sudo cp camouflage/*.txt /var/lib/ssh-chatter/
Vous pouvez modifier tout fichier copié pour personnaliser ce qui apparaît lorsque l'écran de camouflage est actif.
La prise en charge de la traduction repose désormais sur l'API Google Gemini. Définissez les éléments suivants dans `chatter.env` (ou dans l'environnement) pour l'activer :
- `GEMINI_API_KEY` – Clé API secrète utilisée pour authentifier les requêtes de traduction.
- `GEMINI_API_BASE` – Remplacement facultatif pour l'URL de base de l'API (par défaut `https://generativelanguage.googleapis.com/v1beta`).
- `GEMINI_MODEL` – Remplacement facultatif pour le nom du modèle Gemini (par défaut `gemini-2.5-flash`).
Lorsque la traduction est active, le chat délivre chaque message immédiatement dans sa langue d'origine et le complète avec une légende indentée contenant le texte traduit une fois la réponse Gemini arrivée. Les résumés de réactions utilisent le même style de légende afin que les mises à jour apparaissent directement sous le message auquel elles se réfèrent.
Si les insertions de légendes en ligne semblent gênantes, vous pouvez réserver un petit tampon de lignes vierges à l'avance avec `/chat-spacing <0-5>`. Ce paramètre n'affecte que les fils de discussion en direct — le contenu du tableau d'affichage continue d'être traduit sans réservation — vous pouvez donc ajuster l'espacement pour votre propre session sans impacter les messages longs.
Votre bascule de traduction et vos choix de langue sont sauvegardés dans `chatter_state.dat`, de sorte que les sessions futures restaurent automatiquement la même configuration une fois que vous vous reconnectez.
Si vous préférez installer sans démarrer immédiatement le service, exécutez le script avec `SKIP_START=1`.
Commandes de gestion du service :```bash
sudo systemctl status chatter.service
sudo systemctl restart chatter.service
sudo systemctl disable --now chatter.service
-m ou le fichier de configuration géré par le service./help pour les clients connectés./ban, /poke)./weather/vote et les alternatives à choix unique /vote-single, y compris /elect <label> <choice> comme un raccourci de vote textuel./bbs avec étiquetage, commentaires, remontée, et un compositeur interactif qui se termine par un terminateur tenant compte de la locale (par défaut >/__BBS_END>).Les problèmes et pull requests sont les bienvenus. Veuillez inclure les étapes de reproduction pour les bogues et assurez-vous que make réussisse avant de soumettre des modifications.
| Chemin | Description |
|---|
src/main.c | Analyse de la ligne de commande et amorçage du processus (adresse de liaison, port, MOTD, répertoire des clés d'hôte). |
src/host_aggregate.c, include/ssh_chatter/host.h | Implémentation de l'hôte de chat – cycle de vie de session, gestion du MOTD, et hooks pour la future logique de diffusion de messages. |
src/host | Sous-systèmes d'hôte modulaires qui compilent en une seule unité de traduction via src/host_aggregate.c. |
include/ssh_chatter | En-têtes partagés pour le démon, les outils de stress, et le backend de traduction. |
include/ssh_chatter/contexts | Définitions pour session_ctx_t et les structures associées qui encapsulent l'état par connexion. |
data/banner/banner | Exemple de bannière de bienvenue qui peut être pointée avec CHATTER_WELCOME_BANNER. |
scripts/install_chatter_service.sh | Installeur pratique qui construit le binaire, l'installe sous /usr/local/bin, et met en place une unité systemd (chatter.service). |
scripts/install_dependencies.sh | Installeur de paquets minimal pour les prérequis de construction sur les systèmes Debian/Ubuntu. |
CHATTER_GEMINI_COOLDOWN_FILE – Chemin vers le fichier d'état du temps de recharge Gemini (par défaut gemini_cooldown.dat).CHATTER_SECURITY_FILTER – Définir sur off/false/0 pour désactiver le filtre de sécurité en couches (activé par défaut).CHATTER_SECURITY_AI – Définir sur on/true/1 pour activer la modération IA (désactivée par défaut).CHATTER_FILESTORE_PATH – Remplace le chemin de stockage des fichiers gérés (par défaut /etc/ssh-chatter/user-files).CHATTER_FILE_STORAGE_ROOT – Repli hérité pour le chemin de stockage des fichiers gérés.CHATTER_MAX_ALLOC_BYTES – Limite supérieure pour une tentative d'allocation contiguë unique dans le gestionnaire de mémoire interne. Par défaut, il n'y a aucune limite (SIZE_MAX). Définissez-le uniquement si vous souhaitez imposer une limite stricte à une seule allocation. Définissez sur 0, unlimited, inf ou infinity pour supprimer explicitement toute limite./asciiart avec brouillons de 640 lignes, un délai de dix minutes par IP pour les publications, livraison multi-lignes, et raccourcis Ctrl+A/Ctrl+S./game avec tetris intégré (transcodé de l'implémentation C originale de l'ère soviétique) et liargame, tous deux suspendables via /suspend! ou Ctrl+Z.