Exploring the roots and future of Internet Relay Chat

Historia técnica del protocolo IRC

Los orígenes: Jarkko Oikarinen y el BBS de Oulu

En el verano de 1988, Jarkko Oikarinen trabajaba como administrador de sistemas en la Universidad de Oulu, Finlandia. Su tarea inmediata era mantener un BBS llamado OuluBox. El sistema de chat que tenía ese BBS, MUT (MultiUser Talk), le parecía insuficiente. En lugar de mejorarlo, decidió reemplazarlo con algo completamente distinto.

Lo que escribió entre agosto y septiembre de 1988 fue la primera implementación del Internet Relay Chat. El servidor corría en tolsun.oulu.fi. El cliente original se llamaba simplemente irc, compilaba en sistemas Unix de la época, y usaba una conexión TCP directa al puerto 6667 — número que, curiosamente, no estaba definido en ningún estándar formal cuando Oikarinen lo eligió.

La primera red fue trivial: un servidor, varios usuarios locales. Pero Oikarinen conectó ese servidor a otros nodos universitarios finlandeses en enero de 1989. Para noviembre de ese mismo año, la red ya cruzaba el Atlántico. El evento catalizador fue la Guerra del Golfo de 1991: periodistas y ciudadanos usaron IRC para difundir noticias en tiempo real cuando otros canales fallaban. En ese momento, la red EFnet (Eris Free Network) tenía ya decenas de servidores.

Consejo: Si quieres ver cómo era el cliente IRC original de 1988, el código fuente de las versiones tempranas de ircII (el primer cliente ampliamente distribuido, escrito por Michael Sanchez y luego por Troy Rollo) está disponible en archivos FTP históricos. La diferencia con los clientes modernos es sorprendente: sin colores, sin iconos, sin pestañas.

El protocolo que Oikarinen diseñó tenía características que reflejaban los recursos de la época. Los mensajes eran líneas de texto terminadas en \r\n, con un prefijo opcional que indicaba el origen, un comando y parámetros separados por espacios. Sin cifrado, sin autenticación criptográfica, sin compresión. Un protocolo que cabe en la cabeza de una persona.

Arquitectura inicial: servidores, canales y modos

La arquitectura de IRC es, en términos de teoría de grafos, un árbol de expansión (spanning tree). Los servidores se conectan entre sí formando una topología sin ciclos: cada servidor tiene exactamente un camino hacia cualquier otro servidor en la red. Esta decisión de diseño tiene consecuencias profundas.

Cuando un usuario en irc.mit.edu envía un mensaje al canal #linux, ese mensaje viaja por el árbol hasta llegar a todos los servidores que tienen usuarios suscritos a ese canal. No hay mecanismo de confirmación de entrega entre servidores: el protocolo es fundamentalmente best-effort sobre TCP.

Los canales tienen un sistema de modos que se gestiona con el comando MODE. Los modos de canal más comunes son:

MODE #canal +o usuario   ; dar operador a un usuario
MODE #canal +v usuario   ; dar voz (en canal moderado)
MODE #canal +i           ; canal solo por invitación
MODE #canal +k secreto   ; canal con clave
MODE #canal +l 50        ; límite de usuarios
MODE #canal +m           ; canal moderado (solo +v y +o pueden hablar)
MODE #canal +t           ; solo operadores pueden cambiar el topic
MODE #canal +n           ; no se permite mensajes externos al canal

Los modos de usuario siguen la misma sintaxis pero se aplican al nick individual. El modo +i en un usuario lo hace invisible en los listados WHO; el modo +o indica IRC operator (ircop), con privilegios sobre la red completa.

El sistema de nicks es global en toda la red: no puede haber dos usuarios con el mismo nick simultáneamente. Esta restricción, que parece obvia, es la fuente de la mayoría de los problemas históricos de IRC. Cuando dos partes de la red se desconectan y reconectan (un «netsplit»), cada fragmento puede haber asignado el mismo nick a usuarios distintos. Al reconectarse, el servidor debe resolver este conflicto: en la implementación original, simplemente mataba (desconectaba) a uno de los dos. En implementaciones posteriores, a ambos.

Los canales cuyo nombre empieza por # son globales (visibles en toda la red). Los que empiezan por & son locales al servidor. Los que empiezan por + (introducidos en IRCnet más tarde) no tienen operadores. Esta distinción nunca fue adoptada uniformemente por todas las redes.

Los RFCs que definen el protocolo

El primer intento de estandarizar IRC en un RFC fue en 1993, casi cinco años después de la primera implementación. Esto no es inusual en la historia de Internet: primero se construye, luego se documenta.

El RFC 1459, publicado en mayo de 1993 y escrito por Jarkko Oikarinen y Darren Reed, es el documento fundacional. Define la sintaxis de los mensajes, los comandos base, los modos, la topología de red y los numerales de respuesta. Es un documento de lectura razonablemente amena, lo que también es inusual para un RFC.

La estructura de un mensaje IRC según RFC 1459 es:

mensaje    ::= [':' prefijo ESPACIO] comando [params] '\r\n'
prefijo    ::= nombre-servidor | nick ['!' usuario] ['@' host]
comando    ::= letra+ | número número número
params     ::= [ESPACIO [':' trailing | medio params]]
medio      ::= carácter-sin-espacio+
trailing   ::= carácter*

La longitud máxima de un mensaje, incluyendo \r\n, es de 512 bytes. Este límite, heredado de las restricciones de red de 1988, ha sobrevivido décadas sin cambios en el protocolo base.

En 2000, el RFC 1459 fue reemplazado por dos documentos complementarios: RFC 2810 (arquitectura), RFC 2811 (canales), RFC 2812 (protocolo cliente-servidor) y RFC 2813 (protocolo servidor-servidor). Esta división reflejaba la madurez del ecosistema: había suficientes implementaciones distintas como para necesitar separar claramente qué parte del estándar afectaba a qué componente.

El RFC 2812 introduce el soporte oficial para el prefijo : en el último parámetro (el «trailing»), que permite mensajes con espacios sin necesidad de comillas. También define formalmente los numerales de respuesta, que van del 001 al 999 y cubren desde «bienvenido a la red» (001) hasta errores específicos de modo (472).

Algunos numerales históricos merecen mención:

  • 001 RPL_WELCOME: primer mensaje al conectarse, contiene el nombre completo de la red
  • 004 RPL_MYINFO: informa al cliente de los modos disponibles en el servidor
  • 005 RPL_ISUPPORT: no definido en RFC 1459, pero adoptado universalmente para anunciar capacidades extendidas
  • 433 ERR_NICKNAMEINUSE: el nick que pediste ya está cogido
  • 471 ERR_CHANNELISFULL: el canal tiene el modo +l y está lleno

El numeral 005 (RPL_ISUPPORT) merece una nota especial. No aparecía en el RFC 1459 original, pero hacia mediados de los 90 todos los servidores lo emitían para anunciar características no estándar: el prefijo de modos que usaban, el límite de canales por usuario, si soportaban canales seguros, etc. En 2005 se publicó el RFC 2812-bis que lo documenta formalmente como parte del protocolo, aunque técnicamente es una extensión.

Las guerras de redes: splits, EFnet y Undernet

La historia política de IRC es inseparable de su historia técnica. Las decisiones de arquitectura crearon incentivos que llevaron a fragmentaciones, y las fragmentaciones crearon nuevas implementaciones.

EFnet (Eris Free Network) fue la primera gran red IRC, formada alrededor de 1990 tras una disputa sobre si el servidor eris.berkeley.edu debía poder unirse a la red original. El administrador de ese servidor tenía políticas de acceso más permisivas que el resto; tras la exclusión, varios servidores lo siguieron y formaron la red separada.

Undernet se fundó en 1992, parcialmente como reacción a los problemas técnicos de EFnet. La topología de árbol de IRC tiene un problema inherente: los netsplits. Cuando la conexión entre dos servidores se interrumpe, la red se divide en dos fragmentos. Cada fragmento continúa funcionando de forma independiente, pero los usuarios de un lado no ven a los del otro. Cuando la conexión se restaura, ambos fragmentos intentan «mergearse», y aquí empiezan los problemas.

El merge en IRC clásico produce lo que se llama un «nick collision»: si el mismo nick fue asignado en ambos fragmentos durante el split, ambos usuarios son desconectados. Los operadores de canal (ops) que estaban en un fragmento pueden no estar ops en el fragmento opuesto. Esto llevó a un abuso sistemático: si lograbas provocar un netsplit artificialmente, podías obtener ops en canales donde no los tenías. Se llamaba «opless channel takeover» y fue un problema real durante los 90.

Undernet intentó resolver esto con el servicio ChanServ y el concepto de «channel registration»: un canal podía registrarse a un usuario, y ChanServ restauraba automáticamente los ops tras un netsplit. Esta solución funcionaba, pero era un servicio centralizado en una red supuestamente distribuida.

DALnet, fundada en 1994, llevó esto más lejos con NickServ (registro de nicks) y un conjunto completo de servicios gestionados por bots especializados. El protocolo IRC no tiene mecanismo nativo de autenticación de usuarios; los «servicios» son la solución pragmática que adoptó la mayoría de las redes grandes.

IRCnet, formada en 1996 tras otra escisión de EFnet, tomó una postura diferente: rechazó los servicios centralizados y propuso soluciones técnicas al nivel del protocolo. Introdujo el modo de canal +r (solo usuarios registrados) y el modo +e (excepciones a baneos), pero sin ChanServ ni NickServ. Esta pureza técnica tuvo un coste: los canales en IRCnet eran más vulnerables a tomas hostiles.

ircd y sus variantes: una genealogía fragmentada

El servidor IRC original de Oikarinen derivó en varias líneas de desarrollo que divergieron sustancialmente. Entender esta genealogía ayuda a explicar por qué diferentes redes tienen capacidades distintas a pesar de usar «el mismo protocolo».

El árbol genealógico principal:

  • ircd 2.x (1988-1990): el original de Oikarinen, base de todo lo demás
  • ircd 2.8 (1991): versión que se convirtió en la base de EFnet durante años
  • ircd 2.9/2.10: línea de IRCnet, con mejoras de estabilidad y nuevos modos
  • ircu (Undernet ircd): fork sustancial con soporte para servicios y mejor gestión de netsplits
  • Bahamut: el ircd de DALnet, con soporte nativo para servicios y modificaciones al protocolo servidor-servidor
  • Unreal IRCd: derivado de Bahamut, ampliamente usado en redes medianas, con sistema de módulos
  • InspIRCd: reescritura completa desde cero, escrita en C++, diseño modular, soporte para TLS desde el principio
  • Charybdis: fork de ircd-ratbox, base del servidor de Freenode/Libera.Chat

Cada uno de estos servidores introdujo extensiones propias al protocolo. Algunas se estandarizaron de facto; otras quedaron limitadas a una red específica. El numeral 005 (RPL_ISUPPORT) se convirtió en el mecanismo por el cual un servidor anuncia qué extensiones soporta, permitiendo a los clientes adaptarse.

El protocolo entre servidores (S2S) divergió aún más que el protocolo cliente-servidor (C2S). Mientras que un cliente moderno puede conectarse a casi cualquier servidor IRC y funcionar razonablemente bien, los servidores de distintas genealogías no pueden conectarse entre sí. EFnet usa un protocolo S2S distinto al de Undernet, que es distinto al de IRCnet.

# Ejemplo de protocolo S2S (TS6, usado por Charybdis/Libera)
# El servidor envía su información al conectarse:
SERVER irc.example.com 1 :Descripción del servidor
SID 42A 1 42AAAAAAA :irc.example.com

# Presentación de usuario desde el servidor remoto:
UID 42AAAAAAB 1 1234567890 marco ~marco host.example.com host.example.com 0 +i :Marco Pellegrini

# Diferente del protocolo P10 de ircu (Undernet):
S irc.undernet.org 2 123456789 123456789 J10 ABAA :Undernet Server

Esta fragmentación del protocolo S2S ha sido una de las razones por las que IRC nunca tuvo una red verdaderamente unificada. Cada red grande desarrolló su propio dialecto interno.

Extensiones del protocolo: CTCP, DCC y más allá

El protocolo IRC base, tal como está definido en los RFCs, es deliberadamente simple. Las funcionalidades que los usuarios asocian con IRC (transferencia de archivos, chats privados directos, acciones, versiones de cliente) son extensiones construidas encima del protocolo base.

CTCP (Client-To-Client Protocol) fue diseñado por Michael Sanchez (autor de ircII) en 1990. No es un RFC, es una especificación informal que los clientes adoptaron de facto. CTCP usa el carácter de control \x01 (ASCII 1) como delimitador para encapsular mensajes especiales dentro de los mensajes PRIVMSG y NOTICE normales.

Los comandos CTCP más comunes:

  • VERSION: solicita la versión del cliente IRC del destinatario
  • PING: mide la latencia entre dos clientes
  • TIME: solicita la hora local del destinatario
  • USERINFO: información definida por el usuario
  • ACTION: el famoso /me hace algo, que los clientes muestran como * nick hace algo
# Un mensaje CTCP VERSION se ve así en el wire:
PRIVMSG marco :\x01VERSION\x01

# La respuesta típica de un cliente moderno:
NOTICE origen :\x01VERSION irssi v1.4.3 - https://irssi.org\x01

DCC (Direct Client-to-Client) es otra extensión de ircII, también de 1990. Permite establecer conexiones TCP directas entre dos clientes, sin pasar por el servidor. Se usa principalmente para transferencia de archivos (DCC SEND/GET) y chats directos (DCC CHAT).

El mecanismo es: el cliente que inicia la transferencia abre un socket TCP en su máquina, luego envía un mensaje CTCP DCC al destinatario con la dirección IP y el puerto donde está escuchando. El destinatario se conecta directamente. El servidor IRC ya no está en el camino.

# Un DCC SEND se negocia así:
PRIVMSG destino :\x01DCC SEND archivo.txt 167772161 1024 12345\x01
# Donde 167772161 es 10.0.0.1 en decimal (sí, en decimal, no en notación punteada)
# 1024 es el puerto, 12345 es el tamaño del archivo

DCC funcionó bien en la era pre-NAT. Cuando la mayoría de los usuarios pasaron a estar detrás de routers con NAT, DCC se volvió problemático: el cliente que inicia no puede recibir conexiones entrantes fácilmente. Surgió DCC REVERSE (o DCC Passive) para resolver esto: quien recibe el archivo es quien abre el puerto, invirtiendo la lógica.

IRCv3 es el intento más reciente de modernizar el protocolo de forma estandarizada. El grupo de trabajo IRCv3 (formado alrededor de 2012) ha publicado especificaciones para:

  • CAP negotiation: permite a cliente y servidor negociar capacidades extendidas al inicio de la conexión
  • SASL authentication: autenticación estándar sin depender de NickServ
  • multi-prefix: mostrar todos los prefijos de un usuario (ej: @+ para op con voz)
  • server-time: timestamps para mensajes, permitiendo mostrar historial del servidor
  • message-tags: metadatos adicionales en los mensajes sin romper la sintaxis base
  • batch: agrupa mensajes relacionados para reducir la carga en el cliente
  • labeled-response: correlaciona comandos con sus respuestas

La negociación CAP ocurre antes del login:

# Cliente solicita capacidades:
CAP LS 302

# Servidor responde con las capacidades disponibles:
:server CAP * LS :sasl server-time multi-prefix message-tags batch

# Cliente solicita las que quiere usar:
CAP REQ :sasl server-time multi-prefix

# Servidor confirma:
:server CAP nick ACK :sasl server-time multi-prefix

# Cliente termina la negociación:
CAP END

Declive relativo y legado técnico

El pico de uso de IRC fue alrededor de 2003-2004, cuando EFnet tenía más de 140.000 usuarios simultáneos. Desde entonces, el número ha caído de forma sostenida. Las razones son bien conocidas: AOL Instant Messenger, MSN Messenger, y eventualmente Slack, Discord y Teams ofrecieron experiencias más accesibles con historial persistente, notificaciones push y mejores mecanismos de gestión de identidad.

Lo que IRC nunca resolvió bien desde el nivel de protocolo:

  • Persistencia: si te desconectas, no recibes los mensajes que llegaron mientras estabas fuera. Los bouncers (IRCBouncer como ZNC) son el parche estándar, pero siguen siendo infraestructura adicional.
  • Identidad: el sistema de nicks sin autenticación nativa es fundamentalmente inseguro. NickServ es una solución de aplicación a un problema de protocolo.
  • Historial en el servidor: el protocolo no define cómo almacenar o recuperar historial. IRCv3 añade capacidades opcionales, pero dependen de la implementación de cada servidor.
  • Cifrado por defecto: TLS llegó tarde y aún no es universal. Conectarse a IRC en texto plano era (y en algunas redes, sigue siendo) lo predeterminado.

Dicho esto, el legado técnico de IRC es considerable. Fue el primer sistema de mensajería en tiempo real a escala de Internet. Sus decisiones de diseño (topología de árbol, modelo de canales con modos, protocolo de texto plano) influyeron en sistemas posteriores, a veces por adopción y a veces por reacción.

La especificación de IRCv3 sigue activa. Libera.Chat (heredera de Freenode, formada en 2021) tiene más de 20.000 usuarios simultáneos y soporta IRCv3 completo. OFTC, EFnet y varias redes más siguen operativas. Para proyectos de software libre que prefieren no depender de infraestructura corporativa, IRC sigue siendo una opción viable.

Técnicamente, lo más interesante de IRC hoy es precisamente su simplicidad: puedes implementar un cliente IRC básico en menos de 200 líneas de Python, conectarte a irc.libera.chat en el puerto 6667 (o 6697 para TLS) y estar chateando en minutos. No hay OAuth, no hay handshakes de 15 pasos, no hay SDKs propietarios. Un socket TCP y texto plano.

import socket

s = socket.socket()
s.connect(('irc.libera.chat', 6667))
s.send(b'NICK testuser\r\n')
s.send(b'USER testuser 0 * :Test User\r\n')
# Esperar 001 (RPL_WELCOME) antes de hacer JOIN
s.send(b'JOIN #python\r\n')
s.send(b'PRIVMSG #python :Hola desde un cliente de 5 líneas\r\n')

Esta accesibilidad es parte de por qué IRC ha sobrevivido más de tres décadas. No porque sea el mejor sistema de mensajería disponible, sino porque es el más transparente y el más sencillo de implementar desde cero. En un mundo de protocolos binarios, cifrados y propietarios, un protocolo de texto que puedes leer con tcpdump tiene un valor pedagógico difícil de reemplazar.

Preguntas frecuentes

¿Cuál es la diferencia entre EFnet, IRCnet, Undernet y DALnet?

Son redes IRC independientes que surgieron de escisiones sucesivas desde la red original. EFnet (1990) fue la primera gran escisión, por desacuerdos sobre políticas de acceso. Undernet (1992) nació como alternativa técnicamente más estable, con servicios como ChanServ para gestionar canales tras netsplits. DALnet (1994) añadió NickServ para registro de nicks. IRCnet (1996) es otra escisión de EFnet, con enfoque en soluciones técnicas de protocolo en lugar de servicios centralizados. Hoy, ninguna de estas redes se conecta entre sí; son redes separadas con usuarios y servidores independientes.

¿Por qué IRC no tiene historial de mensajes nativo?

Por decisión de diseño original. El RFC 1459 define IRC como un sistema de mensajería en tiempo real, no de almacenamiento. Los mensajes se entregan a los clientes conectados en el momento; si no estás conectado, no los recibes. Esto simplificó enormemente el protocolo y la implementación del servidor, pero dejó el problema de la persistencia sin resolver a nivel de protocolo. IRCv3 añade la capacidad server-time y define mecanismos opcionales de historial (chathistory), pero dependen de que cada servidor los implemente. La solución más usada sigue siendo el IRC bouncer: un proxy que permanece conectado en tu nombre y te entrega los mensajes cuando te reconectas.

¿Qué es un netsplit y por qué causa tantos problemas?

Un netsplit ocurre cuando la conexión entre dos servidores de una misma red IRC se interrumpe. Como la topología de IRC es un árbol sin ciclos, cualquier corte de enlace divide la red en dos fragmentos que funcionan de forma independiente. Desde tu perspectiva como usuario, verás cómo decenas o cientos de usuarios «abandonan» el canal simultáneamente con el mensaje «irc.servidor1.com irc.servidor2.com». Cuando la conexión se restaura, los dos fragmentos intentan sincronizarse. Los problemas surgen porque durante el split pueden haberse asignado el mismo nick a usuarios distintos en cada fragmento (nick collision), o haber cambiado los modos de un canal de forma conflictiva. En redes sin servicios como ChanServ, un netsplit puede resultar en que un canal quede sin operadores (opless), lo que históricamente fue explotado para tomar control de canales.

¿Qué es IRCv3 y qué problemas resuelve respecto al protocolo original?

IRCv3 es un conjunto de especificaciones extensiones al protocolo IRC, desarrollado por el grupo de trabajo IRCv3 desde aproximadamente 2012. No reemplaza al RFC 2812, sino que añade capacidades opcionales sobre él. Las principales mejoras incluyen: negociación de capacidades (CAP), que permite a cliente y servidor acordar qué extensiones usar sin romper compatibilidad; autenticación SASL, que elimina la dependencia de NickServ para la autenticación segura; etiquetas de mensaje (message-tags), que permiten adjuntar metadatos a los mensajes; y capacidades de historial del servidor. IRCv3 está implementado en InspIRCd, Charybdis, Unreal IRCd y otros servidores modernos, y es soportado por clientes como WeeChat, irssi (con plugins) y Textual.

¿Sigue siendo seguro usar IRC hoy en día?

Depende de la red y de cómo te conectes. IRC moderno soporta TLS en el puerto 6697 (definido en el RFC 7194 de 2014), y la mayoría de las redes activas lo ofrecen. Libera.Chat y OFTC, por ejemplo, permiten conectarse con TLS y verificar el certificado del servidor. SASL EXTERNAL permite autenticarte con tu propio certificado de cliente, eliminando la necesidad de contraseñas en texto plano. Lo que IRC no tiene es cifrado de extremo a extremo en los canales: los mensajes que envías a un canal son visibles para el operador del servidor. Para comunicaciones privadas cifradas end-to-end, OTR (Off-The-Record Messaging) es el plugin más usado, aunque no es parte del protocolo IRC base.