Mensageiro XMPP

Prosody: como instalar seu próprio servidor XMPP

O XMPP (antes conhecido como Jabber) é um protocolo de comunicação que foi a base do finado Google Talk e até serviu para formar as entranhas do que hoje é o WhatsApp. E você pode instalar seu próprio servidor agora mesmo.

Mas para que isso serve? É uma alternativa para fugir das grandes plataformas e ter sua própria instalação para se comunicar com amigos, parentes, colegas, funcionários e tudo mais que você imaginar.

Dá para trocar mensagens criptografadas (usando OMEMO e OpenPGP) tanto individualmente quanto em grupo e você pode configurar seu servidor para chamadas de áudio e vídeo também. Tudo sob sua gestão e controle.

O Prosody é uma das opções disponíveis para instalar seu próprio servidor XMPP. Além dele, há outras alternativas como o eJabberd e o OpenFire. Mas vamos optar pelo Prosody pela simplicidade, riqueza de recursos e leveza.

Neste tutorial vamos tratar apenas das funções básicas para troca de mensagens de texto e arquivos, incluindo criptografados, sem entrar na parte de comunicação por áudio e vídeo.

Para saber como configurar chamadas de áudio e vídeo, veja este post.

Ingredientes

Você vai precisar ter um domínio, mesmo que um gratuito da Freenom, e saber como editar os registros DNS para apontar os endereços corretamente. Você também vai precisar de um servidor VPS rodando Debian 11.

Como um servidor XMPP/Jabber não consome muitos recursos, você pode escolher qualquer plano baratinho como algum da Vultr. Você também precisa ter noção de como manusear um Terminal via SSH.

Criando os registros DNS

Como cada lugar tem caminhos diferentes para fazer a mesma coisa, você precisará ver como proceder para criar os seguintes registros DNS no domínio que vai usar para seu servidor XMPP.

Na tabela abaixo temos o hostname, tipo de registro DNS, time to live (TTL), prioridade, peso, porta e para onde cada linha aponta.

@                           A        3600                   <IP do VPS>
rooms                       A        3600                   <IP do VPS>
proxy                       A        3600                   <IP do VPS>
chat                        A        3600                   <IP do VPS>
_xmpp-client._tcp           SRV     18000    5   0  5222    chat.exemplo.com
_xmpps-client._tcp          SRV     18000    5   0  5223    chat.exemplo.com
_xmpp-server._tcp           SRV     18000    5   0  5269    chat.exemplo.com
_xmpps-server._tcp          SRV     18000    5   0  5270    chat.exemplo.com
_xmpp-server._tcp.rooms     SRV     18000    5   0  5269    chat.exemplo.com

Antes de mais nada, você precisa editar exatamente o que está em negrito e sublinhado. Depois de substituir o IP e domínio do que será seu servidor XMPP, prossiga com a criação dos registros DNS.

Assim fica mais fácil passar por essa parte do tutorial. Caso não consiga adicionar um desses registros onde mantém seu domínio, há uma solução: aponte seu domínio para o Cloudflare e gerencie os registros DNS por lá.

Abrindo as portas do firewall

É importante fazer a liberação das portas necessárias para o correto funcionamento do seu servidor XMPP. Para isso, vamos usar o UFW, que significa “firewall descomplicado” em inglês.

Instale o UFW com o seguinte comando:

apt install ufw -y

E agora rode esses comandos para liberar as portas necessárias:

ufw default deny incoming
ufw default allow outgoing
ufw allow 22
ufw allow 80
ufw allow 443
ufw allow 5000
ufw allow 5222
ufw allow 5223
ufw allow 5269
ufw allow 5270
ufw allow 5280
ufw allow 5281
yes | ufw enable
ufw reload

Instalando o Prosody

Agora vamos começar a por a mão na massa pra valer. O primeiro passo é adicionar o repositório de onde baixaremos o instalador do Prosody e também vamos puxar arquivos de outro repositório com módulos para o servidor XMPP.

echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/prosody.list
wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -
apt update
apt install prosody gnupg git mercurial lua-dbi-sqlite3 lua-unbound lua-event certbot

Depois precisamos interromper o serviço enquanto fazemos a configuração do servidor XMPP:

systemctl stop prosody.service
prosodyctl status

O segundo comando acima precisa informar “Prosody is not running”.

Instalando módulos da comunidade

Esses módulos incluem funcionalidades extras ou melhoradas para usar com seu servidor XMPP. Para prosseguir, vamos executar os seguintes comandos:

hg clone https://hg.prosody.im/prosody-modules/ /var/lib/prosody/modules/
chown root:prosody -R /var/lib/prosody/modules/

Gerando os certificados TLS

Certificados SSL são uma nomenclatura obsoleta, já que na verdade o SSL foi substituído pelo TLS. Então vamos gerar os certificados TLS para criptografar as comunicações entre servidor-servidor e servidor-cliente.

certbot certonly --standalone --agree-tos -m meu@email.com -d exemplo.com
certbot certonly --standalone --agree-tos -m meu@email.com -d chat.exemplo.com
certbot certonly --standalone --agree-tos -m meu@email.com -d rooms.exemplo.com
certbot certonly --standalone --agree-tos -m meu@email.com -d proxy.exemplo.com

Mais uma vez, altere somente aquilo que estiver exatamente em negrito e sublinhado e nada mais. Se por acaso você se deparar com o erro a seguir ao tentar renovar os certificados:

Attempting to renew cert (exemplo.com) from /etc/letsencrypt/renewal/exemplo.com.conf produced an unexpected error: Problem binding to port 80: Could not bind to IPv4 or IPv6.

É necessário interromper o processo do Prosody, para que desta forma o Certbot possa usar as portas necessárias para gerar os novos certificados TLS.

systemctl stop prosody

E em seguida renovar seus certificados:

certbot renew

Depois é hora de importar os novos certificados e, finalmente, iniciar novamente o serviço do Prosody:

prosodyctl --root cert import /etc/letsencrypt/live
systemctl start prosody

Configurando o Prosody

Agora nós já estamos na etapa final antes de poder usar nosso servidor XMPP. Vamos fazer os ajustes no arquivo de configuração para que tudo funcione como esperado.

O arquivo que vamos editar é /etc/prosody/prosody.cfg.lua:

admins = { "seu-usuario@exemplo.com" }
plugin_paths = { "/var/lib/prosody/modules" }
pidfile = "/var/run/prosody/prosody.pid"

c2s_ports = { 5222 } --Ports on which to listen for client connections.
s2s_ports = { 5269 } --Ports on which to listen for server-to-server connections.

c2s_direct_tls_ports = { 5223 } --Ports on which to listen for XMPP over TLS client connections.
s2s_direct_tls_ports = { 5270 } --Ports on which to listen for XMPP over TLS server-to-server connections.

http_ports = { 5280 }
https_ports = { 5281 }

http_interfaces = { "*", "::" }
https_interfaces = { "*", "::" }

contact_info = {
    abuse = { "mailto:contato@exemplo.com", "xmpp:seu-usuario@exemplo.com" };
    admin = { "mailto:contato@exemplo.com", "xmpp:seu-usuario@exemplo.com" };
    security = { "mailto:contato@exemplo.com", "xmpp:seu-usuario@exemplo.com" };
    support = { "mailto:contato@exemplo.com", "xmpp:seu-usuario@exemplo.com" };
};

modules_enabled = {
	"admin_adhoc"; 
	"admin_shell"; 
	"announce"; 
	"auto_answer_disco_info";
	"blocklist"; 
	"bookmarks2"; 
	"bosh"; 
	"carbons"; 
	"cloud_notify"; 
	"csi"; 
	"csi_battery_saver"; 
	"csi_simple"; 
	"debug_omemo"; 
	"dialback"; 
	"disco"; 
	"external_services";
	"groups"; 
	"http_avatar"; 
	"http_pep_avatar"; 
	"idlecompat";
	"limits"; 
	"mam"; 
	"net_multiplex";
	"offline"; 
	"pep"; 
	"ping"; 
	"presence_cache"; 
	"private"; 
	"register"; 
	"roster"; 
	"s2s_bidi"; 
	"saslauth"; 
	"server_contact_info"; 
	"smacks"; 
	"time"; 
	"tls"; 
	"turn_external"; 
	"uptime"; 
	"vcard4"; 
	"vcard_legacy"; 
	"version"; 
	"webpresence";
	"websocket"; 
}

disco_items = {
    { "exemplo.com", "Exemplo XMPP Server" };
    { "rooms.exemplo.com", "Salas de exemplo.com" };
    { "proxy.exemplo.com" };
    { "chat.exemplo.com" };
}

bosh_max_inactivity = 60

consider_bosh_secure = true
consider_websocket_secure = true

smacks_hibernation_time = 600
smacks_enabled_s2s = false
smacks_max_unacked_stanzas = 0
smacks_max_ack_delay = 60
smacks_max_hibernated_sessions = 10
smacks_max_old_sessions = 10

push_notification_important_body = "Nouveau Message"
push_notification_with_body = false 
push_notification_with_sender = false 
push_max_errors = 5 
push_max_devices = 5 

-- ###
-- ESSE TRECHO A SEGUIR PERMITE FAZER CHAMADAS DE ÁUDIO E VÍDEO
-- PARA SABER COMO CONFIGURAR, VISITE https://is.gd/94SRAb
-- ###
--turn_external_host = "turn.exemplo.com"
--turn_external_port = 3478
--turn_external_secret = "código-super-secreto"

--external_service_secret = "código-super-secreto"
--external_services = {
--    {
--        type		= "stun",
--        transport	= "udp",
--        host		= "turn.exemplo.com",
--        port		= 3478
--    }, {
--        type		= "turn",
--        transport	= "udp",
--        host		= "turn.exemplo.com",
--        port		= 3478,
--        secret		= true
--    }, {
--        type		= "turns",
--        transport	= "tcp",
--        host		= "turn.exemplo.com",
--        port		= 5349,
--        secret		= true
--    }
--}

allow_registration = false
c2s_require_encryption = true
s2s_require_encryption = true
s2s_secure_auth = true

limits = { c2s = { rate = "100kb/s"; }; s2sin = { rate = "100kb/s"; }; }

authentication = "internal_hashed"
archive_expires_after = "1w"
--archive_store = "sql"

log = { info = "/var/log/prosody/prosody.log"; error = "/var/log/prosody/prosody.err"; }

certificates = "certs"
https_certificate = "certs/exemplo.com.crt"

--storage = "sql"
--sql = { driver = "SQLite3", database = "prosody.sqlite" }

VirtualHost "bolha.one"
	name = "Exemplo XMPP Server"

Component "rooms.exemplo.com" "muc"
	name = "Salas do Exemplo"
	restrict_room_creation = "local"
	modules_enabled = { "muc_mam"; "muc_mam_hints"; "muc_limits"; "vcard_muc"; "bob"; }
	muc_log_by_default = true;
	muc_log_all_rooms = false;
	max_history_messages = 20;
	muc_log_expires_after = "1w"
	muc_log_cleanup_interval = 4 * 60 * 60

Component "chat.exemplo.com" "http_file_share"
    http_file_share_size_limit = 1024 * 1024 * 1000
    http_file_share_expires_after = 60 * 60 * 24 * 30

Component "proxy.exemplo.com" "proxy65"
	proxy65_address = "exemplo.com"
	proxy65_acl = { "exemplo.com" }

Mais uma vez, altere exatamente os pontos destacados com negrito e sublinhado para se adequar a sua realidade. Eles incluem informar o domínio usado por você e também dar nome para os componentes do servidor XMPP.

É no arquivo de configuração você define qual usuário terá direitos de administrador do sistema alterando a linha admins = { "seu-usuario@exemplo.com" }.

Mais pra frente você verá como criar um usuário. Os endereços que parecem um e-mail são chamados JID (Jabber ID) e precisam ser exatamente iguais para o sistema considerar o usuário como administrador.

Essa configuração acima é baseada no arquivo de configuração de um servidor perfeitamente funcional que montei. Mas para ver se está tudo correto após suas alterações, rode o seguinte comando:

prosodyctl check config

Se nenhum erro for mostrado, vamos continuar.

Como esta é nossa primeira instalação e ainda não chegamos ao ponto de renovar o certificado TLS do domínio como já descrito anteriormente, vamos precisar executar o seguinte comando que você já está familiar:

prosodyctl --root cert import /etc/letsencrypt/live

Por fim, finalmente vamos ativar o serviço do Prosody durante o boot e iniciar o servidor XMPP:

systemctl enable --now prosody.service

Você pode checar os arquivos /var/log/prosody/prosody.log e /var/log/prosody/prosody.err para debugar eventuais erros.

Utilizando o Prosody

Agora que você chegou ao fim deste tutorial, está na hora de usar seu servidor. Para criar um novo usuário, você vai usar o seguinte comando:

prosodyctl adduser usuario@exemplo.com

Já sabe quais trechos precisa editar, né? Pois bem. O comando vai perguntar qual senha você deseja usar para acessar a conta em um cliente compatível. Depois, para que entrem em contato via XMPP, divulgue seu JID.

O Prosody, assim como outros servidores XMPP, permite que o próprio usuário interessado crie uma conta diretamente a partir de um cliente compatível mas por razões de segurança este recurso vem desativado.

Se for do seu interesse deixar que o usuário se vire para criar as contas em vez de fazê-las manualmente, no arquivo de configuração mude allow_registration de false para true.

Clientes compatíveis

São vários os programas que você pode usar para se comunicar com outros contatos na rede XMPP/Jabber. Um dos mais conhecidos é o Pidgin, mas temos também o Gajim e o Miranda NG entre as opções.

Pidgin logado no servidor XMPP Prosody
Cliente Pidgin logado no servidor XMPP Prosody.

O Pidgin e o Miranda servem para você ter acesso a funcionalidades básicas como conversas de texto sem criptografia e participação em grupos. Já com o Gajim você pode fazer isso tudo com direito a criptografia.

No celular você pode instalar o Conversations no Android, o qual permite usar todas as funcionalidades permitidas por um servidor XMPP, incluindo criptografia e até mesmo chamadas de vídeo e áudio.

Para uma lista de outras opções de clientes para diversas plataformas, visite esta página no site oficial do XMPP.

Este tutorial foi baseado neste passo a passo criado por Samir Parikh.

Sem rastreadores. Sem anúncios. Sem paywall.

Se você gostou do conteúdo, considere pagar um cafezinho para o autor.

Este blog não mostra mais anúncios, nem conta com rastreadores ou paywall. De verdade. Não rouba seus dados e nem os vende. Ele conta apenas com a colaboração dos leitores.

Botão Doar com Mercado Pago