Tips & Triks

не ломается у того, кто ничего не делает...

Jabber + GSSAPI + LDAP

, ,

Появилось нормальное желание сделать прозрачную авторизацию на стороне сервера для входа в корпоративный jabber. В сети уже работал kerberos5 и пользователи хранились в open-ldap, все было хорошо... Начались поиски быстрого способа воплотить задумку в жизнь... быстрого найти не удалось, но появились варианты

Openfire
Ejabberd
Jabberd

Оговорюсь сразу, пока удалось настроить только связку Ejabberd + Pidgin, о ней и пойдет речь...

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


I. Повторять все не буду, скачиваем, патчим, ставим.
Я предлагаю уже скачать готовый пакеты, которые я собрал и просто поставить.
Сборка для Debian Lenny x86.

Ejabberd + GSSAPI for ejabberd 2.1.0 final + mod_shared_roster_ldap
ejabberd_2.1.0-3_i386.deb


esasl_0.1-1_i386.deb

Так же рекомендую проверить чтобы стояли библиотеки

libkrb5-25-heimdal
libkrb5-dev
libkrb53
libpam-krb5


II.После установки необходимо поправить конфиг /etc/ejabberd/ejabberd.cfg
Это реально работающий конфиг, где убрано все лишнее, важные моменты прокомментированы

override_global.
override_local.
override_acls.
%% ACL администратора сервера
{acl, admin, {user, "admin", "domain.org"}}.
%% Имя сервера
{hosts, ["domain.org"]}.
%% Лог уровень debug
{loglevel, 5}.
{route_subdomains, s2s}.
%% Настройки портов
{listen,
 [
  {5222, ejabberd_c2s, [
                        {access, c2s},
                        {shaper, c2s_shaper},
                        {max_stanza_size, 65536}
                       ]},
  {5223, ejabberd_c2s, [
                        {access, c2s},
                        {shaper, c2s_shaper},
                        {max_stanza_size, 65536},
                        starttls, {certfile, "/etc/ejabberd/ejabberd.pem"}
                       ]},
  {5269, ejabberd_s2s_in, [
                           {shaper, s2s_shaper},
                           {max_stanza_size, 131072}
                          ]},
  %%Авторизоваться в web у меня так и не получилось.
  {5280, ejabberd_http, [
                         http_poll,
                         web_admin
                        ]}
 ]}.
%% Настройки SSL
{s2s_use_starttls, true}.
{s2s_certfile, "/etc/ejabberd/ejabberd.pem"}.
%% ВАЖНО! Realm вашего kerberos
{sasl_realm, "DOMAIN.ORG"}.
{sasl_fqdn, "jabberd-host.domain.org"}.
%% Настройки авторизации в ldap (в данном примере анонимная)
{host_config, "domain.org", [
        {auth_method, ldap},
        {ldap_servers, ["ldap.domain.org"]},
        {ldap_port, 389},
        {ldap_base, "ou=People,dc=domain,dc=org"}
        ]}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
%% АCL для входа через веб-интерфейс
{acl, admins, {user, "admin@domain.org", "domain.org"}}.
{host_config, "domain.org", [{acl, admins, {user, "admin@domain.org", "domain.org"}}]}.
{access, configure, [{allow, admins}]}.
{acl, local, {user_regexp, ""}}.
{access, max_user_sessions, [{10, all}]}.
{access, local, [{allow, local}]}.
{access, c2s, [{deny, blocked},
               {allow, all}]}.
{access, c2s_shaper, [{none, admin},
                      {normal, all}]}.
{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}]}.
{access, pubsub_createnode, [{allow, all}]}.
{language, "en"}.
{modules,
 [
  {mod_adhoc,    []},
  {mod_announce, [{access, announce}]}, % requires mod_adhoc
  {mod_caps,     []},
  {mod_configure,[]}, % requires mod_adhoc
  {mod_ctlextra, []},
  {mod_disco,    []},
  %%{mod_echo,   [{host, "echo.localhost"}]},
  {mod_irc,      []},
  {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,  []},
  {mod_privacy,  []},
  {mod_private,  []},
  {mod_proxy65,  [
                  {access, local},
                  {shaper, c2s_shaper}
                 ]},
  {mod_pubsub,   [ % requires mod_caps
                  {access_createnode, pubsub_createnode},
                  {plugins, ["default", "pep"]}
                 ]},
  {mod_register, [
                  {access, register}
                 ]},
  {mod_roster,   []},
  %%{mod_service_log,[]},
  %%{mod_shared_roster,[]},
  {mod_stats,    []},
  {mod_time,     []},
  %%Брать информацию о пользователях из ldap
  {mod_vcard_ldap, [
    {ldap_rootdn, ""},
    {ldap_password, ""},
    {ldap_servers, ["ldap.domain.org", "ldaps.domain.org"]},    % List of LDAP servers
    {ldap_port, 389},
    {ldap_base, "ou=People,dc=domain,dc=org"}, % Search base of LDAP directory
    {ldap_uidattr, "uid"},
    {ldap_uidattr_format, "%u"},
    {ldap_filter, ""},
    {ldap_vcard_map, [
        {"NICKNAME", "%u", []}, % just use user's part of JID as his nickname
        {"FN", "%s", ["cn"]},
        {"FAMILY", "%s", ["sn"]},
        {"GIVEN", "%s", ["givenName"]},
        {"MIDDLE", "%s", ["initials"]},
        {"ORGNAME", "%s", ["o"]},
        {"ORGUNIT", "%s", ["ou"]},
        {"CTRY", "%s", ["c"]},
        {"LOCALITY", "%s", ["l"]},
        {"STREET", "%s", ["street"]},
        {"REGION", "%s", ["st"]},
        {"PCODE", "%s", ["postalCode"]},
        {"TITLE", "%s", ["title"]},
        {"URL", "%s", ["labeleduri"]},
        {"DESC", "%s", ["description"]},
        {"TEL", "%s", ["telephoneNumber"]},
        {"EMAIL", "%s", ["mail"]},
        {"BDAY", "%s", ["birthDate"]},
        {"PHOTO", "%s", ["jpegPhoto"]}
    ]},
    %% Поиск в ldap
    {ldap_search_fields, [
        {"User", "%u"},
        {"Full Name", "cn"},
        {"Given Name", "givenName"},
        {"Middle Name", "initials"},
        {"Family Name", "sn"},
        {"Nickname", "%u"},
        {"Birthday", "birthDate"},
        {"Country", "c"},
        {"City", "l"},
        {"Email", "mail"},
        {"Organization Name", "o"},
        {"Organization Unit", "ou"}
        ]}
    ]},
  {mod_version,  []}
 ]}.



Для того чтобы при логине в jabber у нас отображалась группа пользователей взятая из Ldap, необходимо доставить модуль mod_shared_roaster_ldap


Добавить настройки в конфиг в раздел modules.
%%mod_shared_roster
{mod_shared_roster_ldap,[
    {ldap_base, "dc=domain,dc=org"},
    {ldap_uidattr, "uid"},
    {ldap_groupattr,"o"},
    {ldap_groupdesc,""},
    {ldap_rfilter,"(o=Jabber Group)"},
    {ldap_filter,"(ObjectClass=*)"},
    {ldap_memberattr,"uid"},
    {ldap_userdesc,"gecos"}
    ]},

Возможно в вашей ldap схеме придется заменить "o" на "cn".


Сделаем еще сертификат для ssl

  
openssl req -new -x509 -newkey rsa:1024 -days 60 -keyout privkey.pem -out key.pem
openssl rsa -in privkey.pem -out privkey.pem
cat privkey.pem >> /etc/ejabberd/ejabberd.pem


III. Теперь нужно добавить строчку чтобы демон знал где брать keytab от xmpp

/etc/default/ejabberd
export KRB5_KTNAME="/etc/ejabberd/xmpp.keytab"



IV. Теперь как делать keytab.
Заходим в kadmin как админ, создаем принципла для нашего сервера и его кейтаб.

addprinc -randkey xmpp/jabberd-host.domain.org@DOMAIN.ORG
ktadd -k /etc/ejabberd/xmpp.keytab -e des3-hmac-sha1:normal xmpp/jabberd-host.domain.org@DOMAIN.ORG
chown ejabberd:ejabberd /etc/ejabberd/xmpp.keytab
chmod 600 /etc/ejabberd/xmpp.keytab

Должны получить файл по указанному нами выше пути /etc/ejabberd/xmpp.keytab, файл этот должен находится конечно же на сервере где запущен jabberd.
Одно замечание, почему нужно использовать это шифрование, потому что с des-cbc-crc:normal у меня не заработало.
Так же очень важно проверить права на keytab, пользователь от которого запускается jabber должен иметь право на чтение keytab, ибо по умолчание читать может его только рут.


V.Теперь нужно сделать записи в DNS. Не уверен что нужны именно все записи, но по разным источникам часть из них нужна точно.

zone: domain.org

; records  for jabber
_kerberos._udp  IN      SRV     0 0 88 kdc
_kerberos._udp  IN      SRV     1 0 88 kdcs
_kerberos       IN      TXT     "DOMAIN.ORG"
_jabber._tcp    IN      SRV     5 0 5269 jabberd-host
_xmpp-server._tcp       IN      SRV   5 0 5269 jabberd-host
_xmpp-client._tcp       IN      SRV   5 0 5222 jabberd-host
_xmpp-client._tcp       IN      SRV   5 0 5223 jabberd-host


- kdc и kdcs это наши primary и secondary kerberos domain server.
- "DOMAIN.ORG" наш REALM который должен совпадать с realm в конфиге ejabberd.cfg
- jabberd-host это имя нашего сервера, на котором запущен Ejabberd, естественно у каждого оно будет свое, и A и PTR запись jabberd-host.domain.org соотвественно тоже должны быть.

VI. Если все готово, то теперь необходимо запустить сервер и посмотреть что все заработало

/etc/init.d/ejabberd start
netstat -nlp --tcp |grep 52

Вывод
tcp        0      0 0.0.0.0:5280            0.0.0.0:*               LISTEN      11608/beam.smp
tcp        0      0 0.0.0.0:56352           0.0.0.0:*               LISTEN      11608/beam.smp
tcp        0      0 0.0.0.0:5222            0.0.0.0:*               LISTEN      11608/beam.smp
tcp        0      0 0.0.0.0:5223            0.0.0.0:*               LISTEN      11608/beam.smp
tcp        0      0 0.0.0.0:5269            0.0.0.0:*               LISTEN      11608/beam.smp


Смотрим так же в /var/log/ejabberd/esasl.log
ищем там =PROGRESS REPORT==== если видим ====CRASH REPORT==== то гдето проблемы.

Смотрим в /var/log/ejabberd/ejabberd.log и ищем там


=INFO REPORT==== 2009-06-05 19:27:14 ===
D(<0.268.0>:eldap:745) : {'LDAPMessage',1,
{bindResponse,
{'BindResponse',success,[],[],asn1_NOVALUE,
asn1_NOVALUE}},
asn1_NOVALUE}



что озночает что с ldap у нас все срослось...


VII. Пробуем Pidgin с клиентской машины где настроен kerberos и установлен pidgin

Проверяем
dpkg -l |grep pidgin

ii  pidgin                                      2.4.3-4lenny2                  graphical multi-protocol instant messaging client for X
ii  pidgin-data                                 2.4.3-4lenny2                  multi-protocol instant messaging client - data files


Запускаем...
pidgin -d


Настройки соединения в клиенте.

User admin (тот на которого у вас есть тикет)
Domain domain.org
Port 5222 (Если включить SSL то порт 5223)
Server jabberd-host.domain.org

Внимательно смотрим в debug коносоль
Ищем строчки

Первое: что сервер нам отвечает и говорит какие способы авторизации он поддерживает, то что наш клиент отправляет ему запрос на авторизацию по GSSAPI.

(14:41:07) sasl: Mechs found: GSSAPI PLAIN
(14:41:07) jabber: Sending: <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='GSSAPI'>YIICRwYJKoZIhvcSAQICAQBuggI2MIICMqADAgEFoQMCAQ6iBwMFACAAAACjggEVYYIBETCCAQ2gAwIBBaEOGwxPS1RFVExBQlMuUlWiJDAioAMCAQGhGzAZGwR4bXBwGxFkaW9yLm9rdGV0bGFicy5ydaOBzzCBzKADAgEQoQMCAQeigb8EgbyuqR9Hwk0IPrzohvBMYEOQxiEnvKfgYwXg/+QewkrXGCPIZisdfsdfXb2s03TNkC1x6hkErerty3zChLvYIhFhbnqjhjh8wCNAbsVoqA7sw/NyIqOV/tB19H34NJBj767IfKWtyteyercvnukk78oinoJbwfJx8rrf4YNKv7+n3LqE5ezM+eygA4ziWDv6JMPCBsdffgsfsgjkuy5ou963GZesYrdwFkDsYwSoO73xkn9fgJbWjjt92ZEIYr7Jw4Ekr9tjI3SU4G7PK2W9K+IF8/6n2364WC3tgyh9ycpBPHCpamdf534Enhcbnu54r60fVUbct8IPzGmkCOSpQFz5A3ix0Gk=</auth>



Второе: мы получаем ответ от сервера, что мы авторизированы


(14:41:07) jabber: Recv (268): <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>YIGWBgkqhk78siGasd9xghgIBaAsdfAgICAG+BhjCBg6ADAgEFoQMCAQ+idzLJKDFnmsdhjgsd73kmKJSHDNLKC094jmtrnbmzBDStnyJrDpwa6csho+ZpE6h+RrXtP7UIL9u5J1KJLSWXNBV91423n2CJSdfo45tJHGSDQJ5</challenge>
(14:41:07) jabber: Sending: <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl%27/>
(14:41:07) jabber: Recv (152): <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>YD8GCSJLKJLOM487NBA3EgECAgIBBAD/////M0SdnAsOdnQdba5Lw+CBpzASTRP/iL+AoiAGfJSNANCVBZOPXAf///wQEBSJWA=</challenge>
(14:41:07) jabber: Sending: <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>YD8DFHSJSAOOWBAD/////4dSKJncUJUSJALlSieDFh3947263D4qV1VhvKc56AILIASJS=</response>
(14:41:07) jabber: Recv (51): <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl%27/>



Неправильно если видим строчку


jabber: Recv (ssl)(77): <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>



Так же необходимо проверить у клиента что он получает тикет от сервера для xmpp
Вот так должен выглядеть вывод если все правильно.
#klist

Ticket cache: FILE:/tmp/krb5cc_1065_UJnRu3
Default principal: user@DOMAIN.ORG

Valid starting     Expires            Service principal
06/09/09 14:35:39  06/10/09 06:35:39  krbtgt/DOMAIN.ORG@DOMAIN.ORG
06/09/09 14:41:07  06/10/09 06:35:39  xmpp/jabberd-host.domain.org@DOMAIN.ORG


Пока все.

Updated 2010/03/15

Ссылки по теме:
Ejabberd2 Guide
GSSAPI Patch
mod_shared_roster_ldap (original)
mod_shared_roster_ldap (правленый)

Сравнение производительности файловых систем установленных поверх DRBDШифрование туннелей c помощью IPSEC

Comments

Виталийh2005 Friday, February 19, 2010 9:55:16 AM

вопрос:
а если не сростается с лдап
=INFO REPORT==== 2010-02-19 11:44:33 === D(<0.679.0>:eldap:695) : {bindResponse, {'BindResponse',invalidCredentials,[],[], asn1_NOVALUE,asn1_NOVALUE}}
таким вот образом, куда дальше идти?

Zl0 Saturday, February 27, 2010 10:35:10 AM

Обратите внимание что в конфиге ldap поддерживает анонимное соединение к нему, если у вас не поддерживает то добавте bind dn dnpassword

Unregistered user Saturday, May 8, 2010 1:04:37 AM

Ðноним writes: А с openfire проблемы возникли, или просто jabberd оказался первым в очереди?

Zl0 Saturday, May 8, 2010 7:15:48 AM

Openfire тяжелая поделка, с кучей функционала, который не был бы востребован, к тому же используют java-nonfree, хотя вроде последнии версии можно запустить и на openjdk.
Особых проблем с ним не возникало, хотя да, я не смог нормально сделать там shared roster из ldap групп, видимо схема у нас в ldap не совсем обычная.

Write a comment

New comments have been disabled for this post.

June 2012
M T W T F S S
May 2012July 2012
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30