Рекомендации по настройке SSSD в Debian GNU/Linux

System Security Services Daemon (SSSD) – это пакет приложений для управления аутентификацией и авторизацией в операционных системах на базе Linux. SSSD является отличной альтернативой монструозной Samba, позволяя подключить Linux машину к уже имеющемуся домену Active Directory.

Большинство статей в интернет, описывающих использование SSSD для подключения к Active Directory, ставят перед собой задачу показать, насколько это легко и непринужденно. Зачастую, это очень короткие "истории успеха", в которых берется SSSD и Realmd, вводится пара команд, и все! Авторизация настроена.

Спорить тут не с чем, так оно и есть. Но при этом надо держать в уме, что SSSD – это довольно сложный программный продукт, взаимодействующий с целым рядом отдельных подсистем хоста. В этой статье мне бы хотелось остановиться на некоторых нюансах настройки SSSD в Debian GNU/Linux и дать несколько полезных советов по его использованию в боевых условиях.

Отмечу, что отправной точкой для исправления любых проблем с SSSD является вдумчивое чтение его логов, файлы которых расположены в /var/log/sssd. При этом отладочные логи SSSD достаточно подробны, их очень легко читать, и они включаются одной простой командой, не требующей перезапуска сервиса:

# sss_debuglevel 7

Все описанные ниже особенности актуальны для версий SSSD 1.11.7 и 1.15.0. На момент написания этой статьи именно эти версии находятся в stable репозиториях Debian 8 Jessie и Debian 9 Stretch соответственно.

 

FQDN в качестве имени хоста

Исторически сложилось, что в "родных" для SSSD дистрибутивах - RHEL и CentOS - принято в качестве имени хоста использовать FQDN, тогда как в Debian и Ubuntu - наоборот, короткое имя без DNS суффикса.

На Debian эта идеологическая разница приводит не только к некорректной установке SPN (подробнее см. "Обходное решение для ошибки регистрации servicePrincipalName (ATT_OR_VALUE_EXISTS) при подключении Debian GNU/Linux Jessie к домену Active Directory с помощью realm join"), но и к отказу функции динамического обновления DNS.

В отладочных логах SSSD можно увидеть, что некорректное имя хоста появляется в сообщениях для nsupdate. В примере вместо строки "debian." должно быть полное DNS имя хоста "debian.example.com.".

..[sssd[be[example.com]]] [nsupdate_msg_create_common] (0x0200): Creating update message for server [dc01.example.com] and realm [EXAMPLE.COM].
..[sssd[be[example.com]]] [be_nsupdate_create_fwd_msg] (0x0400):  -- Begin nsupdate message --
server dc01.example.com
realm EXAMPLE.COM
update delete debian. in A
send
update delete debian. in AAAA
send
update add debian. 3600 in A 192.168.191.8
send
..[sssd[be[example.com]]] [be_nsupdate_create_fwd_msg] (0x0400):  -- End nsupdate message --
..[sssd[be[example.com]]] [write_pipe_handler] (0x0400): All data has been sent!
..[sssd[be[example.com]]] [nsupdate_child_stdin_done] (0x1000): Sending nsupdate data complete
..[sssd[be[example.com]]] [be_nsupdate_args] (0x0200): nsupdate auth type: GSS-TSIG
..[sssd[be[example.com]]] [child_sig_handler] (0x1000): Waiting for child [29253].
..[sssd[be[example.com]]] [child_sig_handler] (0x0020): child [29253] failed with status [1].
..[sssd[be[example.com]]] [nsupdate_child_handler] (0x0040): Dynamic DNS child failed with status [256]
..[sssd[be[example.com]]] [be_nsupdate_done] (0x0040): nsupdate child execution failed [1432158228]: Dynamic DNS update failed

Некорректное поведение исправляется явным указанием параметра ad_hostname в конфигурационном файле SSSD /etc/sssd/sssd.conf. В качестве значения параметра указывается полное DNS имя хоста, включая DNS суффикс.

[domain/example.com]
...
ad_hostname = debian.example.com
...

 

Разрешение имени хоста

Функция динамического обновления DNS также некорректно работает, если собственное имя хоста разрешается в адрес петлевого (loopback) интерфейса.

Дело в том, что функция динамического обновления DNS обновляет не только A-запись на DNS сервере. Помимо этого, SSSD обновляет соответствующую PTR-запись для обратного разыменования (reverse lookup). По умолчанию на Debian системах в /etc/hosts есть строка вида

127.0.1.1 debian.example.com debian

Эта запись разрешает имя хоста в IP адрес петлевого интерфейса 127.0.1.1, что, в свою очередь, приводит к тому, что SSSD пытается обновлять на DNS сервере некорректную PTR-запись вида 1.1.0.127.in-addr.arpa.

..[sssd[be[example.com]]] [nsupdate_msg_create_common] (0x0200): Creating update message for server [c01.example.com] and realm [EXAMPLE.COM].
..[sssd[be[example.com]]] [be_nsupdate_create_ptr_msg] (0x0400):  -- Begin nsupdate message --
server dc01.example.com
realm EXAMPLE.COM
update delete 1.1.0.127.in-addr.arpa. in PTR
update add 10.0.168.192.in-addr.arpa. 3600 in PTR debian.example.com.
send
..[sssd[be[example.com]]] [be_nsupdate_create_ptr_msg] (0x0400):  -- End nsupdate message --
..[sssd[be[example.com]]] [write_pipe_handler] (0x0400): All data has been sent!
..[sssd[be[example.com]]] [nsupdate_child_stdin_done] (0x1000): Sending nsupdate data complete
..[sssd[be[example.com]]] [be_nsupdate_args] (0x0200): nsupdate auth type: GSS-TSIG
..[sssd[be[example.com]]] [child_sig_handler] (0x1000): Waiting for child [30140].
..[sssd[be[example.com]]] [child_sig_handler] (0x0020): child [30140] failed with status [2].
..[sssd[be[example.com]]] [nsupdate_child_handler] (0x0040): Dynamic DNS child failed with status [512]

Чтобы исправить такое поведение, необходимо отредактировать файл /etc/hosts и указать там в качестве IP адреса хоста адрес одного из сетевых интерфейсов.

192.168.0.5 debian.example.com debian

 

Локальный DNS кэш

Аутентификация с использованием SSSD может некорректно работать или не работать вовсе, если из поля видимости хоста пропадает первый DNS сервер, указанный в /etc/resolv.conf.

Очевидно, что SSSD использует системный резолвер (resolver) для разрешения DNS имен. При этом в Linux, в отличии от Windows, по умолчанию нет никакого внутреннего DNS кэша, и любое разрешение DNS имени производится через запрос к DNS серверу. Также, тут следует учесть, что системный резолвер опрашивает DNS сервера, указанные в /etc/resolv.conf в том порядке, в котором они там перечислены с таймаутом запроса в 5 секунд.

Все вышеописанное приводит к тому, что каждое разрешение DNS имени может занимать по времени от 5 секунд в том случае, если в качестве первого DNS сервера в /etc/resolv.conf вдруг оказался недоступный в данный момент контроллер домена.

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

Частично проблема решается с помощью указания нескольких опций в /etc/resolv.conf:

options timeout:1
options rotate

Параметр timeout:1 опускает таймаут ожидания ответа от DNS сервера с пяти до одной секунды, а параметр rotate включает round-robin при выборе первого DNS сервера для опроса. Эти изменения позволят SSSD не уходить в оффлайн режим в случае описанного выше сценария. При этом все равно останутся чувствительные задержки при авторизации и аутентификации.

Целиком эта проблема решается только с помощью настройки на Linux машине локального кэша DNS. Существует несколько различных способов для реализации этого, но самым популярным является использование миниатюрного dnsmasq в качестве локального DNS сервера.

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

Базовая установка выполняется командой:

# apt-get install dnsmasq

Пример рабочей конфигурации выглядит следующим образом:

# cat > /etc/dnsmasq.d/dnscache.conf

listen-address=127.0.0.1
bind-interfaces
no-poll
no-negcache
cache-size=1000
dns-forward-max=150
domain-needed
resolv-file=/etc/resolv.dnsmasq
all-servers

В конфигурации dnsmasq следует обратить внимание на параметр all-servers, который заставляет dnsmasq в случае промаха кэша отправлять DNS запросы сразу ко всем DNS серверам одновременно. При этом адреса "настоящих" DNS серверов удобно выносить из общей конфигурации в отдельный файл, расположенный рядом с системным /etc/resolv.conf.

# cat > /etc/resolv.dnsmasq

nameserver 192.168.0.2
nameserver 192.168.0.3

После правки конфигурации, перезапускаем службу dnsmasq:

# service dnsmasq restart

Теперь dnsmasq настроен и мы можем переключить системный резолвер на использование локального DNS сервера, теперь уже расположенного на localhost:

# cat > /etc/resolv.conf

search example.com
domain example.com
nameserver 127.0.0.1

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

 

Автообнаружение в realm

В больших инсталляциях Active Directory редко используется полносвязная топология. В домене есть сайты, которые разнесены территориально, и контроллеры домена не имеют прямого доступа к некоторым другим контроллерам в этом же домене. В таких инсталляциях также, обыкновенно, есть подсети, в которых расположены клиентские машины, из которых также доступны не все доменные контроллеры.

Тут все просто. При вводе в домен с помощью realm join не стоит рассчитывать на функцию автоматического обнаружения контроллеров домена и при вводе указывать конкретный, заведомо доступный контроллер. Например:

# realm join dc01.example.com

 

Автообнаружение в SSSD

По аналогичной ситуации, не стоит полагаться на функцию автоматического обнаружения контроллеров домена в SSSD, которая включается с помощью ключевого слова "_srv_" параметра ad_server конфигурационного файла /etc/sssd/sssd.conf.

Особенностью механизма автообнаружения в SSSD является то, что он достаточно "ленивый" и, при использовании в частично связанной топологии, может выполняться достаточно долго. Служба SSSD может продолжительное время по очереди перебирать недоступные контроллеры, пока в конечном итоге не наткнется на рабочий. Также, необходимо учитывать, что автообнаружение работает раздельно для двух внутренних сервисов, которые во внутренней логике называются "ad" и "ad_gc". Первый сервис ищет любые доступные контроллеры домена, второй – только контроллеры с глобальным каталогом. Оба сервиса работают независимо друг от друга и не обмениваются между собой никакой информацией о доступности серверов. Как следствие, авторизация и аутентификация с помощью SSSD начинает работать только тогда, когда оба сервиса находят доступный сервер и переходят в состояние онлайн.

Все выше описанное в результате ведет к тому, что при использовании автообнаружения, после запуска SSSD авторизация на сервере не работает, и может не работать достаточно продолжительное время. В отладочных логах SSSD при этом можно увидеть такие строки:

17:16:41 [sssd[be[example.com]]] [resolv_discover_srv_next_domain] (0x0400): SRV resolution of service 'ldap'. Will use DNS discovery domain 'example.com'
17:16:41 [sssd[be[example.com]]] [resolv_getsrv_send] (0x0100): Trying to resolve SRV record of '_ldap._tcp.example.com'
...
17:16:41 [sssd[be[example.com]]] [fo_discover_srv_done] (0x0400): Got answer. Processing...
17:16:41 [sssd[be[example.com]]] [fo_discover_srv_done] (0x0400): Got 6 servers
17:16:41 [sssd[be[example.com]]] [ad_get_dc_servers_done] (0x0400): Found 6 domain controllers in domain example.com
17:16:41 [sssd[be[example.com]]] [ad_srv_plugin_dcs_done] (0x0400): About to locate suitable site
17:16:41 [sssd[be[example.com]]] [sdap_connect_host_send] (0x0400): Resolving host dc03.example.com
17:16:41 [sssd[be[example.com]]] [resolv_gethostbyname_files_send] (0x0100): Trying to resolve A record of 'dc03.example.com' in files
17:16:41 [sssd[be[example.com]]] [resolv_gethostbyname_files_send] (0x0100): Trying to resolve AAAA record of 'dc03.example.com' in files
...
17:16:41 [sssd[be[example.com]]] [sdap_connect_host_resolv_done] (0x0400): Connecting to ldap://dc03.example.com:389
17:16:41 [sssd[be[example.com]]] [sss_ldap_init_send] (0x0400): Setting 6 seconds timeout for connecting
...
17:16:47 [sssd[be[example.com]]] [sdap_id_op_connect_done] (0x0020): Failed to connect, going offline (5 [Input/output error])
17:16:47 [sssd[be[example.com]]] [be_ptask_create] (0x0400): Periodic task [Check if online (periodic)] was created
17:16:47 [sssd[be[example.com]]] [be_ptask_schedule] (0x0400): Task [Check if online (periodic)]: scheduling task 69 seconds from now [1510575476]
17:16:47 [sssd[be[example.com]]] [be_run_offline_cb] (0x0080): Going offline. Running callbacks.
17:16:47 [sssd[be[example.com]]] [ad_subdomains_get_conn_done] (0x0080): No AD server is available, cannot get the subdomain list while offline

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

...
ad_server = dc01.example.com, dc02.example.com, _srv_
...

 

Автообнаружение в Kerberos

Аутентификация на Linux серверах, на которых должным образом не настроен протокол Kerberos, может выполняться с задержками или не выполняться вовсе.

Kerberos 5 - это сетевой протокол аутентификации, в концепции которого лежит доверие к, так называемой, третьей стороне. Kerberos является основным протоколом аутентификации в доменах Active Directory, где в качестве такой третьей стороны выступают контроллеры домена, или KDC (Key Distribution Center).

Для реализации поддержки протокола Kerberos SSSD использует стандартную для Linux библиотеку libkrb5, которая устанавливается автоматически при установке SSSD, и которая содержит в себе эталонную реализацию Kerberos 5 от MIT (Massachusetts Institute of Technology). Вся информация о настройке Kerberos для этой библиотеки находится в конфигурационном файле /etc/krb5.conf.

При вводе машины в домен, утилита realm производит базовую настройку Kerberos, добавляя в конфигурационный файл /etc/krb5.conf лишь информацию о домене без указания конкретных серверов. При такой настройке Kerberos будет автоматически искать доступные KDC с пятисекундным таймаутом запроса к каждому серверу.

Тут необходимо обратить внимание еще и на то, что протокол Kerberos работает поверх более низкоуровневых протоколов UDP и TCP, используя в обоих случаях 88-й порт сервера. Причем, для снижения задержек и общей нагрузки на сеть, по умолчанию, используется именно UDP протокол с "откатом" на TCP только в тех случаях, когда данные запроса перестают помещаться в один UDP пакет.

Поэтому, использование автообнаружения Kerberos в не полносвязной топологии Active Directory может приводить к необъяснимым, на первый взгляд, задержкам аутентификации. В отладочных логах SSSD такие задержки можно определить по следующим строкам:

12:29:52 [sssd[be[example.com]]] [sdap_kinit_kdc_resolved] (0x1000): KDC resolved, attempting to get TGT...
12:29:52 [sssd[be[example.com]]] [create_tgt_req_send_buffer] (0x0400): buffer size: 40
12:29:52 [sssd[be[example.com]]] [set_tgt_child_timeout] (0x0400): Setting 15 seconds timeout for tgt child
12:29:52 [sssd[be[example.com]]] [write_pipe_handler] (0x0400): All data has been sent!
12:29:59 [sssd[be[example.com]]] [read_pipe_handler] (0x0400): EOF received, client finished

На данном примере видно, что запрос TGT-билета Kerberos занял целых 7 секунд. Все из-за того, что в течении этого времени библиотека libkrb5 выполнила попытку запроса билета на недоступный контроллер домена. Как и в случае с автообнаружением в SSSD, в такой ситуации рекомендуется явно добавить описание доступных контроллеров домена в конфигурационный файл /etc/krb5.conf.

[realms]
EXAMPLE.COM = {    
kdc = dc01.example.com 
kdc = dc02.example.com
}

 

Вывод

Мы используем SSSD на боевых серверах уже без малого два года, ровно с того момента, как пакет SSSD появился в stable репозиториях Debian. За все это время SSSD показал себя, как замечательный инструмент для интеграции существующей Linux инфраструктуры в Active Directory. В статье выше перечислено несколько, мягко говоря, не очевидных, но важных моментов при настройке SSSD, которые, зачастую, не описаны в стандартных инструкциях по настройке авторизации.

Резюмируя, еще раз кратко обозначим то, на что следует обращать внимание при настройке SSSD.

    • Динамическое обновление DNS, которое может некорректно работать из-за короткого DNS имени в качестве имени хоста или из-за разрешения DNS имени хоста в IP адрес петлевого интерфейса.
    • Локальный DNS кэш, отсутствие которого в определенных ситуациях может приводить к медленной или вовсе некорректной работе авторизации и аутентификации с использованием SSSD.
    • Автообнаружение, на которое не стоит полагаться и сводить его использование к минимуму, если ваша инсталляция Active Directory не использует полносвязную топологию.

Всего комментариев: 4 Комментировать

  1. Alex M. /

    Здравствуйте, спасибо большое за статью. Не могли бы вы выложить ваши /etc/sssd/sssd.conf и /etc/krb5.conf для Debian для примера? Понятно, что с generic именами.адресами без всего, что относится к реальной сети. Спасибо!

    1. Степан Кохановский / Автор записи

      Да, конечно.

      Опубликовал в виде gist на github: https://gist.github.com/skokhanovskiy/45766c1a23439eee815508feb8c5661c

  2. Алексей Максимов /

    Доброго здоровья, Степан Сергеевич.

    По поводу опции "ad_backup_server = _srv_" могу отметить тот факт, что в sssd 1.15.0 это вызывает ошибку:

    "[_ad_servers_init] (0x0080): Failed to add server [_srv_] to failover service: SRV resolution only allowed for primary servers!"

    То есть получается, что данная настройка в таком виде не несёт пользы.

    1. Степан Кохановский / Автор записи

      Алексей, спасибо за замечание. Да, действительно, в таком виде не работает.

Добавить комментарий