Bad Daemons

XMPP en móviles: mentiras habituales y cómo mejorar tu servidor

La primera parte está basada en el gran articulo de Daniel Gultsch, "The State of Mobile XMPP in 2016", muy recomendable. Si alguien quiere pasar directamente a cómo montar un servidor que mejore las conexiones móviles, que clique aquí.

Pasa cada vez menos, pero sigue habiendo aún el mito de que XMPP o jabber no sirve para usarlo en el móvil. Hay varios motivos por los que se dice esto, comentaré tres. El primero es que usa conexiones sincronas, es decir, conexiones en las que o estás conectado o no, por lo tanto si pierdes cobertura por el motivo que sea, no estás conectado. Esto tiene problemas evidentes, cómo la posible pérdida de mensajes. El segundo es que también se podrian perder si no hubiese ningún cliente conectado y alguien envia un mensaje. Y por último está el tema del consumo de bateria, que es muy elevado, ya que en XMPP se está continuamente enviando información, aunque no se vea. Todo estos argumentos eran cierto, pero hace ya mucho que no lo es.

Para arreglar estos problemas, surgieron tres XEP, que son Stream Management, Message Archive Management y Client State Indication. El primero hace que la sesión se mantenga abierta durante unos cinco minutos (por defecto) aún habiendo perdido la conexión, por lo que cuando la retomamos en ese lapso de tiempo, es cómo si no nos hubiesemos caido nunca. No hay logueo, ni renegociación de otr si se está usando, ni nada. El segundo se encarga de guardar y enviar los mensajes que se envian cuando no hay ningún cliente conectado. El tercero se encarga de decirle al servidor que en ese momento, el cliente no está en uso y no deberia enviarle nada que no sea muy importante.

En fin, una vez analizado el problema, hay que ponerle solución. Por suerte gente más inteligente y trabajadora ha hecho que aplicar todo lo mencionado anteriormente a nuestro propio servidor, se pueda hacer en menos de 20 minutos. De regalo veremos cómo hacer accesible el servidor desde la red tor, cómo permitir subir imágenes fácilmente a las salas, cómo hacer que todos los mensajes lleguen a todos los clientes conectados y cómo añadir la posibilidad de bloquear cuentas molestas.

Hay un tema, y es que el único cliente que soporta absolutamente todo lo mencionado, sólo funciona en móviles android. Quien use IOS, está jodido, sin más. No ya por que no pueda usar todos esos XEP tan útiles, sinó por que hace ya tiempo que pusieron un límite que corta cualquier aplicación que funcione en segundo plano más de 3 minutos, por lo que si no estás mirando el cliente, este se cierra, siempre. Solución? De momento, ninguna, que yo sepa. Hace falta adaptar un servidor o hacer un XEP que use PuSH (PubSubHubbub). El XEP existe, pero es experimental. Por lo que, de momento, tocará esperar al experimento de Chatsecure, Zom y Conversations.

Para que sea un manual que sirva a todo el mundo, usaremos el repositorio Mercurial de los módulos para prosody, por lo que cada una deberá encargarse de instalar, según su distribución, Prosody. Si se usa Debian, recomiendo usar el repositorio propio de Prosody. Se pueden ver las instrucciones aquí. Si aún no tenéis instalado Prosody, podéis consultar el tutorial que hizo el bueno de haton en elbinario.

Primero de todo, hay que instalar Mercurial y clonar los módulos en algún sitio. En el ejemplo, será en el $HOME del usuario.

cd ~/
aptitude install mercurial
slackpkg install mercurial
# lo que sea que instale mercurial
hg clone https://hg.prosody.im/prosody-modules/ prosody-modules

Extenderemos un poco más la información de lo que hacen los módulos que instalaremos:

  • mod_smacks (Stream Management): Mantiene una cola de las últimas stanzas enviadas, que sólo se borran cuando se ha confirmado que se han recibido. Esto significa que cuando el cliente se desconecta, el servidor espera un periodo de tiempo por defecto en el que sigue actuando cómo si el cliente está conectado, de modo que el cliente sigue apareciendo online y pudiendo recibir mensajes de manera normal.
  • mod_csi (Client State Indication): No hace nada por defecto, necesita dos módulos más, que en conjunto hace que el uso de la bateria y de los datos transferidos sea mucho más bajo:
    • mod_throttle_presence: Corta los cambios de status cuando el cliente está en segundo plano.
    • mod_filter_chatstates: Corta las notificaciones estados, cómo cuando alguien escribe.
  • mod_mam (Message Archive Management): Guarad las conversaciones de manera centralizada en el servidor y sincroniza las conversaciones entre distintos dispositivos. Esto pasa tanto en chats privados cómo públicos.

Estos son los módulos útiles que vienen de regalo:

  • mod_carbons: Sirve para distribuir las conversaciones entre los distintos clientes. A mi, en general, me parece una gilipollez, pero se ve que suele gustar. Hay que tener en cuenta que esto no funciona si se suele usar otr. Está pensado para funcionar sin cifrado o con OMEMO, un nuevo tipo de cifrado que promete, pero que de momento solo es usable con Conversations (hay que tener en cuenta que no es tan maduro cómo otr).
  • mod_http_upload: Sirve para subir imagenes al servidor jabber y que devuelva la dirección web de esta. Bastante útil para compartir fotos o archivos ligeros. Hay varios clientes que lo soportan.
  • mod_onions: Sirve para servir un dominio de la red onion de tor. Se puede usar tanto con un virtualhost en la clearnet como sólo el onion. Lo primero tiene sentido si quieres más privacidad desde el cliente, desde el lado del servidor no hay, ya que su dominio de la clearnet lo hace localizable.
  • mod_blocking: Sirve para bloquear JID (Captain Obvius al rescate). Es un complemento del módulo mod_privacy, que ya trae por defecto, y que de hecho lo necesita cómo dependencia.
cp -r ~/prosody-modules/mod_smacks/ /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_csi/ /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_throttle_presence/ /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_filter_chatstates/ /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_mam/ /usr/lib/prosody/modules/

cp -r ~/prosody-modules/mod_carbons /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_http_upload/ /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_onions/ /usr/lib/prosody/modules/
cp -r ~/prosody-modules/mod_blocking/ /usr/lib/prosody/modules/

Ahora están instalados, habrá que configurarlos y ya estaremos. Un consejo, poned los parámetros en el mismo orden o al menos similar al que ponga yo. De no hacerlo, algunas opciones podrian no funcionar o funcionar mal. Avisadas quedáis.

  -- Hay que añadirlo a la misma variable existente, sinó lo sobreescribe
  modules_enabled = {
                  ...
                  "smacks";
                  "csi";
                  "throttle_presence";
                  "filter_chatstates";
                  "mam";

                  "carbons";
                  "onions";
                  "http";
                  "privacy";
                  "blocklist";
  };

  -- Torifica todas las conexiones
  onions_tor_all = true
  -- Funciona tanto con onions cómo con servidores de la clearnet
  onions_only = false
  -- Mapea servidores de la clearnet con sus onions para que vaya más rápido
  -- al resolver los segundos
  onions_map = {
          ["jabber.calyxinstitute.org"] = "ijeeynrc6x2uy5ob.onion";
          ["riseup.net"] = "4cjw6cwpeaeppfqz.onion";
          ["jabber.otr.im"] = "5rgdtlawqkcplz75.onion";
          ["jabber.systemli.org"] = "x5tno6mwkncu5m3h.onion";
          ["securejabber.me"] = "giyvshdnojeivkom.onion";
          ["so36.net"] = "s4fgy24e2b5weqdb.onion";
          ["autistici.org"] = "wi7qkxyrdpu5cmvr.onion";
          ["inventati.org"] = "wi7qkxyrdpu5cmvr.onion";
          ["jabber.ipredator.se"] = "3iffdebkzzkpgipa.onion";
          ["cloak.dk"] = "m2dsl4banuimpm6c.onion";
          ["im.koderoot.net"] = "ihkw7qy3tok45dun.onion";
          ["anonymitaet-im-inter.net"] = "rwf5skuv5vqzcdit.onion";
          ["jabber.ccc.de"] = "okj7xc6j2szr2y75.onion";
          ["daemons.cf"] = "daemon4jidu2oig6.onion";
  }

  -- Sólo funciona con sql, no va con internal ni internal_hashed
  storage = { archive2 = "sql"; }

  -- Guarda los mensajes un sólo día
  archive_expires_after = "1d"

Os fijaréis que no sale nada en la configuración al respecto de varios módulos. Eso es debido a que los valores que tiene por defecto son válidos para el caso, por lo que no hace falta ponerlos. Si por lo que sea queréis cambiar los valores por defecto, echadle un ojo al final del articulo, en Recursos, que hay una lista de links a los módulos de prosody en los que se ve como configurarlos.

No tiene que ver directamente con el tema que se trata, pero me encontré con ello al intentar tener dos virtualhosts con el módulo http_upload. Debe haber un certificado definido únicamente, y debe ser fuera de los virtualhosts. Podréis verlo más claramente en la configuración de mi servidor que adjunto al final, en la sección Recursos. Esto es debido a que Prosody no permite, de momento, concretar más de uno, y si se intenta puede llevar a comportamientos inesperados, cómo las cinco horas que pasé intentando arreglar el error SSL que devolvia al entrar con el navegador al servidor web de Prosody, hasta que me dió por preguntar en el canal #prosody de Freenode y me dijeron que no iba aún.

PD: Recomiendo definir la siguiente linea dentro del array de ssl:

options = { "no_sslv2", "no_sslv3", "no_tlsv1", "no_ticket", "no_compression", "cipher_server_preference", "single_dh_use", "single_ecdh_use" }.

El único valor añadido es el de no_tlsv1, que hace lo obvio. Así dan más puntitos en el escaner SSL de xmpp.net.

PD2: en daemons.cf tengo un servidor XMPP que de hecho tiene activos todos estos módulos. Me gustaria ofrecerlo cómo servicio, pero el dominio que tengo es gratuito y no me fio de que no desaparezca cualquier día, con los problemas que conllevaria. En el momento en el que pueda alquilar un dominio, abriré el registro de este servidor.

Recursos: