
ssh-chat en C moderno

Software General de BBS
SSH-Chatter comenzó como una reimplementación en C del servidor Go ssh-chat. Refleja/extiende el comportamiento original mientras usa patrones modernos de C y un núcleo pequeño y comprobable. El servidor escucha conexiones SSH/TELNET y coloca a cada usuario autenticado en una sala de chat compartida que expone la misma superficie de comandos que la implementación de referencia en Go.
¿Sabes por qué lleva tanto tiempo entender C? Porque es un instinto.
/rss list, /rss read <tag>, además de /rss add <url> <tag> y /rss del <tag> (solo operadores) para que la sala pueda navegar juntos por los titulares./delete-msg para limpieza selectiva del historial del chat./bbs que desbloquea un sistema de tablón de anuncios retro inmersivo con etiquetas, comentarios, bumping y un compositor multilínea.
bumped (actividad reciente), hot (tendencia por puntuación y comentarios), top (mayor puntuación neta de votos positivos) o new (fecha de creación) usando list [hot|top|new|bumped|all].search <query>.▲ 12 💬 5) directamente en las listas./bbs dentro del modo BBS./asciiart con un límite de 640 líneas, un tiempo de espera de diez minutos por IP, salida multilínea y atajos de teclado para cancelar con Ctrl+A y enviar con Ctrl+S o el valor predeterminado sensible a la configuración regional >/__ARTWORK_END>./birthday para registrar cumpleaños, /grant <ip> para que los operadores de LAN puedan delegar privilegios por dirección, y /revoke <ip> para que los administradores principales de LAN puedan recuperarlos./ban que aceptan direcciones IP sin formato junto con nombres de usuario./weather <city> para pronósticos globales rápidos.

El código base es intencionalmente compacto para que los nuevos contribuyentes puedan navegar rápidamente:

mainLa rama work se desvía regularmente del desarrollo ascendente para que las funcionalidades más grandes puedan incubarse sin interrumpir el tráfico de producción. Cuando sea el momento de sincronizar con main, extrae el árbol más reciente y combínalo localmente antes de abrir una solicitud de extracción:```bash
git fetch origin main
git checkout work
git merge --no-ff origin/main
Resuelva cualquier conflicto en el lugar (las rutinas auxiliares en `src/host_aggregate.c` ya reflejan el diseño usado en `main`, por lo que las fusiones suelen ser sencillas) y ejecute `make` para confirmar que la compilación aún tenga éxito antes de enviar el resultado.
## Hooks de automatización
- `host_snapshot_last_captcha` expone el aviso de captcha generado más recientemente y su respuesta junto con una marca de tiempo para que los clientes externos puedan pasar desafíos en nombre de la automatización no supervisada.
## Endurecimiento de seguridad
- `scripts/safe_permission.sh` ajusta la propiedad y los modos de los archivos de datos en tiempo de ejecución (estado del BBS, estado de votación, instantáneas de enfriamiento y estado general de chatter). Ejecútelo después del despliegue para confinar el directorio de datos a `ssh-chatter` y asegurar que cada archivo tenga modo `0600`. Sobrescriba los destinos pasando rutas explícitas o exportando `STATE_ROOT` o las variables de entorno `CHATTER_*_FILE` correspondientes antes de la ejecución.
- Un vigilante BBS en segundo plano alimenta periódicamente publicaciones y comentarios a través del pipeline de moderación de IA (Gemini principal con respaldo de Ollama). Las publicaciones marcadas se eliminan automáticamente y se transmite un aviso a la sala.
- Los mensajes de chat, el arte ASCII y las publicaciones/comentarios del BBS pasan por un pipeline de moderación de IA. Actívelo con `CHATTER_SECURITY_AI=on` (configure `GEMINI_API_KEY` para Gemini; el daemon recurre automáticamente al endpoint local de Ollama en `http://127.0.0.1:11434`). Desactive todo con `CHATTER_SECURITY_FILTER=off`. Si todos los proveedores fallan, el filtro se desactiva automáticamente para mantener las conversaciones fluyendo en lugar de descartar contenido en silencio.
- El transporte SSH está fijado a intercambios de claves, cifrados y MACs modernos, y cada carga útil del puente está envuelta en una cebolla triple AES-256-GCM, por lo que los relevos solo ven texto cifrado.
- Las presentaciones sospechosas que activan el filtro en capas ahora se rastrean por IP; los impactos repetidos activan una patada y una prohibición automática cuando están habilitados, mientras que el detector de reconexión rápida permite ventanas de recuperación más largas para que las sesiones de red inestables puedan reincorporarse sin ser penalizadas. Las entradas de baneo automático están **desactivadas por defecto**; establezca `CHATTER_AUTO_BAN=on` (o `true`/`1`) para habilitarlas, o deje la variable sin definir para mantener advertencias y limitación sin escribir entradas de baneo automático.
- Los operadores pueden marcar puntos de entrada de confianza (salidas VPN, proxies inversos, localhost) con `CHATTER_PROTECTED_IPS` (separados por comas, por defecto `127.0.0.1,::1,192.168.0.1`) para que los baneos de emergencia nunca bloqueen al daemon fuera de su propio plano de control.
## Almacenamiento y transferencias de archivos
- Todos los archivos gestionados por el usuario ahora residen en `/etc/ssh-chatter/user-files` (sobrescribir con `CHATTER_FILESTORE_PATH`, respaldo heredado: `CHATTER_FILE_STORAGE_ROOT`). El daemon crea el directorio si es necesario y mantiene las subidas confinadas a él.
- Los clientes SSH usan `scp` estándar sin ningún envoltorio personalizado. Trate `/nombre.ext` como la raíz del árbol de almacenamiento: `scp my.zip user@host:/demos/my.zip` escribe en `/etc/ssh-chatter/user-files/demos/my.zip` mientras que `scp user@host:/readme.txt ./` descarga `/etc/ssh-chatter/user-files/readme.txt`.
- Los clientes TELNET usan los nuevos comandos `/filestore`. `/filestore` lista los archivos disponibles, `/filestore-upload` inicia una sesión `rz`, y `/filestore-download <nombre>` inicia una sesión `sz`. Instale `lrzsz` (o cualquier paquete que proporcione `rz`/`sz`) en el servidor para que el backend ZMODEM pueda lanzar esos helpers.
- `/filestore-upload` acepta un destino opcional (por ejemplo `/filestore-upload /kitten/meow.png`). SSH-Chatter crea el directorio `/kitten` automáticamente y coloca el archivo subido allí, reflejando cómo SCP usa rutas como `user@host:/kitten/meow.png`.
- Ambos transportes pueden mezclarse: SSH para transferencias programadas no supervisadas, TELNET para clientes BBS nostálgicos con herramientas ZMODEM integradas.
## Retransmisión Morse
SSH-Chatter soporta retransmisión de radioaficionados ham.
Esto muestra señales morse globales.
`/morse on` para ver, `/morse-reply` para enviar.
### Detalles del Protocolo
La implementación sigue la especificación del protocolo Binkp:
- Estructura de trama Binkp estándar con encabezados de 2 bytes
- Autenticación con contraseña de sesión (CMD\_PWD/CMD\_OK)
- Mecanismo de Keepalive (CMD\_NUL) cada 60 segundos
- Comando CHAT personalizado (CMD\_CHAT, extensión) para sincronización de mensajes
## Requisitos previos
Construir el proyecto requiere un entorno POSIX con:
- Un compilador compatible con C23 (por ejemplo `gcc` o `clang`)
- `make`
- Encabezados de desarrollo y biblioteca `libssh` (`libssh-dev` en Debian/Ubuntu)
- Encabezados de desarrollo y biblioteca `libcurl` (`libcurl4-openssl-dev` en Debian/Ubuntu)
- Encabezados de desarrollo y biblioteca `uchardet` (`libuchardet-dev` en Debian/Ubuntu)
- Encabezados de desarrollo y biblioteca `icu` (Componentes Internacionales para Unicode) (`libicu-dev` en Debian/Ubuntu)
- Biblioteca de compresión `lz4` y encabezados de desarrollo (`liblz4-dev` en Debian/Ubuntu)
- Hilos POSIX (normalmente proporcionados por el sistema `libpthread`)
- `python3-pygments` (proporciona el resaltador `pygmentize` para la pantalla de camuflaje Tetris)
En Debian/Ubuntu las dependencias se pueden instalar con:```bash
sudo apt-get update
sudo apt-get install build-essential libssh-dev libcurl4-openssl-dev libuchardet-dev libicu-dev liblz4-dev
Clona el repositorio y utiliza el Makefile proporcionado:```bash
make
Esto produce un binario `ssh-chatter` en la raíz del repositorio y un objeto compartido `libssh_chatter_backend.so` que expone las
ayudantes de traducción para su reutilización en otras aplicaciones. Limpie los artefactos intermedios con `make clean`.
### Usando el backend de traducción compartido
El objeto compartido reutiliza el pipeline de traducción C del servidor (incluyendo la preservación de marcadores ANSI) para que otros procesos puedan
obtener traducciones sin iniciar el host SSH completo. Enlace contra `libssh_chatter_backend.so` e incluya
`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);
}
}
Establece GEMINI_API_KEY (y opcionalmente GEMINI_API_BASE o GEMINI_MODEL) en el entorno para que el asistente pueda alcanzar la API de Google Generative Language, reflejando los requisitos de ejecución del daemon principal. Puedes ejecutar ./scripts/test_gemini_connection.sh antes de iniciar el servidor de chat para verificar que las credenciales permiten llamadas salientes; el script imprime la respuesta cruda de Gemini para que puedas ver si la solicitud tuvo éxito.
El servidor escucha por defecto en 0.0.0.0:2222. Puedes ajustar los parámetros de ejecución con las siguientes banderas:```
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]
Cuando se proporciona, `-m` lee el mensaje del día desde la ruta de archivo especificada.
Ejemplos comunes:```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
El directorio de clave de host debe contener un archivo ssh_host_rsa_key (y opcionalmente .pub). Genere uno con ssh-keygen -t rsa -b 4096 -f /path/to/dir/ssh_host_rsa_key si no desea reutilizar las claves de host SSH de su sistema. Las claves de host adicionales llamadas ssh_host_ed25519_key y ssh_host_ecdsa_key se cargan automáticamente cuando están presentes, para que el servidor pueda ofrecer algoritmos modernos durante el intercambio de claves.
Una vez en ejecución, conéctese con cualquier cliente SSH:```bash ssh -p 2222 user@server-address
El servidor público está disponible en `bbs.chatter.pw` en el puerto SSH predeterminado:```bash
ssh -p 2222 [email protected]
Los nombres de usuario proporcionados en el prompt SSH se utilizan como tu apodo en el chat.
Los clientes Telnet pueden unirse con el mismo conjunto de características. La escucha Telnet está habilitada por defecto en el puerto 2323 y se puede ajustar o deshabilitar con la bandera -T. Proporcione -T address:port para anular la dirección de enlace (hereda el enlace SSH cuando se omite; use un host vacío como -T :4242 para escuchar en todas las interfaces). Por ejemplo, para conectarse a través de telnet desde un terminal retro:```bash
telnet server-address 2323
Pasa `-T off` (o `-T disable`) para desactivar el listener telnet por completo.
### API de líneas JSON
El servidor también expone un protocolo de líneas JSON sobre TCP para automatización e integraciones externas. Escucha en el puerto `34567` por defecto y se puede desactivar o reconfigurar con `-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
Cada solicitud es un único objeto JSON terminado por \n. Las respuestas y eventos de chat son objetos JSON, también delimitados por nueva línea. La API soporta chat general y los flujos /poll, /vote, /image, /video, /audio, /files, y /asciiart.
Cargas de eventos (servidor → cliente)```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":""}}}
**Ejemplos de solicitud (cliente → servidor)**```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}
Las respuestas reflejan el id e incluyen los objetos status, message y opcionalmente 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}]}}}
Para un ejemplo ejecutable, consulta `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
Se proporciona un script auxiliar para automatizar la instalación en sistemas que usan systemd:```bash
sudo ./scripts/install_chatter_service.sh
Lo que hace el script:
1. Compila el proyecto (`make`).
2. Instala el binario resultante en `/usr/local/bin/ssh-chatter`.
3. Crea un usuario y grupo de sistema dedicados `ssh-chatter` (si aún no existen).
4. Crea `/var/lib/ssh-chatter` para el estado en tiempo de ejecución (incluyendo la clave de host SSH) y `/etc/ssh-chatter` para los archivos de configuración.
5. Genera una clave de host RSA predeterminada en `/var/lib/ssh-chatter/ssh_host_rsa_key` si falta.
6. Crea un MOTD predeterminado en `/etc/ssh-chatter/motd` y un archivo de anulación `/etc/ssh-chatter/chatter.env` para el ajuste basado en variables de entorno.
7. Escribe `/etc/systemd/system/chatter.service`, recarga `systemd`, habilita el servicio y lo inicia inmediatamente.
La unidad `chatter.service` resultante inicia el servidor con valores predeterminados sensatos y otorga la capacidad `CAP_NET_BIND_SERVICE` para que la cuenta de servicio no root pueda enlazarse a puertos privilegiados si es necesario.
### Personalizando el servicio
Puede ajustar los valores predeterminados editando `/etc/ssh-chatter/chatter.env` y reiniciando el servicio:```bash
sudo systemctl edit chatter.service # or edit the environment file directly
sudo systemctl restart chatter.service
Las variables de entorno compatibles incluyen:
CHATTER_BIND_ADDRESS – Dirección IP a la que vincularse (por defecto 0.0.0.0).CHATTER_PORT – Puerto TCP expuesto a los clientes (por defecto 2222).CHATTER_MOTD_FILE – Ruta al archivo del mensaje del día (por defecto /etc/ssh-chatter/motd).CHATTER_HOST_KEY_DIR – Directorio que contiene ssh_host_rsa_key (por defecto /var/lib/ssh-chatter).CHATTER_EXTRA_ARGS – Argumentos adicionales añadidos a la invocación de ssh-chatter.CHATTER_VOTE_FILE – Ruta al archivo de estado de votación (por defecto vote_state.dat).Fragmentos de código de camuflaje:
Para la funcionalidad de camuflaje Tetris, el tiempo de ejecución espera archivos de fragmentos de código en /var/lib/ssh-chatter/.
Este repositorio ahora incluye ejemplos listos para usar en ./camouflage/ (c.txt, cpp.txt, java.txt, go.txt, js.txt, ts.txt, rust.txt).
Cópielos al directorio de tiempo de ejecución una vez durante la configuración:```bash
sudo install -d /var/lib/ssh-chatter
sudo cp camouflage/*.txt /var/lib/ssh-chatter/
Puede editar cualquier archivo copiado para personalizar lo que aparece cuando la pantalla de camuflaje está activa.
La compatibilidad con la traducción ahora depende de la API de Google Gemini. Configure lo siguiente en `chatter.env` (o en el entorno) para habilitarla:
- `GEMINI_API_KEY` – Clave API secreta utilizada para autenticar las solicitudes de traducción.
- `GEMINI_API_BASE` – Anulación opcional de la URL base de la API (por defecto `https://generativelanguage.googleapis.com/v1beta`).
- `GEMINI_MODEL` – Anulación opcional del nombre del modelo Gemini (por defecto `gemini-2.5-flash`).
Cuando la traducción está activa, el chat envía cada mensaje inmediatamente en su idioma original y, a continuación, añade un subtítulo con sangría que contiene el texto traducido una vez que llega la respuesta de Gemini. Los resúmenes de reacciones utilizan el mismo estilo de subtítulo, por lo que las actualizaciones aparecen directamente debajo del mensaje al que hacen referencia.
Si las inserciones de subtítulos en línea resultan molestas, puede reservar un pequeño búfer de líneas en blanco con antelación con `/chat-spacing <0-5>`. Esta configuración solo afecta a los hilos de chat en vivo (el contenido del tablón de anuncios continúa traduciéndose sin reserva), por lo que puede ajustar el espaciado para su propia sesión sin afectar a las publicaciones largas.
Los cambios de idioma y la opción de traducción se guardan en `chatter_state.dat`, por lo que las sesiones futuras restauran automáticamente la misma configuración una vez que se reconecte.
Si prefiere instalar sin iniciar el servicio inmediatamente, ejecute el script con `SKIP_START=1`.
Comandos de gestión del servicio:```bash
sudo systemctl status chatter.service
sudo systemctl restart chatter.service
sudo systemctl disable --now chatter.service
-m o archivo de configuración gestionado por el servicio./help para clientes conectados./ban, /poke)./weather/vote y alternativas de opción única /vote-single, incluido /elect <etiqueta> <opción> como un atajo de votación amigable con el texto./bbs con etiquetado, comentarios, promoción y un compositor interactivo que termina con un terminador consciente de la configuración regional (predeterminado ).Los issues y pull requests son bienvenidos. Incluye pasos de reproducción para errores y asegúrate de que make se ejecute correctamente antes de enviar cambios.
| Ruta | Descripción |
|---|
src/main.c | Análisis de línea de comandos e inicio del proceso (dirección de enlace, puerto, MOTD, directorio de claves de host). |
src/host_aggregate.c, include/ssh_chatter/host.h | Implementación del host de chat – ciclo de vida de sesiones, manejo de MOTD y enganches para lógica futura de difusión de mensajes. |
src/host | Subsistemas de host modulares que se compilan en una sola unidad de traducción a través de src/host_aggregate.c. |
include/ssh_chatter | Cabeceras compartidas para el daemon, herramientas de estrés y el backend de traducción. |
include/ssh_chatter/contexts | Definiciones para session_ctx_t y estructuras relacionadas que encapsulan el estado por conexión. |
data/banner/banner | Ejemplo de banner de bienvenida al que se puede apuntar con CHATTER_WELCOME_BANNER. |
scripts/install_chatter_service.sh | Instalador de conveniencia que compila el binario, lo instala en /usr/local/bin y configura una unidad systemd (chatter.service). |
scripts/install_dependencies.sh | Instalador mínimo de paquetes para requisitos previos de compilación en sistemas Debian/Ubuntu. |
CHATTER_GEMINI_COOLDOWN_FILE – Ruta al archivo de estado de reutilización de Gemini (por defecto gemini_cooldown.dat).CHATTER_SECURITY_FILTER – Establézcalo en off/false/0 para deshabilitar el filtro de seguridad en capas (habilitado por defecto).CHATTER_SECURITY_AI – Establézcalo en on/true/1 para habilitar la moderación por IA (deshabilitado por defecto).CHATTER_FILESTORE_PATH – Sobrescribe la ruta de almacenamiento de archivos gestionados (por defecto /etc/ssh-chatter/user-files).CHATTER_FILE_STORAGE_ROOT – Fallback heredado para la ruta de almacenamiento de archivos gestionados.CHATTER_MAX_ALLOC_BYTES – Límite superior para un único intento de asignación contigua en el administrador de memoria interno. Por defecto no hay límite (SIZE_MAX). Establézcalo solo si desea imponer un límite estricto en una asignación. Establézcalo a 0, unlimited, inf o infinity para eliminar explícitamente cualquier límite.>/__BBS_END>/asciiart con borradores de 640 líneas, un período de espera de publicación de diez minutos por IP, entrega multilínea y atajos Ctrl+A/Ctrl+S./game con tetris incorporado (transcodificado de la implementación original en C de la era soviética) y liargame, ambos suspendibles mediante /suspend! o Ctrl+Z.