Skip to main content

Настройка ejabberd, транспорта ICQ pyICQ-t и скрипт авторизации MySQL

В этой статье я расскажу вам о том, как настроить свой Jabber сервер.

Чтобы дело выглядело не таким простым, как

root@poligon:~# apt-get install ejabberd

мы сделаем так, чтобы пользователи jabber брались из той же базы, что и пользователи почтового сервера, в статьях, рассмотренных нами ранее. Также мы настроим джаббер-транспорт в сеть ICQ (не забывать же старых друзей, переход надо начать плавно). Дополнительно мы скомпилируем модуль на эрланге для записи истории.

Напомню, все дело происходит на виртуальном сервере на Ubuntu под чутким руководством OpenVZ

root@poligon:~# lsb_release -d -r -c   
Description:	Ubuntu 10.04 LTS
Release:	10.04
Codename:	lucid
root@poligon:~# uname -a
Linux poligon 2.6.18-194.8.1.el5.028stab070.2 #1 SMP Tue Jul 6 15:26:41 MSD 2010 i686 GNU/Linux

И так, приступим.

root@poligon:~# apt-get install ejabberd pyicqt
The following NEW packages will be installed:
  ejabberd erlang-asn1 erlang-base erlang-corba erlang-crypto
  erlang-docbuilder erlang-edoc erlang-eunit erlang-ic erlang-inets
  erlang-inviso erlang-mnesia erlang-nox erlang-odbc erlang-os-mon
  erlang-parsetools erlang-percept erlang-public-key erlang-runtime-tools
  erlang-snmp erlang-ssh erlang-ssl erlang-syntax-tools erlang-tools
  erlang-webtool erlang-xmerl liblcms1 libsctp1 lksctp-tools pyicqt
  python-crypto python-imaging python-mysqldb python-nevow python-openssl
  python-pam python-pkg-resources python-pyasn1 python-serial python-support
  python-twisted python-twisted-bin python-twisted-conch python-twisted-core
  python-twisted-lore python-twisted-mail python-twisted-names
  python-twisted-news python-twisted-runner python-twisted-web
  python-twisted-words python-zope.interface
0 upgraded, 52 newly installed, 0 to remove and 98 not upgraded.
Need to get 14.6MB of archives.
After this operation, 45.7MB of additional disk space will be used.


Сразу скажу, что, если у вас еще нет сертификата для сервера, то сгенерируйте его, например, с помощью этой инструкции.

Все настройки производятся правкой конфигурационных файлов. Они уже богато прокомментированы, правда на английском языке. Поэтому сохраните их, чтобы почитать потом, и настроить сервер под себя. Ниже я приведу файл конфигурации на каждом этапе и прокомментирую важные места.

root@poligon:~# cat /etc/ejabberd/ejabberd.cfg 
%%%  - The character to comment a line is %
%%%  - Each term ends in a dot, for example:
%%%      override_global.
%%%  - A tuple has a fixed definition, its elements are
%%%    enclosed in {}, and separated with commas:
%%%      {loglevel, 4}.
%%%  - A list can have as many elements as you want,
%%%    and is enclosed in [], for example:
%%%      [http_poll, web_admin, tls]
%%%  - A keyword of ejabberd is a word in lowercase.
%%%    The strings are enclosed in "" and can have spaces, dots...
%%%      {language, "en"}.
%%%      {ldap_rootdn, "dc=example,dc=com"}.
%%%  - This term includes a tuple, a keyword, a list and two strings:
%%%      {hosts, ["jabber.example.net", "im.example.com"]}.
 
%% пользователь - администратор
{acl, admin, {user, "admin", "poligon.scaytrase.ru"}}.
 
%% Hostname
{hosts, ["poligon.scaytrase.ru"]}.
 
%%%   =========
%%%   Отладка
 
%%
%% loglevel: уровень подробности логов программы.
%% 0: без логов
%% 1: только критические
%% 2: ошибки
%% 3: предупреждения
%% 4: информация
%% 5: дополнительная отладочная информация
%%
{loglevel, 4}.
 
%%
%% watchdog_admins: Если сервер джаббера, например, потребляет слишком много памяти,
%% отслылает уведомления следующим пользователям.
%%
%%{watchdog_admins, ["bob@example.com"]}.
 
%%%   ===============
%%%   LISTENING PORTS
 
%%
%% listen: какие порты слушает сервер, каким сервисом обрабатывает
%% и с какими опциями запускается.
%%
{listen,
 [
  {5222, ejabberd_c2s, [ % Настройки соединения с клиентами
			{access, c2s}, % доступ для c2s acl группы
			{shaper, c2s_shaper}, % ограничение траффика фильтром c2s_shaper
			{max_stanza_size, 65536}, % максимальный размер строфы джаббера
                        zlib, % Сжатие траффика Отключите, если клиенты не поддерживают сжатие траффика
			starttls, {certfile, "/etc/ejabberd/ejabberd.pem"} % сертификат для шифрованного подключения
		       ]},
 
  {5269, ejabberd_s2s_in, [ % Настройки соединения с другими серверами
			   {shaper, s2s_shaper}, % ограничение траффика фильтром s2s_shaper
			   {max_stanza_size, 131072} % максимальный размер строфы
			  ]},
 
  %% Далее идут шаблоны настроек для разных транспортов. Я их оставлю, вдруг пригодятся, прокомментирую только нужный нам транспорт ICQ
 
  %% External MUC jabber-muc
  %%{5554, ejabberd_service, [
  %%			    {ip, {127, 0, 0, 1}},
  %%			    {access, all},
  %%			    {shaper_rule, fast},
  %%			    {host, "muc.localhost", [{password, "secret"}]}
  %%			    ]},
 
  %% Jabber ICQ Transport
  {5347, ejabberd_service, [ % Настройки подключения стороннего сервиса, в данном случае транспорта ICQ
  			    {ip, {127, 0, 0, 1}}, % IP Для подключения, в нашем случае транспорт запущен на этом же сервере
  			    {access, all}, % Доступ для всех пользователей
  			    {shaper_rule, fast}, % Ограничение траффика фильтром fast
  			    {hosts, ["icq.poligon.scaytrase.ru"],  % Имя транспорта
  				       [{password, "verysecretpassword"}]} % Пароль для подключения - смотрите конфигурационный файл транспорта
  			    ]},
 
  %% AIM Transport
  %%{5556, ejabberd_service, [
  %%			    {ip, {127, 0, 0, 1}},
  %%			    {access, all},
  %%			    {shaper_rule, fast},
  %%			    {host, "aim.localhost", [{password, "secret"}]}
  %%			    ]},
 
  %% MSN Transport
  %%{5557, ejabberd_service, [
  %%			    {ip, {127, 0, 0, 1}},
  %%			    {access, all},
  %%			    {shaper_rule, fast},
  %%			    {host, "msn.localhost", [{password, "secret"}]}
  %%			    ]},
 
  %% Yahoo! Transport
  %%{5558, ejabberd_service, [
  %%			    {ip, {127, 0, 0, 1}},
  %%			    {access, all},
  %%			    {shaper_rule, fast},
  %%			    {host, "yahoo.localhost", [{password, "secret"}]}
  %%			    ]},
 
  %% External JUD (internal is more powerful,
  %% but doesn't allow to register users from other servers)
  %%{5559, ejabberd_service, [
  %%			    {ip, {127, 0, 0, 1}},
  %%			    {access, all},
  %%			    {shaper_rule, fast},
  %%			    {host, "jud.localhost", [{password, "secret"}]}
  %%			    ]},
 
  {5280, ejabberd_http, [ % HTTP сервер для передачи файлов
			 %%{request_handlers,
			 %% [
			 %%  {["pub", "archive"], mod_http_fileserver}
			 %% ]},
			 %%captcha,
			 http_bind,
			 http_poll,
			 web_admin
			]}
 
 ]}.
 
%% s2s_use_starttls: включает STARTTLS + Dialback для S2S соединений.
%% Разрешенные значения: true или false.
%% Нужно указать файл сертификата ниже.
 
{s2s_use_starttls, true}.
 
%% s2s_certfile: файл сертификата.
 
{s2s_certfile, "/etc/ejabberd/ejabberd.pem"}.
 
%% domain_certfile: Можно указать отдельный сертификат для каждого обслуживаемого домена.
 
%%{domain_certfile, "example.org", "/path/to/example_org.pem"}.
%%{domain_certfile, "example.com", "/path/to/example_com.pem"}.
 
%% S2S белый и черный список
%% Политика s2s для новых серверов.
 
{s2s_default_policy, allow}.
 
%% Разрешение или запрет обмена данными с конкретными серверами:
 
%%{{s2s_host, "goodhost.org"}, allow}.
%%{{s2s_host, "badhost.org"}, deny}.
 
 
%%%   ==============
%%%   Аутентификация
 
%% Аутентификация через внешний скрипт. В нашем случае скрипт берет данные для аутентификации из MySQL базы
%% Убедитесь, что скрипт доступен для запуска eJabberd.
 
{auth_method, external}.
{extauth_program, "/etc/ejabberd/auth.pl"}.
 
%%%   ===============
%%%   Фильтры траффика ( шейперы )
 
%% Фильтр "normal" ограничивает траффик до 1 000 Б/с
{shaper, normal, {maxrate, 1000}}.
 
%% Фильтр "fast" ограничивает траффик до 50 000 Б/с
{shaper, fast, {maxrate, 50000}}.
 
 
%%%   ====================
%%%   Списки контроля доступа
 
%%
%% Админские учетные записи. Можно управлять сервером прямо из клиента, если он это поддерживает
%% Можно сделать сколько угодно записей.
%%
%%{acl, admin, {user, "aleksey", "localhost"}}.
%%{acl, admin, {user, "ermine", "example.org"}}.
 
%%
%% Заблокированные пользователи
%%
%%{acl, blocked, {user, "baduser", "example.org"}}.
%%{acl, blocked, {user, "test"}}.
 
%%
%% Локальные пользователи: не модифицируйте эту строчку
%%
{acl, local, {user_regexp, ""}}.
 
%%
%% Еще примеры
%%
%%{acl, jabberorg, {server, "jabber.org"}}.
%%{acl, aleksey, {user, "aleksey", "jabber.ru"}}.
%%{acl, test, {user_regexp, "^test"}}.
%%{acl, test, {user_glob, "test*"}}.
 
 
%%%   ============
%%%   Правила доступа
 
%% Количество одновременных подключений одного пользователя:
{access, max_user_sessions, [{10, all}]}.
 
%% Количество оффлайн сообщений пользователя:
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}. 
 
%% Разрешить доступ локальным пользователям:
{access, local, [{allow, local}]}.
 
%% Запретить доступ блокированным пользователям:
{access, c2s, [{deny, blocked},
	       {allow, all}]}.
 
%% Для всех - фильтр скорости "normal" и без ограничений для админа
{access, c2s_shaper, [{none, admin},
		      {normal, all}]}.
 
%% для всех S2S соединений использовать фильтр "fast"
{access, s2s_shaper, [{fast, all}]}.
 
%% Только админы могут рассылать уведомления:
{access, announce, [{allow, admin}]}.
 
%% Только админы могут использовать веб-интерфейс для конфигурации:
{access, configure, [{allow, admin}]}.
 
%% Админы сервера также являются админами сервиса многопользовательских чатов:
{access, muc_admin, [{allow, admin}]}.
 
%% Всем разрешено использовать чаты:
{access, muc, [{allow, all}]}.
 
%% Регистрация. Так как мы используем внешнюю базу пользователей, то мы отключим регистрацию
{access, register, [{deny, all}]}.
 
%% Everybody can create pubsub nodes
{access, pubsub_createnode, [{allow, all}]}.
 
%%
%% language: Язык по умолчанию
%%
{language, "ru"}.
 
%%%   =======
%%%   Модули
 
{modules,
 [
  {mod_adhoc,    []},
  {mod_announce, [{access, announce}]}, % требует mod_adhoc
  {mod_caps,     []},
  {mod_configure,[]}, % требует mod_adhoc
  {mod_admin_extra, []},
  {mod_disco,    []},
  %%{mod_echo,   [{host, "echo.localhost"}]},
  {mod_irc,      []},
  %% NOTE that mod_http_fileserver must also be enabled in the
  %% "request_handlers" clause of the "ejabberd_http" listener
  %% configuration (see the "LISTENING PORTS" section above).
  %%{mod_http_fileserver, [
  %%                       {docroot, "/var/www"}, 
  %%                       {accesslog, "/var/log/ejabberd/access.log"}
  %%                      ]},
  {mod_last,     []},
  {mod_muc,      [
		  {host, "conference.@HOST@"},
		  {access, muc},
		  {access_create, muc},
		  {access_persistent, muc},
		  {access_admin, muc_admin},
		  {max_users, 500}
		 ]},
  {mod_muc_log,[]},
  {mod_offline,  [{access_max_user_messages, max_user_offline_messages}]},
  {mod_privacy,  []},
  {mod_private,  []},
  {mod_proxy65,  [
		  {access, local},
		  {shaper, c2s_shaper}
		 ]},
  {mod_pubsub,   [ % requires mod_caps
		  {access_createnode, pubsub_createnode},
		  {pep_sendlast_offline, false},
		  {last_item_cache, false},
		  %%{plugins, ["default", "pep"]}
		  {plugins, ["flat", "hometree", "pep"]}  % pep requires mod_caps
		 ]},
  {mod_roster,   []},
  {mod_service_log,[]},
  {mod_shared_roster,[]},
  {mod_stats,    []},
  {mod_time,     []},
  {mod_vcard,    []},
  {mod_version,  []}
 ]}.
root@poligon:~# cat /etc/pyicqt.conf.xml 
<pyicqt>
	<!-- The JabberID of the transport. -->
	<jid>icq.poligon.scaytrase.ru</jid>
 
	<!-- The component JID of the transport. Unless you're doing clustering, leave this alone -->
	<!-- <compjid>icq1</compjid> -->
 
	<!-- The IP address of the main Jabberd server -->
	<mainServer>127.0.0.1</mainServer>
 
	<!-- The JID of the main Jabber server -->
	<mainServerJID>poligon.scaytrase.ru</mainServerJID>
 
	<!-- The website of the Jabber service -->
	<website>http://poligon.scaytrase.ru/someJabberPage/HowToJabber</website>
 
	<!-- The website of the transport service -->
	<transportWebsite>http://poligon.scaytrase.ru/someJabberPage/HowToICQ</transportWebsite> -->
 
	<!-- The support room on your server -->
	<!-- <supportRoom></supportRoom> -->
 
	<!-- The JID of a service admin or helpdesk -->
	<supportJid>admin@poligon.scaytrase.ru</supportJid>
 
	<!-- The TCP port to connect to the Jabber server on -->
	<!-- (this is the default for Jabberd2) -->
	<port>5347</port>
 
	<!-- The TCP port that the web admin interface will answer on -->
	<!-- (uncomment to enable) -->
	<webport>8022</webport>
 
	<!-- The authentication token to use when connecting to the Jabber server -->
	<secret>verysecretpassword</secret>
 
	<!-- The default language to use (for error/status messages) -->
	<lang>ru</lang>
 
	<!-- Default one-byte message encoding to use -->
	<encoding>cp1251</encoding>
 
	<!-- The hostname of the ICQ server you wish to connect to -->
	<icqServer>login.icq.com</icqServer>
 
	<!-- The port of the ICQ server you wish to connect to -->
	<icqPort>5190</icqPort>
 
	<!-- Enable it if you want md5 authentication -->
	<usemd5auth/>
 
	<!-- The name of Socks Proxy if connecting thru a proxy -->
	<!-- <socksProxyServer>im-proxy2</socksProxyServer> -->
 
	<!-- The Socks Proxy port to use when connecting thru a proxy -->
	<!-- <socksProxyPort>1080</socksProxyPort> -->
 
	<!-- Send greeting on login (enter text to be sent to users here) -->
	<!-- <sessionGreeting>enter message here</sessionGreeting> -->
 
	<!-- Send message to user on transport stop/restart -->
	<enableShutdownMessage/>
 
	<!-- Custom shutdown message -->
	<!-- <customShutdownMessage></customShutdownMessage> -->
 
	<!-- Send message on successful registration -->
	<!-- <registerMessage>You have successfully registered with PyICQt</registerMessage> -->
 
	<!-- Allow users of ICQ gateway to chat with AIM users -->
	<!-- (uncomment to enable) -->
	<!-- <crossChat/> -->
 
	<!-- Disable registration with the transport -->
	<!-- (uncomment to disable) -->
	<!-- <disableRegister/> -->
 
	<!-- Enable automatic invitation to reconnect on restart -->
	<!-- (uncomment to enable) -->
	<!-- <enableAutoInvite/> -->
 
	<!-- Disable xhtml support (messages with fonts and colors) -->
	<!-- (uncomment to disable) -->
	<!-- <disableXHTML/> -->
 
	<!-- Disable mail notifications -->
	<!-- (uncomment to disable) -->
	<!-- <disableMailNotifications/> -->
 
	<!-- Disable use of default avatar if none is specified -->
	<!-- (uncomment to disable) -->
	<!-- <disableDefaultAvatar/> -->
 
	<!-- Disable use of iq-based avatars (JEP-0008) -->
	<!-- (uncomment to disable) -->
	<!-- <disableIQAvatars/> -->
 
	<!-- Disable use of vcard-based avatars (JEP-0153) -->
	<!-- (uncomment to disable) -->
	<!-- <disableVCardAvatars/> -->
 
	<!-- Disable use of PEP-based avatars (JEP-0084) -->
	<!-- (uncomment to disable) -->
	<!-- NOT IMPLEMENTED YET -->
	<!-- <disablePEPAvatars/> -->
 
	<!-- Support for x-statuses -->
	<xstatusessupport/>
 
	<!-- Try detect Unicode:
	    0 - never
	    1 - in offline messages
	    2 - and in nicknames
	    Attention: this solution can be slowly on high-load servers
	-->
	<detectunicode>2</detectunicode>
 
	<!-- You can choose which users you wish to have as administrators. These users can perform some tasks with Ad-Hoc commands that others cannot -->
	<admins>
	<jid>admin@poligon.scaytrase.ru</jid>
	</admins>
 
	<!-- You can select which event loop PyICQt will use. It's probably safe to leave this as the default -->
 
	<!-- Use epoll for high-load Linux servers running kernel 2.6 or above -->
	<reactor>epoll</reactor>
 
	<!-- Use kqueue for high-load FreeBSD servers -->
	<!--<reactor>kqueue</reactor>-->
 
	<!-- Use poll for high-load Unix servers -->
	<!--<reactor>poll</reactor>-->
 
	<!-- You can select which spool storage method you wish to use -->
	<!-- Available methods are: -->
	<!-- xmlfiles: single xml files in the spool directory in hashed dirs (default)-->
	<!-- legacyaimtransport: compatible with c-based aim transport, less functionality -->
	<!-- legacyjittransport: compatible with JIT transport, less functionality -->
	<!-- mysql: registration information stored in a MySQL database -->
	<!--<xdbDriver>xmlfiles</xdbDriver>-->
 
	<!-- For MySQL -->
	<!--<xdbDriver>mysql</xdbDriver>-->
	<!--<xdbDriver_mysql>-->
	<!--<username>pyicqt</username>-->
	<!--<password>pyicqt</password>-->
	<!--<database>pyicqt</database>-->
	<!--<server>localhost</server>-->
	<!--<format>encrypted</format>--> <!-- Enable encryption of passwords -->
	<!--</xdbDriver_mysql>-->
 
	<!-- For XMLFiles -->
	<!--<xdbDriver>xmlfiles</xdbDriver>-->
	<!--<xdbDriver_xmlfiles>-->
	<!--<format>encrypted</format>--> <!-- Enable encryption of passwords -->
	<!--</xdbDriver_xmlfiles>-->
 
	<!-- Only grab avatars when a chat is initiated. -->
	<!-- <avatarsOnlyOnChat/> -->
 
	<!-- Disable all avatar functionality. Might be necessary if you -->
	<!-- do not have PIL installed. -->
	<disableAvatars/>
 
	<!-- Enable web presence indicator.  This can increase ICQ spam. -->
	<enableWebPresence/>
 
	<!-- Disable automatic send (via im) of away message when away set. -->
	<!-- Note that away messages are -in addition to- the away status -->
	<!-- message. -->
	<disableAwayMessage/>
 
	<!-- Use Jabber.com's XCP component protocol extensions. -->
	<!-- <useXCP/> -->
 
	<!-- SASL username used to bind to Jabber server. -->
	<!-- secret, above, is used for sasl password -->
	<!-- <saslUsername>username</saslUsername> -->
 
	<!-- Use external component binding. -->
	<!-- This dodges the need to manually configure all jids that talk to this transport. -->
	<!-- Jabberd2 requires saslUsername and useRouteWrap for this to work. -->
	<!-- Wildfire as of 2.6.0 requires just this. -->
	<!-- <useComponentBinding/> -->
 
	<!-- Wrap stanzas in <route> stanza. -->
	<!-- Jabberd2 requires this for useComponentBinding. -->
	<!-- <useRouteWrap/> -->
 
	<!-- JID of message archive service -->
	<!-- <messageArchiveJID>datasink.example.org</messageArchiveJID> -->
 
	<!-- If registration authentication is used, enter the method -->
	<!-- Auth configs often require additional options to be specified. -->
	<!-- See associated config entries per authRegister example. -->
	<!-- NOTE: limited to LDAP for now -->
 
	<!-- THIS IS UNTESTED AS OF YET -->
	<!-- <authRegister>LDAP</authRegister> -->
	<!-- For LDAP auth, make sure to uncomment <authRegister_LDAP> -->
	<!-- and </authRegister_LDAP> and fill out the options in between. -->
	<!-- <authRegister_LDAP> -->
	<!-- The fqdn or ip address of the LDAP server -->
	<!-- <server>ldap.example.org</server> -->
	<!-- The Root DN to be used to perform LDAP searches -->
	<!-- <rootDN>CN=Administrator,CN=Users,DC=example,DC=org</rootDN> -->
	<!-- The password for the Root DN -->
	<!-- <password>SECRET</password> -->
	<!-- The Base DN to search for users -->
	<!-- <baseDN>DC=example,DC=org</baseDN> -->
	<!-- The attribute to search for the user ID. -->
	<!-- 'samAccountname' in Windows, 'uid' on most other systems -->
	<!-- <uidAttr>samAccountname</uidAttr> -->
	<!-- </authRegister_LDAP> -->
 
	<!-- Default Ad-Hoc settings -->
	<adhocDefaults>
	  <user> <!-- ... for new users - they can change these settings later -->
	    <xstatus_receiving_mode>3</xstatus_receiving_mode> <!-- 0 - disable x-status receiving, 1 - receive as ICQ 5.1, 2 - as ICQ 6, 3 - combined -->
	    <xstatus_sending_mode>3</xstatus_sending_mode> <!-- 0 - disable x-status sending, 1 - send as ICQ 5.1, 2 - as ICQ 6, 3 - combined -->
	    <xstatus_saving_enabled>1</xstatus_saving_enabled> <!-- 1 - restore latest x-status after login, 0 - do not restore -->
	    <xstatus_option_smooth>1</xstatus_option_smooth> <!-- 1 - allow partial interconnect between ICQ 5.1 and ICQ 6 x-statuses -->
	    <xstatus_display_icon_as_PEP>1</xstatus_display_icon_as_PEP> <!-- 1 - display x-status icon as User Mood/Activity/Tune -->
	    <xstatus_display_text_as_PEP>1</xstatus_display_text_as_PEP> <!-- 1 - Try interpret x-status text as User Mood/Activity/Tune -->
	    <xstatus_icon_for_transport>1</xstatus_icon_for_transport> <!-- 1 - show self x-status icon as User Mood/Activity/Tune for transport (works for Gajim when transport displayed in roster) -->
	    <away_messages_receiving>0</away_messages_receiving> <!-- 1 - ask contacts for Away messages -->
	    <away_messages_sending>0</away_messages_sending> <!-- 1 - allow own Away Message sending -->
	    <clist_show_phantombuddies>0</clist_show_phantombuddies> <!-- 1 - show old deleted contacts without authorization in roster -->
	    <clist_deny_all_auth_requests>1</clist_deny_all_auth_requests> <!-- 1 - auto send 'Deny' reply on any authorization request -->
	    <utf8_messages_sendmode>2</utf8_messages_sendmode> <!-- 0 - never send messages in Unicode, 1 - only when contact sends messages in Unicode, 2 - send always -->
	    <offline_messages_sendenc>2</offline_messages_sendenc> <!-- 0 - send offline messages in Unicode, 1 - in default message encoding (see above), 2 - auto detect -->
	    <msgconfirm_sendmode>2</msgconfirm_sendmode> <!-- 0 - never send message confirmations, 1 - send for Unicode messages, 2 - for all messages -->
	    <msgconfirm_recvmode>1</msgconfirm_recvmode> <!-- 1 - receive message confirmations -->
	    <user_mood_receiving>1</user_mood_receiving> <!-- 1 - transport should send User Mood/Activity/Tune events to connected user -->
	    <user_activity_receiving>1</user_activity_receiving> <!--  (requirted for x-status as icon displaying) -->
	    <user_mood_receiving>1</user_mood_receiving> <!-- set options if most of users has client with support of these PEP events -->
	    <autoanswer_enable>0</autoanswer_enable> <!-- enable auto answer as reply on any incoming message -->
	    <autoanswer_hide_dialog>0</autoanswer_hide_dialog> <!-- hide incoming messages when autoanswer enabled -->
	  </user>
	</adhocDefaults>
</pyicqt>

Далее мы настроим скрипт авторизации так, чтобы он использовал нашу почтовую базу пользователей.

Для этого создадим указанный в конфигурации файл /etc/ejabberd/auth.pl:

#!/usr/bin/perl 
use Switch;
use Digest::MD5 qw(md5_hex);
use DBI;
 
open(LOG, '>/var/log/ejabberd/auth.log');
 
 
my $dbUser="mail";  
my $dbName="mail";	
my $dbTable="virtual_users"; # The name of the table inside the database
my $dbPass ='mail_password';
 
sub log_die {
	my ($msg) = @_;
	syswrite LOG, "\n$msg";
	die;
	return true;
}
 
 
 
# Reading information from ejabberd
while(1) {
        my $nread = sysread STDIN, my $buf, 2;
		unless ($nread == 2) { exit }
        my $len = unpack "n", $buf;
        $nread = sysread STDIN, $buf, $len;
        syswrite LOG, "[$len]$buf->";
        my ($operation,$user,$domain,$passwd) = split /:/, $buf;
        # Filter dangerous characters
        $user 		=~ s/["\n\r'\$`]//g;
        $passwd 	=~ s/["\n\r'\$`]//g;
        $domain 	=~ s/["\n\r'\$`]//g;
	$passwd		= md5_hex($passwd);
	$dbh = DBI->connect("DBI:mysql:$dbName", $dbUser, $dbPass) or log_die 'Cannot connect to MySQL';
    eval {
		my $result = 0;
		switch ($operation)
		{
			case /isuser/	 
			{
				my $query = "
					SELECT 
						COUNT(id)
					FROM 
						virtual_users
					WHERE
							user = 
								'$user'
						AND
							domain_id = 
								(SELECT 
									id 
								FROM
									virtual_domains 
								WHERE
									name = '$domain'
								)
							";
				my $sth_isuser = $dbh->prepare($query);
				$sth_isuser->execute;
				my @row = $sth_isuser-> fetchrow_array;
				$result = $row[0];
			}
			case /auth/		
			{
				my $query = "
								SELECT 
									COUNT(id)
								FROM 
									virtual_users
								WHERE
										user = 
											'$user'
									AND
										domain_id = 
											(SELECT 
												id 
											FROM
												virtual_domains 
											WHERE
												name = '$domain'
											)
									AND
										password =
											'$passwd'
							";
				my $sth_auth = $dbh->prepare($query);
				$sth_auth->execute;
				my @row = $sth_auth-> fetchrow_array;
				$result = $row[0];
				#syswrite LOG, "\n".@row[0]."\n";
			}
			case /setpass/		 
			{
					my $query = "
					UPDATE 
						virtual_users
					SET
						password = 
							'$passwd'
					WHERE
							user = 
								'$user'
						AND
							domain_id = 
								(SELECT 
									id 
								FROM
									virtual_domains 
								WHERE
									name = '$domain'
								)
							";
				my $sth_setpass = $dbh->prepare($query);
				$sth_setpass->execute or die 'cannot execute';
				$result = $sth_setpass-> rows ? true : false;
			}
			case /tryregister/	 
			{
					my $query = "
					INSERT IGNORE
					INTO
						virtual_users
					(user,domain_id,password)
					VALUES
							('$user',
							(SELECT 
								id 
							FROM
								virtual_domains 
							WHERE
								name = '$domain'
							),
							'$passwd'
						)
					";
				my $sth_tryregister = $dbh->prepare($query);
				$sth_tryregister->execute;
				$result = $sth_tryregister-> rows;
			}
			case /removeuser/	 
			{
				my $query = "
					DELETE
					FROM
						virtual_users
					WHERE
							user = 
								'$user',
						AND
							domaint_id = 
								(SELECT 
									id 
								FROM
									virtual_domains 
								WHERE
									name = '$domain'
								),
					";
				my $sth_remove = $dbh->prepare($query);
				$sth_remove->execute or die 'cannot execute';
				$result = $sth_remove-> rows ? true : false;
			}
			case /removeuser3/	 
			{
				my $query = "
					DELETE
					FROM
						virtual_users
					WHERE
							user = 
								'$user',
						AND
							domaint_id = 
								(SELECT 
									id 
								FROM
									virtual_domains 
								WHERE
									name = '$domain'
								),
						AND 
							password = 
								'$passwd'
					";
				my $sth_remove3 = $dbh->prepare($query);
				$sth_remove3->execute or die 'cannot execute';
				$result = $sth_remove3-> rows ? true : false;
			}
		}
		syswrite LOG, $result ? "VALID\n":"INVALID\n";
		my $out = pack "nn",2, $result ? 1 : 0;
		syswrite STDOUT, $out;
	};
	next if $@;
	$dbh->disconnect();
	#die 'Test complete';
}
 
close(LOG);

После этого можете брать ваш любимый jabber-клиент (я предпочитаю Psi+ ), подключаться к серверу и радоваться жизни.