Kerberos: тяжкий путь между багами

Jul 01, 2015 00:05


Моё внимание всегда привлекали гетерогенные решения. Из серии "скрестить ужа с ежом и получить полтора метра колючей проволоки". Если речь идёт о совместной работе Windows и Linux, то тут наверняка откуда-нибудь из-за угла выползет Kerberos - протокол аутентификации. И несмотря на страшное название, бояться его не стоит. Только вот почти все связанные с ним инструменты и реализации имеют такое количество злобных неочевидных багов, что прорваться между ними подчас бывает очень и очень непросто. Некоторые из них я изложу здесь прежде всего себе на память.

Про матчасть очень хорошо расписано вот здесь (и там тоже фигурирует Стас, гы), повторяться не буду. Напомню только прописные азы практической реализации.
  1. Kerberos подвязан на системное время. Часы везде должны быть синхронизированы.
  2. Kerberos подвязан на DNS. Разрешение имени хоста по IP должно дать актуальный FQDN сервера. Который, в свою очередь должен коррелировать с именем системы и при прямом разрешении отдавать исходный IP.
  3. В общем случае все сообщения и параметры протокола являются Case-sensitive. Названия Realm-ов пишутся заглавными буквами (caps).

Теперь про конкретную задачу. Захотелось вот монаху съесть живую черепаху. Вознамерился я в видновом домене (Win 2012R2 + AD) с условным именем "foo.blya" приподнять линуксовую виртуалку с Samba server и Apache2. Причем, по задумке, и тот, и другой должны впускать своих пользователей абсолютно прозрачно.

Для начала разберёмся с самбой (ди жанейро!). С одной стороны, к ней в комплекте идёт бинарная утилитка "net", которая умеет создавать в виндовом домене учётки. Плюс модуль WinBind, предназначенный для генерирования и сопоставления системных uid-ов именам доменных пользователей. Но если оных не так уж много, то куда проще организовать что-нибудь вроде "username map = /etc/samba/usermap" и не колдовать с nsswitch, pam и прочими радостями повседневного системного администрирования. Во-вторых, "net ads" - это такая вещь в себе, которая будет драться со сторонними сервисами. А я ведь хотел там же ещё и Apache завести, помните?

Значит надо привязывать самбу к домену ручками. Раньше это сводилось к созданию юзеров в AD, генерации keytab-ов при помощи "ktpass", потом надо было переносить получившийся файл на Linux-машину, а впоследствии следить за тем чтобы пароль от учётки не протух... Однако в 2013-м году доброму дяденьке по имени Ken Dreyer надоел весь этот геморрой, и он написал волшебную приблуду под названием "msktutil", которая всё делает сама. Надо только запустить её с правильными параметрами. И обойти баги.
  1. В документации к msktutil есть ошибка. Один из параметров называется не "--accountname", а "--account-name" (с дефисом).
  2. Если у вас в имени сервера присутствуют заглавные буквы, то вся эта кухня не срастётся по причине различий в алгоритмах генерации соли к аккаунту виндовой машиной и утилитой. То же самое относится и к "--use-service-account". Называйте свои хосты и придумывайте имена для сервисных аккаунтов только в нижнем регистре.
  3. Самба (по крайней мере та версия, которую ковырял лично я - 4.1.17), поддерживает только RC4-алгоритм шифрования ключей. Соответственно, добавляйте параметр "--enctypes 0x4".
  4. Сервис, которым по умолчанию представляется Samba, называется "cifs". Плюс ей надо положить в TDBSam пароль для расшифровки присылаемых с сервера аккаунтов. Таким образом, добавляются параметры "--service cifs --set-samba-secret".
  5. Самбе нужна PAC Validation, поэтому ни в коем случае "--no-pac" не прописывать.
  6. В самбе до сих пор актуален баг #6833. Поэтому в конфиге оной писать не "kerberos method = system keytab", а "kerberos method = secrets and keytab".
  7. Самбовый параметр "realm =" есть что-то суть весьма неясное. В документации почему-то рекомендуется прописывать там DNS-имя контроллера домена (KDC-сервера). Видимо, без ковыряния исходного кода этот вопрос так и останется загадкой.
  8. С "server role = meber server" мне не повезло. Заработало с "security = ads".
  9. В usermap в правой части выражений соответствия юзеров необходимо упоминать вместе с именем домена. Например: "stas = FOO\klinkov".
Итого, исчерпывающее заклинание для добавления самбы в AD-домен выглядит так:/usr/sbin/msktutil --create --keytab /etc/krb5.keytab -b OU=SERVERS --service cifs --set-samba-secret --enctypes 0x4
Если заметили, я там заодно ещё и OU-шку явно указал. Это необязательно. И разумеется, при этом должны присутствовать правильные записи в "/etc/hosts", "/etc/krb5.conf" и сделан "kinit vasya.pupkin@FOO.BLYA" с правами доменного админа.
Итак, самба вроде заработала. Теперь хочется ещё поднять рядом апач. Тут есть варианты.

Можно было бы в принципе прикрутить к апачу тот же самый keytab, что и для самбы, но.
  1. Ему придётся работать с теми же алгоритмами шифрования ключей. То есть RC4, без вариантов.
  2. Apache будет получать от KDC сеансовые мандаты с вшитым в оные PAC-ом, что неиллюзорно раздувает их размеры. А вместе с ними - и длину HTTP-заголовка. Который, в свою очередь, по достижении некоторого критического размера, повлечет за собой неработоспособность решения в целом.
  3. Апач читает файл keytab-а от имени непривилегированного пользователя-потомка (в отличие от самбы). То есть, сделать его root:root с правами 600 уже не получится. Нужно давать дополнительные привилегии на чтение какому-нибудь "www-data", что есть не очень хорошо.
  4. В реальности навряд ли, но с параноидальной точки зрения, технически возможная компрометация апачевского keytab-а приведет и к раскрытию самбовых мандатов в том числе. Типа, небезопасно, и всё такое.

Поэтому я долбанулся на отличненько и решил создать для веб-сервера отдельный аккаунт и отдельный keytab. Делается это при помощи всё того же самого msktutil, но заклинание будет уже другим. Нельзя ведь взять и создать в AD-домена два компьютера с одинаковыми именами, верно?
/usr/sbin/msktutil --create --keytab /etc/apache2/apache.keytab -b OU=SERVERS --use-service-account --service HTTP \
--account-name apache-http --no-pac --enctypes 0x18

Таким образом, мы создаём аккаунт "как бе пользователя", который будет привязан к сервису "HTTP/myserver.foo.blya". Еще раз напомню, что после "--account-name" должно идти придуманное нами название обязательно только строчными буквами (убил часа три, прежде чем выяснил)!!!11 Ну и коль скоро это не самба, можно прикрутить к нему шифрование поядрёнее. Единственное, потом придётся не забыть разрешить AES-алгоритмы для пользователей, которые будут работать с этим веб-сервером. Там есть соответствующие "галки" в настройках аккаунта в AD. Обратите также внимание на параметр "--no-pac". В данном конкретном случае он будет совсем не лишним.

И финальный штрих. Добавить в cron на ежедневный запуск выполнение ровно тех же самых заклинаний, только "--create" заменить на "--auto-update". Иначе по прошествии трёх месяцев (когда все про это уже забудут), AD-контроллер решит, что пароль доменной учётки сервера/сервиса уже протух и внезапно без видимых причин откажется с ним работать. А ты иди и разбирайся в чём дело.

И вообще, диагностика и отладка всего этого добра - это отдельная песня. Если в самбе ещё можно выставить "log level = 2" и смотреть по какому поводу она там тихо матерится (причём, увы, совершенно неинформативно), то вот в случае с апачем вообще придётся догадываться исключительно самому по ключевым словам. И весь процесс настройки гетерогенного Kerberos-а очень точно описан в одной известной песне: "Хотя, понемногу, между багов нащупал дорогу, но что ж их так много, ей богу?".

Если кого-то вдруг торкнет повторить мой опыт, вот ссылка на хорошее вдумчивое руководство. Только следовать ему нужно не слепо, а с применением головы. Так, например, в случае использования msktutil для создания сервисных аккаунтов, уже не получится сделать тестовый kinit от их имени, потому что утилита по умолчанию не создаёт соответствующий userPrincipalName (в отличие от заведения аккаунта штатными консолями AD). Но вообще, технология под названием "Kerberos" действительно существует и действительно работает. Теперь я это точно знаю. :)

гетерогенность, администрирование, kerberos, linux, windows, it

Previous post Next post
Up