FreeBSD Jabberd2 Server


Автор Охальников Олег

В данной статье я расскажу о установке сервера Jabber, на примере Jabberd2.
Jabberd2 зарекомендовал себя, как простой и нетребовательный к ресурсам XMPP сервер, поэтому выбор пал на него. Итак приступим, но в начале хочу рассказать о некоторых особенностях построения данного сервера.

Основная особенность - это расширяемость и модульность, вернее сам джабер сервер состоит из нескольких процессов взаимодействующих между собой, причем взаимодействие может происходить как в пределах одной машины, так и по сети, т.е. ни что не мешает разнести составные части Jabberd2 сервера на разные ПК, иногда полезно чтобы снять нагрузку с одной машины. Так же данная архитектура позволяет поддерживать на одной машине несколько "виртуальных хостов".

Начнем с установки сервера.

1) УСТАНОВКА

Установка производится на FreeBSD 7.0 из портов, рекомендую обновить порты перед установкой, о том как это сделать можно прочитать в этой статье...
Поиск порта:

# whereis jabberd
jabberd: /usr/ports/net-im/jabberd

Переходим в нужную директорию и производим установку:

cd /usr/ports/net-im/jabberd

make install clean

Выбираем следующие параметры:

[X] MYSQL
[X] DEBUG
[X] REQUIRES

(Они по умолчанию уже выбраны.)
Будем считать, что установка прошла гладко.
Для автоматического запуска Jabberd не забываем добавить строку в rc.conf

jabberd_enable="YES"

Т.к хранить сведения о пользователях будем в базе данных MySQL (у меня в системе она уже установлена) выполняем установку при ее отсутствии:

# whereis mysql51-server
mysql51-server: /usr/ports/databases/mysql51-server

Переходим в нужную директорию и производим установку:

cd /usr/ports/databases/mysql51-server

Устанавливаем:

make install clean

После установки в системе появится mysql51-server и mysql51-client.
(Для удобного управления базой MySQL рекомендую воспользоваться PhpMyAdmin или Webmin).
Для автоматического запуска MySQL не забываем добавить строку в rc.conf

mysql_enable="YES"


2) НАСТРОЙКА

Настройку начинаем с поиска файла базы пользователей и создания структуры базы из найденного файла.
В разных источниках была найдена информация, что после установки jabberd файл базы должен находится в директории /usr/local/share/jabberd/db-setup.mysql, у меня же после установки данная директория отсутствовала. В любом случае загляните по указанному пути, если не найдете файл базы db-setup.mysql не расстраивайтесь, мы поступим иначе:

cd /usr/ports/net-im/jabberd/work/jabberd-2.2.9/tools/

По этому пути можно найти файл базы, далее устанавливаем ее:

mysql -u root -p
mysql>. db-setup.mysql

GRANT select,insert,delete,update ON jabberd2.* to jabberd2@localhost IDENTIFIED by 'secret';


База с именем jabberd2 создана, приступаем к редактированию конфигурационных файлов Jabberd сервера:

cd /usr/local/etc/jabberd/

Файл router.xml, это диспетчер координирующий работу всех компонентов Jabberd сервера.
Приведу пример своего файла:


<router>
<id>router</id>
<pidfile>/var/jabberd/pid/router.pid</pidfile>
<log type='syslog'>
<ident>jabberd/router</ident>
<facility>local3</facility>
</log>
<local>
<ip>127.0.0.1</ip>
<port>5347</port>
<user>
<name>jabberd</name>
<secret>secret</secret>
</user>
<secret>secret</secret>
</local>
<aliases>
<alias name='conference.ВашДомен.ru' target='conference'/>
</aliases>
<aci>
<acl type='all'>
<user>jabberd</user>
</acl>
</aci>
</router>

Первые 6 строк стандартные, говорят о том где хранить PID файл, где хранить логи. Оставляем все эти данные без изменения.
Следующий блок привязывает процесс к локалхосту и порту 5347, не путайте с работой основного сервера Jabber, эти строки только лишь для связи всех составных частей Jabberd сервера. Как говорилось выше, он состоит из нескольких модулей, так вот в настройках каждого этот блок будет одинаковым, т.е. каждый модуль будет работать на локалхосте и использовать порт 5347. Для авторизации между собой все модули буду содержать jabberd пароль secret все оставляем без изменений.


<local>
<ip>127.0.0.1</ip>
<port>5347</port>
<user>
<name>jabberd</name>
<secret>secret</secret>
</user>
<secret>secret</secret>
</local>

Следующий файл, который нас интересует - это c2s.xml. Ниже приведен пример рабочего файла


<c2s>
<id>c2s</id>
<pidfile>/var/jabberd/pid/c2s.pid</pidfile>
<log type='syslog'>
<ident>jabberd/c2s</ident>
<facility>local3</facility>
</log>
<router>
<ip>127.0.0.1</ip>
<port>5347</port>
<user>jabberd</user>
<pass>secret</pass>
</router>
<local>
<id register-enable='true'>ВашДомен.ru</id> <!-- домен, будет использоваться при регистрации и соединении, например учетка user@ВашДомен.ru-->
<ip>ВашIP</ip> <!-- IP, на него будут соединятся клиенты-->
<port>5222</port> <!-- Порт, на него будут соединятся клиенты-->
</local>
<authreg>
<path>/usr/local/lib/jabberd</path>
<module>mysql</module> <!-- Тип базы данных, ниже секция для коннекта к базе данных -->
<mysql>
<host>localhost</host>
<port>3306</port>
<dbname>jabberd2</dbname> <!-- Имя базы данных MySql -->
<user>root</user> <!-- Пользователь базы данных -->
<pass>пароль</pass> <!-- Пароль пользователя базы данных -->
<password_type>
<plaintext/>
</password_type>
</mysql>

<mechanisms>
<traditional>
<plain></plain>
<digest></digest>
</traditional>
<sasl>
<plain></plain>
<digest-md5></digest-md5>
</sasl>
</mechanisms>

</authreg>
</c2s>


По умолчанию файл содержит множество информации, которая не нужна, например много строчек для работы с различными базами данных, т.к. мы используем MySQL все лишнее удалено. В данном файле содержатся важные данные для соединения с базой данных MySQL (укажите свои логин и пароль, имя базы по умолчанию jabberd2 менять не нужно) также данные об IP адресе Jabber сервера, его порт и имя хоста.

Следующий файл - sm.xml. Session Manager. Сначало данные поступают на модуль c2s, который отдает их на обработку sm.
Так как данных поступает много, для их обработки используются различные правила, модули и т.д., сам файл sm.xml наиболее объемный. Ниже приведу код работающего файла из которого удалено все лишнее.


<chain id='sess-start'>
<module>status</module> <!-- record status information -->
</chain>

<chain id='sess-end'>
<module>status</module> <!-- update status information -->
<module>iq-last</module> <!-- update logout time -->
</chain>

<chain id='in-sess'>
<module>validate</module> <!-- validate packet type -->
<module>status</module> <!-- update status information -->
<module>privacy</module> <!-- manage privacy lists -->
<module>roster</module> <!-- handle roster get/sets and s10ns -->
<module>vacation</module> <!-- manage vacation settings -->
<module>iq-vcard</module> <!-- store and retrieve the user's vcard -->
<module>iq-ping</module> <!-- return the server ping -->
<module>iq-private</module> <!-- manage the user's private data store -->
<module>disco</module> <!-- respond to agents requests from sessions -->
<module>amp</module> <!-- advanced message processing -->
<module>offline</module> <!-- if we're coming online for the first time, deliver queued messages -->
<module>announce</module> <!-- deliver motd -->
<module>presence</module> <!-- process and distribute presence updates -->
<module>deliver</module> <!-- deliver packets with full jids directly -->
</chain>

<chain id='out-sess'/>

<chain id='in-router'>
<module>session</module> <!-- perform session actions as required by c2s -->
<module>validate</module> <!-- validate packet type -->
<module>presence</module> <!-- drop incoming presence if user not online -->
<module>privacy</module> <!-- filter incoming packets based on privacy rules -->
</chain>

<chain id='out-router'>
<module>privacy</module> <!-- filter outgoing packets based on privacy rules -->
</chain>

<chain id='pkt-sm'>
<module>iq-last</module> <!-- return the server uptime -->
<module>iq-ping</module> <!-- return the server ping -->
<module>iq-time</module> <!-- return the current server time -->
<module>iq-version</module> <!-- return the server name and version -->
<module>amp</module> <!-- advanced message processing -->
<module>disco</module> <!-- build the disco list; respond to disco queries -->
<module>announce</module> <!-- send broadcast messages (announce, motd, etc) -->
<module>help</module> <!-- resend sm messages to administrators -->
<module>echo</module> <!-- echo messages sent to /echo -->
<module>status</module> <!-- track status information -->
<module>presence</module> <!-- proces server presence subscriptions -->
</chain>

<chain id='pkt-user'>
<module>roster</module> <!-- handle s10n responses -->
<module>presence</module> <!-- process and distribute incoming presence from external entities -->
<module>iq-vcard</module> <!-- grab user vcards -->
<module>amp</module> <!-- advanced message processing -->
<module>deliver</module> <!-- deliver the packet to an active session if we can -->
<module>vacation</module> <!-- send vacation messages -->
<module>offline</module> <!-- save messages and s10ns for later -->
<module>disco-publish</module> <!-- handle disco publishes; return information about user sessions -->
<module>iq-last</module> <!-- return time since last logout -->
</chain>

<chain id='pkt-router'>
<module>session</module> <!-- take sessions offline if their c2s disappears -->
<module>disco</module> <!-- query new components for service information -->
</chain>

<chain id='user-load'>
<module>active</module> <!-- get active status -->
<module>roster</module> <!-- load the roster and trust list -->
<module>roster-publish</module> <!-- load the published roster -->
<module>privacy</module> <!-- load privacy lists -->
<module>disco-publish</module> <!-- load published information -->
<module>vacation</module> <!-- load vacation settings -->
</chain>

<chain id='user-create'>
<module>active</module> <!-- activate new users -->
<module>template-roster</module> <!-- populate roster from template -->
</chain>

<chain id='user-delete'>
<module>active</module> <!-- deactivate users -->
<module>announce</module> <!-- delete motd data -->
<module>disco-publish</module> <!-- delete published information -->
<module>offline</module> <!-- bounce queued messages -->
<module>privacy</module> <!-- delete privacy lists -->
<module>roster</module> <!-- delete roster -->
<module>vacation</module> <!-- delete vacation settings -->
<module>status</module> <!-- delete status information -->
<module>iq-last</module> <!-- delete last logout time -->
<module>iq-private</module> <!-- delete private data -->
<module>iq-vcard</module> <!-- delete vcard -->
</chain>

<chain id='disco-extend'>
<module>iq-version</module> <!-- add XEP-xxxx Software Information -->
<module>help</module> <!-- add XEP-0157 Contact Addresses -->
</chain>

</modules>

<discovery>

<identity>
<category>server</category> <!-- default: server -->
<type>im</type> <!-- default: im -->
<name>Jabber server</name> <!-- default: Jabber IM server -->
</identity>
<agents/>
<items>
</items>

</discovery>

<user>

<auto-create/>


<template>
<!--
<publish>
-->

<!--
<check-remove-domain>jabber.example.com</check-remove-domain>
-->
<!-- Keep cache of "active" database specified number of seconds.
This will significantly speed up publishing of roster.
If unspecified or 0, no cache is used. -->
<active-cache-ttl>60</active-cache-ttl>
<!-- If <fix-subscriptions/> is not commented, set subscriptions of
user's contacts to subscriptions of corresponding published
contacts. As for now, "both". -->
<!--
<fix-subscriptions/>
-->
<!-- If <override-names/> is not commented, then displayed names of
contacts in user's roster will be updated accordingly to
published roster (if they differ). If commented, then user can
rename contacs in roster -->
<!--
<override-names/>
-->
<!--
<mapped-groups/>
<map-groups/>
<group-cache-ttl>120</group-cache-ttl>
</mapped-groups>
-->
<!--
</publish>
-->

<!-- If you defined publish, you should comment <roster> -->
<!--
<roster>/usr/local/etc/jabberd/templates/roster.xml</roster>
-->
</template>
</user>

<!-- Advanced Message Processing module configuration -->
<amp>
<!-- You can disable some actions -->
<!--
<disableactions>
<drop/>
<error/>
<alert/>
<notify/>
</disableactions>
-->

<!-- You can disable some conditions -->
<!--
<disableconditions>
<expireat/>
<matchresource/>
<deliver/>
</disableconditions>
-->

<!-- You need to enable this if your server has offline storage disabled -->
<!--
<offlinestoragedisabled/>
-->
</amp>

<!-- Offline module configuration -->
<offline>
<!-- Do not store messages in offline store -->
<!--
<dropmessages/>
-->

<!-- Store headline messages in offline store -->
<!--
<storeheadlines/>
-->

<!-- Do not store subscription requests in offline store -->
<!--
<dropsubscriptions/>
-->

<!-- Offline storage message quota.
Specifies how many messages will be stored in user offline store -->
<!--
<userquota>500</userquota>
-->
</offline>

<!-- roster module configuration -->
<roster>
<!-- maximum items per user roster -->
<!--
<maxitems>100</maxitems>
-->
</roster>

<!-- status module configuration -->
<status>
<!-- presence service resource
disabled when commented out -->
<!--
<resource>webstatus</resource>
-->
</status>

</sm>


3) ТЕСТИРОВАНИЕ

Для проверки работы воспользуемся командой:


# jabberd -D


Когда в каком то из модулей есть ошибка, это будет видно в выводе. Кроме того смотрим лог messages.

Если при запуске команды ни какие ошибки не обнаружены, стартуем сервер:


# cd /usr/local/etc/rc.d/

./jabberd start


Проверяем работу сервера:


# ps -ax |grep jabber
78597 ?? Ss 4:38.13 /usr/local/bin/perl /usr/local/bin/jabberd -b
78593 p0- S 0:01.04 /usr/local/bin/router -c /usr/local/etc/jabberd/router.xml
78594 p0- S 0:01.16 /usr/local/bin/sm -c /usr/local/etc/jabberd/sm.xml
78595 p0- S 0:00.44 /usr/local/bin/s2s -c /usr/local/etc/jabberd/s2s.xml
78596 p0- S 0:00.60 /usr/local/bin/c2s -c /usr/local/etc/jabberd/c2s.xml
78331 p1- R 849:46.39 /usr/local/bin/router -c /usr/local/etc/jabberd/router.xml -D


Сервер запущен и работает, более того с удаленной машины к нему можно подключится по telnet:

telnet ВашСервер 5222

При удаче видим как проходит соединение на удаленную машину к службе Jabberd.

Запускаемм jabber клиент и производим регистрацию на сервере.

Про гейты, конференции и прочее добро не в рамках данной статьи, т.к. задача была поднять обычных jabber сервер для небольшой конторы.

http://unixa.ru

Обновлено: 12.03.2015