XMPP Server auf Raspberry Pi3

1. Wieso das ganze?

Nachdem ich wiedermal nach einer alternative für Whatsapp für mein Android Smartphone gesucht habe bin ich auf diese Seite gestoßen: https://www.kuketz-blog.de/conversations-sicherer-android-messenger/
Alles in diesem Blog hat mich überzeugt XMPP für die Zukunft zu Nutzen. Conversations schlägt einen eigenen Server vor, bei dessen Nutzung aber Gebühren pro Jahr anfallen. Da ich einen eigenen kleinen Server (Windows7) betreibe, der 24/7 online ist, lag es nahe auf diesem einen XMPP Server einzurichten, damit ich wirklich komplett unabhängig von anderen bin.

 

2. Der Messenger

Schnell wurde mir klar ich werde Conversations testen und bei Erfolg meine Freunde versuchen zu überzeugen auch – zumindest für mich – zu wechseln oder zumindest über eine Parallel-Installation nachzudenken. Die erste Hürde über die ich stolperte war: Wo bekomme ich Conversations kostenlos her. Im Playstore von Google kostet der Messenger Geld. Komisch, ein Opensource Programm das Geld kostet? Da ich die „Google Umfrage App“ nutze war hier noch Guthaben übrig, das ich zum kauf der App nutzte. Später stellte sich heraus, im alternativ-Appstore F-Droid ist Conversations kostenlos zu beziehen. Hätte ich das mal eher gewusst. Naja.

 

3. Wahl der Serversoftware

Ich betreibe für FTP & Co. sowieso einen eigenen Server 24/7 und dieser läuft mit Windows 7 so entschied ich mich OpenFire zu installieren. Leider bin ich überhaupt nicht mit der Einrichtung zurechtgekommen. 1000 Einstellmöglichkeiten, kaum Dokumentation im Netz irgendwie – doof.

Es gab aber 2 Alternativen: Prosody und eJabberd
Beide Linux 🙁 Nach viel lesen habe ich mich für Prosody entschieden, da hier LUA als Programmiersprache verwendet wurde und so die Möglichkeit für eine große Community besteht sog. Module zu programmieren was auch tatsächlich der Fall ist. (Dazu mehr weiter unten)

 

4. Endlich ein Raspberry Pi

So ein Ding wollte ich schon immer haben. Jetzt entstand Bedarf 🙂
Von der Leistung her sollte es egal sein, welcher Pi es ist (Prosody verbraucht extrem wenig Ressourcen), aber da RPi3 WLAN onboard hat, schien es mir die klügste Entscheidung die jüngste Generation zu kaufen. Gekauft wurde bei Rasppishop.de

Als Betriebssystem habe ich Raspbian genommen. Eine Anleitung zum installieren spare ich mir, da es die zuhauf im Netz gibt. (Raspbian installieren)

Jetzt fingen die Probleme aber schon vor Prosody erst an. Blitzsymbol wenn der RPi3 viel zu arbeiten hatte. (Der RaspberryPi3 zeigt ein Symbol per OSD an, wenn Unterspannung herrscht) Hmm, mein Netzteil kann 3A? Nach viel lesen wurde es klarer. Das Kabel ist schuld. Ich habe ein – in meinen Augen – hochwertiges USB Kabel genommen. Aber die Querschnitte sind wohl trotzdem zu klein gewesen. Also ein USB Kabel von meiner externen Festplatte genommen (so ein schön dickes und kurzes) und siehe da – jetzt keine Probleme mehr.

 

5. Vorbereitungen

  • DynDNS anlegen um die Erreichbarkeit bei wechselnder IP zu gewähleisten
  • Ports im Router freigeben
  • SSL Zertifikat von externem Anbieter (in meinem Fall Let’s Encrypt) erstellen

Als DynDNS Anbieter habe ich mich für DDNSS.de entschieden. Kostenlos und man braucht keinen extra Client um ein „ich-bin-am-leben-Signal“ zu senden.
Nach dem erfolgreichen Anmelden und einrichten seht ihr auch Beispiele, wie diese DynDNS Adresse in eurem Router einzutragen ist. Der Router übermittelt nun bei jeder Änderung der IP die Daten an euren Anbieter und von außen ist der RPi immer unter der gleichen Adresse zu erreichen.

Wenn wir gerade schon in der Oberfläche vom Router sind, können wir auch schon die benötigten Ports freigeben.

443 TCP (nachher fürs SSL-Zertifikat)
5222 TCP (Client-to-Server Connections (C2S))
5269 TCP (Server-to-Server Connections (S2S))

Das komplizierteste am XMPP Server war in meinen Augen die Sache mit den Zertifikaten. Klar, man kann einfach ein eigenes Zertifikat erstellen lassen und gut ist, aber dann bekommen die neuen Nutzer nach der Anmeldung auf eurem Server einmalig die Meldung, dass das Zertifikat selber signiert ist und damit eigentlich nicht vertrauenswürdig. Auch ein „Wie_gut_ist_mein_Server_Test“ auf: IM Observatory fällt dank eigenem Zertifikat mit einem F miserabel aus. Mit einem offiziell signierten Cert bekommt ihr – wenn der Rest auch passt – ein schönes, grünes A. Mach euch nix vor, ohne Lupenreinem Sicherheitscheck wird es euch schwer fallen andere davon zu überzeugen von Whatsapp zu euch zu wechseln.

Für Let’s Encrypt gibt es einen eigenen Client um die Zertifikate auf den heimischen Rechner zu holen: Certbot
Mittels:

sudo apt-get update
sudo apt-get install certbot

werden die Paketlisten aktualisiert und installiert ihr den Client.
dann per:

sudo certbot certonly --standalone -d EUER_SERVER.ddnss.de

das „besorgen“ des Zertifikats anstoßen.
Nach Aufruf des Clients muss eine E-Mailadresse hinterlegt und den Nutzungsbedingungen zugestimmt werden.
Im Verzeichnis

/etc/letsencrypt/live/EUER_SERVER.ddnss.de/

sollten nun 5 Dateien zu finden sein:
cert.pem chain.pem fullchain.pem privkey.pem README
Zugriff auf dieses Verzeichnis nur mit root möglich, also per

sudo su

zum root machen und dann im verzeichis nachschauen.
Einbinden werden wir diese nach der Installation von Prosody.
Mit:

exit

verlassen wir wieder den root-User.

 

6. Installation Prosody

Nun aber zur eigentlichen Installation:
Zuerst wieder die Paketlisten aktualisieren

sudo apt-get update

danach prosody installieren

sudo apt-get install prosody

Konfiguration von Prosody anpassen

sudo nano /etc/prosody/prosody.cfg.lua

Sucht nach dem Eintrag:
admins = { }
und ändert diesen auf:
admins = { "EUER_ADMIN_USER@EUER_SERVER.ddnss.de" }
Als nächstes sucht ihr:
allow_registration = false;
und ändert diesen auf:
allow_registration = true;
Dann sucht ihr:

VirtualHost "example.com"
        enabled = false -- Remove this line to enable this host
 
        -- Assign this host a certificate for TLS, otherwise it would use the one
        -- set in the global section (if any).
        -- Note that old-style SSL on port 5223 only supports one certificate, and will always
        -- use the global one.
        ssl = {
                key = "/etc/prosody/certs/example.com.key";
                certificate = "/etc/prosody/certs/example.com.crt";
        }

und ändert auf:

VirtualHost "EUER_SERVER.ddnss.de"
	ssl = {
		key = "/etc/prosody/certs/privkey.pem";
		certificate = "/etc/prosody/certs/fullchain.pem";
	}

Den Rest kann man erstmal so belassen. Wir schließen die Bearbeitung mit „STRG-X“ ab und betätigen mit der Taste „J“ dass wir speichern wollen.

Nun müssen wir die die vorher erstellten Zertifikate an den den Ort kopieren, wie wir ihn in der Konfiguration definiert haben.
Das Problem ist, dass die Zertifikate nur von root gelesen werden dürfen und somit prosody diese nicht lesen kann.
Wir müssen also den Besitz die kopierten Zertifikate an prosody zusprechen und die Berechtigungen setzen.

Wir machen also:

sudo su
cp /etc/letsencrypt/live/EUER_SERVER.ddnss.de/privkey.pem /etc/prosody/certs/
cp /etc/letsencrypt/live/EUER_SERVER.ddnss.de/fullchain.pem /etc/prosody/certs/
chown -R prosody:prosody /etc/prosody/certs/privkey.pem
chown -R prosody:prosody /etc/prosody/certs/fullchain.pem
chmod -R 700 /etc/prosody/certs/privkey.pem
chmod -R 700 /etc/prosody/certs/fullchain.pem
exit

Ich habe irgendwo im Internet ein kleines Bashscript (Quelle leider unbekannt) gefunden das einem die Arbeit abnimmt und dabei auch gleich die Zertifikate erneuert, wenn erforderlich. So könnte man das Script automatisiert laufen lassen und braucht sich um nichts mehr kümmern.

Anlegen des Scripts:

sudo nano certs_erneuern.sh

Mit diesem Inhalt füllen:

#!/bin/bash
letsencrypt="/etc/letsencrypt/live/EUER_SERVER.ddnss.de/"
certs="/etc/prosody/certs/"
prosody="/etc/prosody/"
/usr/bin/certbot renew >> /var/log/certbot-renew.log
 
   find "${letsencrypt}" -name "*.pem" | while read -r file
 
do
   cp "${file}" "${certs}"
   chown -R prosody:prosody "${prosody}"
   chmod -R 700 "${certs}"
   /etc/init.d/prosody restart
done

Wir schließen die Bearbeitung mit „STRG-X“ ab und betätigen mit der Taste „J“ dass wir speichern wollen.

Script ausführbar machen:

sudo chmod +x certs_erneuern.sh

Mit:

sudo ./certs_erneuern.sh

ausführen.

Jetzt starten wir den Server:

sudo /etc/init.d/prosody restart

Nun legen wir unseren vorhin definierten admin als User an:

sudo prosodyctl register EUER_ADMIN_USER@EUER_SERVER.ddnss.de EIN_SEHR_SICHERES_PASSWORD

Am besten gleich noch euren „normalen“ Standarduser hinterher. (Könnt ihr aber auch direkt über Euren Client machen, da ihr
allow_registration = true;
gesetzt habt.)

sudo prosodyctl register EUER_STANDARD_USER@EUER_SERVER.ddnss.de EIN_SICHERES_PASSWORD

Jetzt sollte alles funktionieren und laufen. Soweit so gut.
Über Module schreibe ich demnächst mehr.

Auf jeden Fall sollte euer XMPP Server nun laufen und ihr könnt ausführlich mit neuen Usern testen.

18 thoughts on “XMPP Server auf Raspberry Pi3

  1. Hallo,

    mit Interesse habe ich Deine Anleitung gelesen und würde das auch gern umsetzen.

    Ich habe bereits einen Raspi und habe dort Nextcloud (https://canox.net/2016/06/die-eigene-cloud-mit-dem-raspberry-pi-und-nextcloud/) eingerichtet. Das funktioniert wunderbar und alle in der Familie sind begeistert, dass Termine und Kontakte synchron sind.

    Jetzt würde ich gern zusätzlich auf dem gleichen Raspi den XMPP Server nach Deiner Anleitung installieren.

    Leider bin ich nicht so ein Super-Experte. Die Zertifikate von LetsEncrypt aktualisieren sich ja bei meinem Nextcloud und sind somit vorhanden – dann müsste nur noch der Copy-Job für Prosody greifen – richtig?

    Wie sieht es mit Anfragen mit Port 443 aus? Nextcloud nutzt ebenfalls den Port – kann ich irgendwo einen anderen sicheren Port für XMPP definieren, oder kommen sich dann Nextcloud und Prosody ins Gehege?

    Was denkst Du über meinen Ansatz? Oder sollte ich für XMPP lieber einen anderen Raspi nehmen?

    Wegen Stromverbrauch wäre es mir allerdings lieber, wenn beide Dienste auf einem Raspi funktionieren würden.

    Würde mich freuen, wenn ich eine Antwort erhalten würde.

    Viele Grüße aus Lemgo
    Tim

    –> vielleicht kannst Du mit Steven von Canox.net zusammen eine Anleitung dafür entwickeln. Das wäre für viele Leute die eierlegennde Wollmilchsau, denn um vor WhatsApp und Dropbox zu entkommen wäre das die ideale Lösung.

    1. Hallo Tim,

      das dürfte ohne Probleme realisierbar sein. Die Zertifikate bestätigen ja nur, das deine Dyn-DNS auch wirklich von diesem Gerät (Raspi) stammt. Es hat also nichts damit zu tun welches Programm die Zertifikate benutzt. Der Port 443 ist also nur für Certbot nötig um die Zertifikate zu bestätigen.
      Es reicht also entweder die Zertifikate zu kopieren oder noch einfacher; verweise einfach auf die vorhanden.
      VirtualHost „EUER_SERVER.ddnss.de“
      ssl = {
      key = „/nextcloud…./certs/privkey.pem“;
      certificate = „/nextcloud…./certs/fullchain.pem“;
      }
      Beim Verweisen auf die vorhanden nicht vergessen die Berechtigung für prosody zu setzen.

      Also erst mal alles ohne Gewähr, da ich mich wie gesagt auch nicht sooo dolle in Linux auskenne.
      Wäre schön, wenn du ein Feedback gibts ob es so funktioniert hat.

      Gruß Robert

  2. Hallo Robert,

    danke für Deine Antwort – ich bin noch nicht weitergekommen.

    Das Thema ist für mich recht sperrig – aber ich möchte es nochmal versuchen.

    Dein Satz:
    Beim Verweisen auf die vorhanden nicht vergessen die Berechtigung für prosody zu setzen.

    verstehe ich nicht. Was für eine Berechtigung muss gesetzt werden?

  3. Hallo Tim,
    also in Linux ist es so, dass nicht jeder automatisch lese und Schreibrechte auf Dateien hat.
    Im Fall von LetsEncrypt hat nur LE und root zugriffsrechte auf die Zertifikate (und vermutlich nextcloud). Wenn also Prosody diese auch lesen muss oder will, muss man dies erlauben. In dem Fall:
    chmod -R 700 /etc/nextclound/certs/privkey.pem
    chmod -R 700 /etc/nextclound/certs/fullchain.pem
    Aber mach lieber eine kopie der 2 Dateien, nicht das was anderes verbogen wird. Bin mir da nämlich auch nicht 100% sicher. Also besser mit root eine Kopie der 2 Dateien machen und dann:

    chown -R prosody:prosody /etc/prosody/certs/privkey.pem
    chown -R prosody:prosody /etc/prosody/certs/fullchain.pem
    (Besitz an prosody zuweisen)

    chmod -R 700 /etc/prosody/certs/privkey.pem
    chmod -R 700 /etc/prosody/certs/fullchain.pem
    (Leserechte setzen)

    1. Hallo Wolfgang,

      freut mich, wenn alles so gut funktioniert hat.
      Das mit der Verschlüsselung ist „etwas“ umständlich in Conversations gelöst, finde ich.
      Vorgehensweise:
      Ich schreibe jmd unverschlüsselt in Conversations an. Füge ihn zu meinen Kontakten hinzu. Mein gegenüber muss mich auch zu seinen Kontakten hinzufügen (In Conv). Erst jetzt werden die Schlüssel übertragen und man kann OMEMO an machen und den Schlüssel des gegenüber per Schiebeschalter bestätigen. Wichtig ist nur, dass beide den anderen in seinen Kontakten von Conversations hat.
      Server seitig muss – soweit ich mich erinnere – nichts eingestellt werden.

      Was in meiner Anleitung noch fehlt ist das mod_http_upload (Für die Möglichkeit Bilder und Dateien zu verschicken) Hoffe ich finde bald die Zeit das nachzutragen.

  4. Vielen Dank!
    Jetzt verstehe ich das. OMEMO muss auf den *Clients* laufen. Dem Server ist es egal, was er überträgt.

    Bisher hab ich mit Conversations und Pidgin getestet. Da Pidgin nicht so einfach zu OMEMO zu überreden ist, ging das auch nicht. Mit Gajim (Plugin herunterladen und aktivieren) ist das wie Zaubern! 😉

    *** Jetzt – bitte, bitte – noch die Anleitung für das mod_http_upload ***

    und meine Daten können in Zukunft in Deutschland mitgelesen werden und müssen nicht mehr über den großen Teich!

  5. Hallo Robert,
    danke für die gute Anleitung, auch in Hinblick darauf, was man machen muss, wenn man schon eine Nextcloud laufen hat. Bei mir läuft die Cloud auf einem kleinem Desktop-PC und der Prosody auf einem RasPi. Klappt aber trotzdem gut. Bin soweit zufrieden.
    Aber wäre es möglich, dass du noch erklärst, wie du deinen Prosody konfiguriert hast? Ich habe z.B. nirgends gefunden, wie ich die Speicherdauern für nicht abgerufene Messages etc. einstellen kannst (Zitat aus deinem anderen Post: „Die Maximale Dateigröße auf meinem Server ist 100MB. Versendete Dateien werden 14 Tage bei Nichtzustellung vorgehalten.“).
    Legst du die Benutzer händisch über prosodyctl an oder hast du da eine komfortable Lösung, bei der man sich nicht immer auf dem Raspi einloggen muss?
    Welche Plugins hast du aktiviert und warum?
    Viele Grüße,
    Jens

    1. Hallo Jens,
      die Speicherdauer für nicht abgerufene Messages wüsste ich jetzt selber nicht. Ich habe nur die Speicherdauer für den http_upload auf 14 Tage eingestellt.
      —-
      http_upload_expire_after = 60 * 60 * 24 * 14
      http_max_content_size = 1024 * 1024 * 100
      —-
      Hier meine module:
      modules_enabled = {
      — Generally required
      „roster“; — Allow users to have a roster. Recommended 😉
      „saslauth“; — Authentication for clients and servers. Recommended if you want to log in.
      „tls“; — Add support for secure TLS on c2s/s2s connections
      „dialback“; — s2s dialback support
      „disco“; — Service discovery

      — Not essential, but recommended
      „private“; — Private XML storage (for room bookmarks, etc.)
      „vcard“; — Allow users to set vCards

      — These are commented by default as they have a performance impact
      –„privacy“; — Support privacy lists
      –„compression“; — Stream compression (Debian: requires lua-zlib module to work)

      — Nice to have
      „version“; — Replies to server version requests
      „uptime“; — Report how long server has been running
      „time“; — Let others know the time here on this server
      „ping“; — Replies to XMPP pings with pongs
      „pep“; — Enables users to publish their mood, activity, playing music and more
      „register“; — Allow users to register on this server using a client and change passwords
      „lastlog“;
      „list_inactive“;
      „register_web“;
      — Admin interfaces
      „admin_web“;
      „admin_adhoc“;

      — HTTP modules
      „http“;
      „bosh“; — Enable BOSH clients, aka „Jabber over HTTP“
      „http_upload“; — store files locally
      „posix“; — POSIX functionality, sends server to background, enables syslog, etc.
      „welcome“; — Welcome users who register accounts
      „watchregistrations“; — Alert admins of registrations
      „cloud_notify“;
      };
      eigentlich alles standard.
      Extra angemacht habe ich: (warum dahinter)
      „register“; — Habe allow_register wieder auf false gesetzt. zu viele Register über TOR 🙁
      „register_web“; — Das ist was du willst. Über https://DEIN_DNS_DE:5281/register/ eine webbasierte anmeldung mit capcha…
      „admin_web“; — Web Admin Oberfläche (User verwaltern, usw…)
      „bosh“; — für HTTP benötigt
      „http_upload“; — upload von dateien ermöglichen
      „welcome“; — willkommensnachricht an neue angemeldete
      „watchregistrations“; — nachricht an mich über neuen benutzer
      „cloud_notify“; — für IOS (Chatsecure) benötigt, damit iphone Push sendet…

        1. Ah, super chic. Vielen Dank für die Infos. Ich werde das bei mir mal probieren. Was ich allerdings nun für ein Problem gefunden habe, ist, dass ich mit http_upload keine Bilder verschicken kann. Hast du da noch irgendwelche Parameter eingestellt?
          Gruß,
          Jens

  6. Hallo,
    vielen Dank für deine Anleitung! 🙂
    Bei mir scheitert es gerade an der Erstellung der TLS Zertifikates.
    sudo certbot certonly –standalone -d meine-domain.de

    Port 443 ist sowohl im Router, als auch per iptables freigegeben. Jedoch bekomme ich die Meldung, ich solle lighttpd beenden, da Port 80 benötigt würde. Selbst wenn ich nun das Programm stoppe und Port 80 freigebe erhalte ich die Fehlermeldung Connection refused obwohl der Server auf ping reagiert.
    Eine Idee woran es liegen kann?
    Du hast definitiv Port 80 nicht geöffnet und keinen Webserver nebenbei auf dem Pi laufen?

    1. Hallo,
      also ehrlich gesagt, weiß ich nicht mehr genau wie ich das damals gemacht habe. Jetzt habe ich Port 80 offen, wegen httpupload.
      Habe nochmal über Certbot gelesen:
      „The client software needs to make outbound connections to ports 80 and 443.“
      Also für den ersten lauf und ein renew musst du 443 und 80 öffnen. Wenn du ein anderen Webserver am laufen hast, musst du wohl diesen für das Zertifikat kurz ausmachen und den Port auf dein rapi umleiten und danach wieder umstellen….

  7. 80 und 443 müssend eingehend geöffnet sein und auf den webserver zeigen.
    Wichtig: Die Fritzboxen nutzen standardmäßig den 443 für eigene Dinge. Der muss vorher auf einen anderen Port eingestellt werden.
    Webserver (bei mir nginx) stoppen. Zertifikate erneuern und dann den Webserver wieder starten.
    Sollte dann alles funktionieren.
    Grüße

  8. Hallo,

    Ich habe dieses Tutorial ausgeführt und es hat auf meiner Raspberry großartig funktioniert. Jetzt möchte ich mod_http_upload aktivieren. Hat es jemand getan?

    1. Hey,
      bei Prosody 0.11.5 hat bei mir der mod_ http_upload nur funktioniert, wenn man den nur unter modules_enabled aktiviert und nicht unter Component, wie es eigentlich gemacht werden sollte.

      Früher bei den alten Versionen von dem Module hat man das so unter modules_enabled aktiviert und bei den aktuellen laut Prosody Module Seite unter Component. Hatte vor ein paar Monaten einen Server aufgesetzt da hat es auch nur funktioniert, wenn man das Modul unter modules_enabled und Component aktiviert hat.
      Musste mal ausprobieren.

      MfG

  9. Huhu, ich habe vor dieser Tage dein Tutorial anzuwenden, nach einigem Gestöber im Internet, ist das bis jetzt das beste HowTo was ich zu dem Thema gefunden habe. Wirklich detailliert und ausführlich, danke für die Mühe!

    Eine Frage hätte ich. Ist das ganze auch verschlüsselt ?

    LG
    J4it

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert