Jabber
Inhaltsverzeichnis
XMPP-Server mit ejabberd
XMPP-Server gibt es an der Zahl viele. Ein populärer, freier XMPP-Server ist ejabberd. Ejabberd ist unter Windows und Unix-Derivaten verfügbar. Neben diversen Modulen und Transports unterstützt ejabberd die Einrichtung von Clustern, so dass durch den Parallelbetrieb mehrerer Server eine hohe Ausfallsicherheit erzeugt werden kann.
Installation und Konfiguration
Im Folgenden wird die Installation und Einrichtung unter Debian Wheezy als Benutzer root beschrieben. Als erstes installieren wir das Paket mit dem Server und ImageMagick, welches für die Erstellung der Captchas benötigt wird:
apt-get install ejabberd imagemagick
Im Anchluss führen wir eine Grundkonfiguration durch:
dpkg-reconfigure ejabberd
Im Zuge der Grundkonfiguration geben wir die Domain <domain> des Servers, sowie einen Namen für den Administrator <administrator> sowie ein Passwort ein. Debconf nimmt im Anschluss automatisch die notwendigen Änderungen in der zentralen Konfigurationsdatei /etc/ejabberd/ejabberd.cfg vor. Dort sollten wir nach Abschluss der Grundkonfiguration den folgenden Abschnitt finden:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Options which are set by Debconf and managed by ucf %% Admin user {acl, admin, {user, "<administrator>", "<domain>"}}. %% Hostname {hosts, ["<domain>"]}.
Da dies noch nicht ausreichend ist, öffnen wir die Konfigurationsdatei /etc/ejabberd/ejabberd.cfg im Anschluss mit dem Editor unserer Wahl und bessern an einigen Stellen nach. Damit wir als Administrator informiert werden, wenn der ejabberd-Prozess außer Kontrolle gerät, aktivieren wir den Watchdog:
%% %% watchdog_admins: If an ejabberd process consumes too much memory, %% send live notifications to those Jabber accounts. %% {watchdog_admins, ["<admin>@<domain>"]}.
Weiterhin wollen wir ejabberd über die eingebaute Web-Oberfläche konfigurieren können und Nutzern die Möglichkeit zur Web-basierten Registrierung bieten. Hierfür aktiviern wir den eingebauten Web-Server mit den entsprechenden Modulen. Durch Hinzufügen der Zeile tls, {certfile, "/etc/ejabberd/ejabberd.pem"} erzwingen wir die Verwendung von TLS:
{5280, ejabberd_http, [ tls, {certfile, "/etc/ejabberd/ejabberd.pem"}, {request_handlers, [ {["pub", "archive"], mod_http_fileserver} ]}, captcha, http_bind, http_poll, web_admin, register ]}
Benutzern soll es prinzipiell erlaubt sein, sich selbst mittels ihrer Klienten zu registrieren:
%% No username can be registered via in-band registration: %% To enable in-band registration, replace 'deny' with 'allow' % (note that if you remove mod_register from modules list then users will not % be able to change their password as well as register). % This setting is default because it's more safe. {access, register, [{allow, all}]}.
Statt Englisch möchten wir Deutsch als Standardsprache für alle Meldungen:
%% %% language: Default language used for server messages. %% {language, "de"}.
Um die Registrierung von Benutzern vor Bots zu schützen, aktivieren wir die Erstellung von Captchas:
{captcha_cmd, "/usr/lib/ejabberd/priv/bin/captcha.sh"}.
Um sicherzustellen, dass die Erstellung der Captchas auch funktioniert, empfiehlt sich ein Test der Befehlszeile /usr/lib/ejabberd/priv/bin/captcha.sh in der Konsole als Benutzer ejabberd. Weiterhin passen wir den URL für das Captcha an, welcher an die Klienten übermittelt wird:
{captcha_host, "https://<domain>:5280"}.
Zuletzt stellen wir noch sicher, dass das Modul mod_register für die Benutzerregistrierung aktiviert ist und tragen unter registration_watchers unseren Administrator ein. In Zukunft sollten wir informiert werden, nachdem sich ein Benutzer registriert hat. Durch hinzufügen der letzten Zeile aktivieren wir zusätzlich noch das Modul mode_register_web, welches für für die Web-basierte Registrierung benötigt wird.
{mod_register, [ %% %% After successful registration, the user receives %% a message with this subject and body. %% {welcome_message, {"Welcome!", "Welcome to a Jabber service powered by Debian. " "For information about Jabber visit " "http://www.jabber.org"}}, %% Replace it with 'none' if you don't want to send such message: %%{welcome_message, none}, %% %% When a user registers, send a notification to %% these Jabber accounts. %% {registration_watchers, ["<admin>@<domain>"]}, {mod_register_web, []},
Im Anschluss starten wir ejabberd erneut, damit die Änderungen übernommen werden:
service ejabberd restart
Im Normalfall sollte unser Rechner durch eine Firewall geschützt sein. Damit ejabberd funktionieren kann, müssen die Ports 5222, 5269 und 5280 für eingehende Verbindungen geöffnet werden. Falls die Uncomplicated Firewall verwendet wird, gelingt dies mit:
ufw allow 5222 # client connections ufw allow 5269 # server connections ufw allow 5280 # web configuration interface
Ab sofort sollten sich Klienten registrieren und mit dem Server verbinden können. Die Administrationsoberfläche erreichen wir unter https://<domain>:5280/admin/. Für den Login verwenden wir den zuvor angelegten Administrator sowie das zugehörige Passwort. Benutzer können sich ab sofort unter der Adresse https://<domain>:5280/register/ selbst registrieren.
Clustering
Um die Ausfallsicherheit des XMPP-Dienstes zu erhöhen bzw. um den Dienst zu skalieren, lassen sich mehrere Knoten zu einem Cluster zusammenschalten. Voraussetzung hierfür ist die Grundkonfiguration wie im vorherigen Abschnitt beschrieben. Im Folgenden Beispiel wird von zwei Knoten <host1> und <host2> ausgegangen. Wichtig: <host1> und <host2> beschreiben hierbei die Host-Namen ohne Domain-Erweiterung! Damit Erlang in der Lage ist, die Host-Namen auch ohne DNS-Server aufzulösen, ergänzen wir die Datei /etc/hosts auf beiden Knoten um die folgenden Einträge:
<ipv4-host1> <host1> <host1>.<domain1> <ipv4-host2> <host2> <host2>.<domain2>
Zusätzlich müssen wir die Firewall öffnen, damit sich die Erlang-Knoten miteinander verbinden können. Zunächst beschränken wir den genutzten Portbereich, indem wir in der Datei /etc/default/ejabberd die folgende Zeile einfügen:
FIREWALL_WINDOW=9001-9005
Im Anschluss öffnen wir den Port 4369 für den Erlang-DNS-Server empd und den zuvor festgelegten Portbereich von 9001 - 9005. Wie im vorherigen Abschnitt wird von der Verwendung der Uncomplicated Firewall ausgegangen:
ufw allow 4369 ufw allow 9001:9005
Eine weitere Voraussetzung für den Austausch der Knoten ist die Verwendung des selben Erlang-Cookies. Dieser ist in der Datei /var/lib/ejabberd/.erlang.cookie hinterlegt. Nachdem wir den Cookie <cookie> des ersten Knotens <host1> in Erfahrung gebracht haben, übertragen wir diesen auf den zweiten Knoten <host2>:
echo -n "<cookie>" > /var/lib/ejabberd/.erlang.cookie
Falls ejabberd bereits läuft, fahren wir den Dämonen herunter:
service ejabberd stop
Danach nehmen wir die Identität des Benutzers ejabberd an:
su ejabberd
Jetzt starten wir von Hand eine Erlang-Konsole unter Eingabe der folgenden Befehlszeile:
erl -sname ejabberd -mnesia dir '"/var/lib/ejabberd/"' -mnesia extra_db_nodes "['ejabberd@<host1>']" -mnesia
Sollte es zu einer längeren Fehlermeldungen mit vielen Klammern kommen (sehr vielen Klammern!), so liegt dies vermutlich daran, dass der ejabberd nicht korrekt heruntergefahren wurde. In diesem Fall muss der Prozess manuell mittels kill beendet werden. Nachdem die Konsole erfolgreich geöffnet wurde, lässt sich der Status der Mnesia-Datenbank abfragen:
mnesia:info().
Hinweis: Erlang-Befehle werde immer mit einem Punkt abgeschlossen. Dieser ist nicht optional! In der Folge sollte sich ein Schwall von Informationen über den Schirm ergießen. Wenn alles in Ordnung ist und die Verbindung mit <host1> zustande kanm, dann sollte sich die folgende Zeile darunter befinden:
runnning db nodes = [ ejabberd@<host1>, ejabberd@<host2> ]
Sollte die Verbindung nicht zustande gekommen sein, empfiehlt es sich manuell ein paar Tests durchzuführen. Auf der Seite Interconnecting Erlang Nodes findet man Anweisungen, um manuell eine Verbindung zwischen zwei Erlang-Knoten herzustellen. Zuvor muss ejabberd allerdings auf beiden Knoten gestoppt werden. War alles erfolgreich, dann geht es weiter mit der Kopplung der Datenbanken. Diese erreichen wir mit der folgenden Befehlszeile:
mnesia:change_table_copy_type(schema,node(),disc_copies).
Tipp: In seltenen Fällen kann es zur folgenden Fehlermeldung kommen: "** FATAL ** Failed to merge schema: Bad cookie in table definition". Dies ist ein Hinweis darauf, dass die Mnesia-Datenbank korrumpiert wurde. Um das Problem zu beheben, müssen wir die Datenbank zurückzusetzen. |
Im Anschluss überprüfen wir erneut den Status der Mnesia-Datenbank. Das Ergebnis sollte in etwa wie folgt aussehen:
---> Processes holding locks <--- ---> Processes waiting for locks <--- ---> Participant transactions <--- ---> Coordinator transactions <--- ---> Uncertain transactions <--- ---> Active tables <--- schema : with 36 records occupying 4696 words of mem ===> System info in version "4.7", debug level = none <=== opt_disc. Directory "/var/lib/ejabberd" is used. use fallback at restart = false running db nodes = ['ejabberd@box-1719',ejabberd@altegurke] stopped db nodes = [] master node tables = [] remote = [acl,bytestream,caps_features,captcha,config,iq_response, irc_custom,last_activity,local_config,mod_register_ip, motd,motd_users,muc_online_room,muc_registered,muc_room, offline_msg,passwd,privacy,private_storage,pubsub_index, pubsub_item,pubsub_last_item,pubsub_node,pubsub_state, pubsub_subscription,reg_users_counter,roster, roster_version,route,s2s,session,session_counter, temporarily_blocked,vcard,vcard_search] ram_copies = [] disc_copies = [schema] disc_only_copies = [] [] = [local_config,caps_features,mod_register_ip] [{ejabberd@altegurke,disc_copies},{'ejabberd@box-1719',disc_copies}] = [schema] [{'ejabberd@box-1719',disc_copies}] = [config,pubsub_subscription,privacy, passwd,irc_custom,roster,last_activity, roster_version,motd,acl,pubsub_index, vcard_search,motd_users,muc_room, pubsub_state,muc_registered, pubsub_node] [{'ejabberd@box-1719',disc_only_copies}] = [offline_msg,vcard,private_storage, pubsub_item] [{'ejabberd@box-1719',ram_copies}] = [reg_users_counter,bytestream, pubsub_last_item,route,s2s,captcha, session_counter,session,iq_response, temporarily_blocked,muc_online_room] 4 transactions committed, 0 aborted, 0 restarted, 3 logged to disc 0 held locks, 0 in queue; 0 local transactions, 0 remote 0 transactions waits for other nodes: []
Sofern sich Erlang nicht beschwert, wurden die Datenbanken erfolgreich gekopplet und die Knoten befinden sich nach dem Neustart von ejabberd im selben Cluster. Wir verlassen die Erlang-Konsole:
q().
Und schlüpfen zurück in die Rolle des Benutzers root:
exit
Bevor wir ejabberd erneut starten nehmen wir noch eine kleine Änderung in der Konfiguration vor. Da die beiden Knoten normalerweise neben der lokalen Domain <local_domain> einen gemeinsame Domain <joint_domain> bedienen sollten, ergänzen wir diese in /etc/ejabberd/ejabberd.cfg:
%% Hostname {hosts, ["<local_domain>", "<joint_domain>"]}.
Diese Änderung muss auf beiden Knoten vorgenommen werden! Zuletzt starten wir ejabberd erneut:
service ejabberd start
Ob wir erfolgreich waren, können wir bequem über die Web-Oberfläche von ejabberd abfragen. Hierzu öffnen wir den Link http://<domain>:5280/admin/ und authentifizieren uns als Administrator. Unter dem Menü-Punkt Nodes sollten ab sofort zwei Knoten ähnlich dem folgenden Bildschirmfoto dargestellt werden:
Um den Cluster als solchen zu nutzen fehlt nur noch ein Round-Robin DNS-Eintrag für die gemeinsame Domain <joint_domain>, welcher auf die beide Knoten verweist mittels ihrer IP-Adressen verweist.
Datenbank zurücksetzen
In seltenen Fällen kann es zu einer Korrumpierung der Mnesia-Datenbank kommen. Um die Datenbank zurückzusetzen stoppen wir als erstes den ejabberd:
service ejabberd stop
Danach öffnen wir als Benutzer ejabberd eine Erlang-Konsole mit der folgenden Befehlszeile:
erl -sname ejabberd -mnesia dir '"/var/lib/ejabberd"'
Die Datenbank setzen wir mit dem folgenden Befehl zurück:
mnesia:delete_schema(['<host2>'])
Im Anschluss müssen wir die Datenbanken wie unter Clustering beschrieben erneut synchronisieren.