Prosody 0.11.2 y Conversations 2.19.x: Fallo de autenticación SASL con TLS 1.3
Resumen
Tras una actualización de la app Conversations (cliente XMPP para Android) a la versión 2.19.12, los usuarios comenzaron a experimentar fallos de conexión contra un servidor Prosody 0.11.2 sobre Debian 10 Buster. El problema se debía a incompatibilidades en la negociación SASL relacionadas con channel binding en TLS 1.3. La solución fue actualizar Prosody a 0.11.9 desde los repositorios de buster-backports.
Entorno afectado
| Componente | Versión |
|---|---|
| Sistema operativo | Debian 10.13 Buster |
| Prosody | 0.11.2-1+deb10u4 (paquete Debian) |
| LuaSec | 0.7 |
| Lua | 5.2 |
| Cliente XMPP | Conversations 2.19.12+playstore (Android) |
| Cifrado negociado | TLSv1.3 con TLS_AES_256_GCM_SHA384 |
Síntoma
El usuario no podía conectar con el servidor XMPP. El resto de usuarios con versiones anteriores de Conversations u otros clientes no presentaban problemas.
Diagnóstico
Error inicial: channel binding no soportado
El log de Prosody mostraba que la conexión TLS se establecía correctamente, pero la autenticación SASL fallaba inmediatamente:
Stream encrypted (TLSv1.3 with TLS_AES_256_GCM_SHA384)
Offering mechanism SCRAM-SHA-1
Offering mechanism SCRAM-SHA-1-PLUS
Offering mechanism PLAIN
Received[c2s_unauthed]: <auth mechanism='SCRAM-SHA-1-PLUS' xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
sasl reply: <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<malformed-request/>
<text>Proposed channel binding type isn't supported.</text>
</failure>
Causa: Conversations 2.19.x, al negociar SCRAM-SHA-1-PLUS sobre TLS 1.3, propone el tipo de channel binding tls-exporter (estándar para TLS 1.3, RFC 9266). Sin embargo, Prosody 0.11.2 con LuaSec 0.7 solo soporta tls-unique, que fue eliminado en TLS 1.3. Al no reconocer el tipo propuesto, Prosody rechaza la autenticación.
Error secundario: SCRAM-SHA-1 sin PLUS también falla
Al deshabilitar SCRAM-SHA-1-PLUS mediante la directiva:
disable_sasl_mechanisms = { "SCRAM-SHA-1-PLUS" }
Conversations negoció correctamente con SCRAM-SHA-1 (sin channel binding), pero Prosody seguía rechazando la autenticación con un error genérico:
Not offering disabled mechanism SCRAM-SHA-1-PLUS
Offering mechanism SCRAM-SHA-1
Offering mechanism PLAIN
Received[c2s_unauthed]: <auth mechanism='SCRAM-SHA-1' xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
sasl reply: <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<malformed-request/>
</failure>
Este segundo fallo indicaba que el client-first-message SCRAM que enviaba Conversations 2.19.x tenía un formato que Prosody 0.11.2 no era capaz de procesar correctamente. El error se producía en /usr/lib/prosody/util/sasl/scram.lua al validar el mensaje recibido.
Se confirmó que el problema no estaba en las credenciales del usuario, ya que se reprodujo con dos cuentas distintas en el mismo dispositivo.
Descarte: forzar solo PLAIN
Al deshabilitar tanto SCRAM-SHA-1-PLUS como SCRAM-SHA-1:
disable_sasl_mechanisms = { "SCRAM-SHA-1", "SCRAM-SHA-1-PLUS" }
Conversations se negó a conectar mostrando el error “Mecanismo SASL degradado”. Esto es una protección del cliente: si previamente se autenticó con SCRAM, no acepta un downgrade a PLAIN para evitar ataques de degradación.
Intentos fallidos de solución
1. Deshabilitar mecanismos SASL
Como se describe arriba, deshabilitar SCRAM-SHA-1-PLUS solo desplazó el problema a SCRAM-SHA-1. Deshabilitar ambos provocó el rechazo de Conversations por protección anti-downgrade.
2. Desactivar “Seguridad de transporte fuerte” en Conversations
Conversations ofrece una opción para requerir TLS 1.3. Desactivarla no resolvió el problema, ya que el servidor seguía negociando TLS 1.3 igualmente.
3. Añadir trazas de debug al módulo SASL
Se intentó insertar líneas de log en /usr/lib/prosody/util/sasl/scram.lua para capturar el contenido del mensaje SASL recibido. Sin embargo, el fichero utiliza local _ENV = nil (práctica de sandboxing en Lua 5.2) que anula el entorno global, impidiendo el uso de funciones como print, tostring o type fuera de las que fueron declaradas como locales antes de esa línea. Aunque log() estaba disponible como variable local, los intentos de usar tostring() y type() en la misma línea provocaban el error:
attempt to index upvalue '_ENV' (a nil value)
Esto impidió obtener el detalle del payload SASL que Conversations estaba enviando.
4. Buscar clientes XMPP alternativos
Se buscaron alternativas para que el usuario pudiera conectar temporalmente:
- Blabber.im: retirado de Google Play Store, última versión de 2022.
- Cheogram: no disponible en Play Store en el momento de la prueba.
- c0nnect easy messenger: disponible pero no llegó a probarse ya que se encontró la solución definitiva.
Solución aplicada
Actualización de Prosody a 0.11.9 desde buster-backports
Debian 10 Buster dispone de la versión 0.11.9 de Prosody en sus repositorios de backports. Esta versión incluye correcciones en el manejo de SASL que resuelven la incompatibilidad con clientes modernos.
Pasos realizados
1. Copia de seguridad de configuración y datos:
rsync -avz /etc/prosody/ /etc/prosody.backup/
rsync -avz /var/lib/prosody/ /var/lib/prosody.backup/
2. Habilitación del repositorio buster-backports (archivado):
echo "deb http://archive.debian.org/debian buster-backports main" > /etc/apt/sources.list.d/buster-backports.list
echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid
3. Instalación de la actualización:
apt update
apt install -t buster-backports prosody
Al preguntar sobre el fichero de configuración, se mantuvo la configuración existente.
4. Reinicio del servicio:
/etc/init.d/prosody restart
5. Eliminación de workarounds: Se eliminó la directiva disable_sasl_mechanisms de la configuración, permitiendo que Prosody ofrezca todos los mecanismos SASL de forma nativa.
Resultado
Tras la actualización a Prosody 0.11.9, Conversations 2.19.12 conecta correctamente utilizando SCRAM-SHA-1-PLUS sobre TLS 1.3 sin ninguna modificación adicional en la configuración del servidor ni del cliente.
Versiones finales
| Componente | Versión |
|---|---|
| Prosody | 0.11.9-1~bpo10+1 (buster-backports) |
| Conversations | 2.19.12+playstore |
| Negociación | SCRAM-SHA-1-PLUS sobre TLSv1.3 |
Notas adicionales
- Prosody 0.11.x ha alcanzado end-of-life. Se recomienda planificar la migración a Prosody 0.12.x o 13.x sobre un sistema operativo soportado (Debian 12 Bookworm o superior).
-
La configuración de Prosody 0.11 es compatible con 0.12 sin necesidad de cambios. Se puede verificar ejecutando
prosodyctl check configtras la actualización. -
Los datos de usuario en
/var/lib/prosodyson compatibles entre versiones de la rama 0.11.x y también con 0.12.x. - Este problema afectará progresivamente a más usuarios a medida que actualicen sus clientes XMPP a versiones que implementen
tls-exportercomo tipo de channel binding por defecto en TLS 1.3.