Надоело набирать каждый раз пароли? Надоело иметь отдельный пароль для почты, для шар, для ssh и т.п.? Решение есть — подход называемый Single Sign-On (SSO, единый вход), при которой пароль вводится один раз, и уже в дальнейшем он не нужен. О его реализации с помощью Kerberos я попробую рассказать. Также речь пойдет об NFSv4 с kerberos авторизацией и о настройке различных служб и сервисов для использования SSO/Kerberos.
Цербер — централизованная система проверки подлинности. Чем-то похож на RADIUS, но предназначен исключительно для авторизации, и в том числе авторизации по ранее выданному ключу. В знакомой многим технологии Active Directory авторизация реализована именно на основе kerberos. RADIUS сервера зачастую умеют авторизировать своих пользователей через kerberos.
Пароли цербера в открытом виде по сети не передаются, и вообще система считается весьма безопасной. Однако следует понимать важность SSO пароля — он един для всех сервисов, доступных данной учетной записи, и его разглашение или утеря могут привести к катастрофичным последствиям. Однако из-за того что пароль един, то и запоминать надо его одного, что позволяет менять его сколь угодно часто. А так как он требуется один раз — пароль может быть сколь угодно сложным. И этими двумя возможностями пренебрегать не следует. Также следует понимать, что хоть для самого цербера пароли в открытом виде не передаются, однако если вы его вводите не для авторизации на локальной машине, а передаете через незащищенное соединение — то это компрометирует пароль.
Учетные записи в kerberos обозначаются следующим образом: пользователь@ДОМЕН или сервис/хост@ДОМЕН. Где ДОМЕН (Realm) это собирательное наименование, которое принято писать заглавными буквами, и обычно с приставкой @. Имена учетных записей чувствительны к регистру. Все сервера, пользователи и машины как правило имеют один realm. Однако допустима и кросс-доменная авторизация, но ее настройка это отдельный вопрос. В данной статейке я буду предполагать, что у всех используемых записей одинаковый домен.
Серверная часть цербера состоит из двух компонентов: сервер выдачи ключей (KDC) и сервер администрации (KADMIN). KDC предназначен для клиентов: он авторизирует клиентов и выдает им тикеты. KADMIN же, в свою очередь, предназначен в основном для администраторов. В реальности при штатной работе он практически не нужен, за исключением смены паролей клиентами.
Существует несколько реализаций цербера, как открытых так и закрытых. Они совместимы между собой, но отличаются настройкой (серверной части, для клиентов в основном все одинаково и автоматически). В этой статейке предполагается реализация MIT. В ней KDC работает и по IPv4 и по IPv6, а KADMIN только по IPv4.
Вкратце система авторизации в kerberos такова: клиент авторизируется с помощью пароля на сервере выдачи ключей, и тот выдает клиенту «мастер-тикет», который действителен определенное время. В дальнейшем, когда клиенту нужно авторизоваться на каком-либо ресурсе, из «мастер-тикета» клиент делает сессионный тикет, который и используется для авторизации. Т.е. вводить пароль второй раз уже не нужно. Из этого следует необходимость синхронизации времени между всеми машинами, участвующими в обмене данными: сессионный ключ действителен обычно 5 минут, и если часы расходятся на бóльшее время, то авторизация не удастся. Благо во всех современных ОС есть клиенты NTP, что эту проблему эффективно решает.
Установку в дальнейшем расписываю для debian-based дистрибутивов linux, однако в других системах больших отличий быть не должно. Итак, для начала нужно поставить необходимые программы: они находятся в панетах krb5-admin-server и krb5-kdc. Также полезны krb5-clients. При установке можно разрешить сгенерировать начальные настройки. В результате настройки будут сгенерированы приблизительно следующие:
/etc/krb5kdc/kdc.conf:
[kdcdefaults] kdc_ports = 750,88 [realms] ДОМЕН = { database_name = /var/lib/krb5kdc/principal admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab acl_file = /etc/krb5kdc/kadm5.acl key_stash_file = /etc/krb5kdc/stash kdc_ports = 750,88 max_life = 10h 0m 0s max_renewable_life = 7d 0h 0m 0s master_key_type = des3-hmac-sha1 supported_enctypes = aes256-cts:normal arcfour-hmac:normal des3-hmac-sha1:normal des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3 default_principal_flags = +preauth }
И в /etc/krb5.conf (за вычетом стандартной фигни):
[libdefaults] default_realm = ДОМЕН [realms] ДОМЕН = { # kdc = kdc.сервер.домена admin_server = kadmin.сервер.домена default_domain = dns.зона.домена } [domain_realm] .dns.зона.домена = ДОМЕН dns.зона.домена = ДОМЕН [logging] kdc = FILE:/var/log/kerberos/krb5kdc.log admin_server = FILE:/var/log/kerberos/kadmin.log default = FILE:/var/log/kerberos/krb5lib.log
Если что-то в вашем случае отсутствует — полезно это добавить. Параметр «kdc» следует раскомментировать, если вы не собираетесь настраивать DNS, в противном случае он скорее вреден т.к. теряется централизованное управление этой настройкой через DNS. Параметр «admin_server», к сожалению, указывать придется хотя-бы на избранных машинах — kadmin не смотрит содержимое DNS. В качестве адреса kadmin сервера указывать 127.0.0.1 нельзя — на этом адресе сервер входящие соединения не слушает. Если сервисы не стартовали, и выдали какие-либо ошибки — ничего страшного. Т.к. фактически записей еще нет, то они и будут ругаться.
Создаем наш домен командой krb5_newrealm. На вопрос пароля важно дать ей действительно надежный пароль. Он практически никогда более не будет нужен, но лучше все-таки его где-то записать. После того, как домен создастся сервисы krb5-kdc и krb5-admin-server должны запуститься нормально.
Тестируем работоспособность, и заодно добавляем административного пользователя с помощью программы kadmin.local (здесь и далее в примерах жирным выделен вводимый текст, остальное — вывод программы):
# kadmin.local Authenticating as principal root/admin@ДОМЕН with password. kadmin.local: listprincs K/M@ДОМЕН kadmin/admin@ДОМЕН kadmin/changepw@ДОМЕН kadmin/адрес.kadmin.сервера@ДОМЕН kadmin/history@ДОМЕН krbtgt/ДОМЕН@ДОМЕН kadmin.local: addprinc root/admin WARNING: no policy specified for root/admin@ДОМЕН; defaulting to no policy Enter password for principal "root/admin@ДОМЕН": Re-enter password for principal "root/admin@ДОМЕН": Principal "root/admin@ДОМЕН" created. kadmin.local: quit
kadmin.local — программа, предназначенная для администрирования базы учетных данных с сервера администрации. Она не требует пароля, т.к. работает непосредственно с файлами базы. Но при этом ей нужен полный доступ к этим файлам, т.е. запускать ее надо из-под root и на сервере. И лучше ее вообще не запускать, для штатной работы есть программа kadmin.
Делаем так, чтобы этот новый аккаунт имел административные права: в файле /etc/krb5kdc/kadm5.acl раскомментируем строку «*/admin *» и перезапускаем krb5-admin-server.
Проверяем новый аккаунт, и, заодно, работу kadmin. Заодно добавляем обычных пользоватей, которые в дальнейшем смогут пользоваться системой (имя пользователя должно совпадать с логином):
# kadmin Authenticating as principal root/admin@ДОМЕН with password. Password for root/admin@ДОМЕН: kadmin.local: listprincs K/M@ДОМЕН kadmin/admin@ДОМЕН kadmin/changepw@ДОМЕН kadmin/адрес.kadmin.сервера@ДОМЕН kadmin/history@ДОМЕН krbtgt/ДОМЕН@ДОМЕН root/admin@ДОМЕН kadmin: addprinc пользователь WARNING: no policy specified for пользователь@ДОМЕН; defaulting to no policy Enter password for principal "пользователь@ДОМЕН": Re-enter password for principal "пользователь@ДОМЕН": Principal "пользователь@ДОМЕН" created. kadmin.local: quit
Итак, если все успешно, то можно логиниться в домен кербероса этим пользователем. Мастер-тикет получается и обновляется программой kinit, посмотреть статус полученных тикетов можно программой klist. Обе программы не требуют каких либо опций, и догадываются автоматически обо всем что надо.
Возможная ошибка «kadmin: Missing parameters in krb5.conf required for kadmin client while initializing kadmin interface» скорее всего означает, что в krb5.conf не прописан admin_server, или имя прописанного сервера не резолвится по IPv4.
Для упрощения настройки клиентов можно прописать настройки kerberos домена в DNS. Для этого следует создать такие записи в зоне, имеющей то же имя что и kerberos домен:
$ORIGIN домен. _kerberos TXT "ДОМЕН" _kerberos._udp SRV 0 0 88 имя.kdc.сервера _kerberos-master._udp SRV 0 0 88 имя.kdc.сервера _kerberos-adm._tcp SRV 0 0 749 имя.admin.сервера
На этом настройка серверной части практически закончена. Ссылки для дальнейшего изучения на тему цербера:
Следующие программы будут полезны для работы и настройки:
Эти и другие полезные программы и нужные библиотеки предоставляются пакетами krb5-user и krb5-clients (а для винды можно воспользоваться реализацией от MIT). Настройка элементарна (особенно если вы прописали в DNS параметры сервера): устанавливаем пакеты, указываем наш домен и вуаля. Работоспособность проверяется через kinit и klist. kinit должен авторизироваться и не выдавать ошибок, klist же должен показывать тикеты.
Для удобной работы могу порекомендовать программку kredentials в одноименном пакете — она позволяет быстро, просто и через GUI получать и обновлять тикеты. Если она ругается на «unable to run aklog», что происходит когда не используется AFS, то создайте в /usr/local/bin файл aklog с правами на выполнение и содержимым:
#!/bin/sh exit 0
А если/когда будете использовать AFS, то этот файл надо будет удалить.
Учетные записи бывают двух типов — учетные записи сервисов и учетные записи пользователей. Пользовательские записи предназначены (сюрприз) для пользователей и имеют пароль. Сервисные же для автоматической работы, пароля не имеют, состоят по сути из ключей для шифрования. и для их использования сервисами помещаются в специальные файлы ключей, keytab’ы.
Как уже говорилось выше, сервисные учетные записи выглядят как сервис/адрес@ДОМЕН. Имя сервиса предопределено для каждого из сервисов, домен также предопреден, а вот на адресе хочу остановиться поподробней т.к. это очень важный момент и может вызвать проблемы. Для доступа к сервису на какой-либо машине определяется ее адрес. Также он определяется, когда сам сервис на этой машине пытается получить свой ключ. Цербер чувствителен к имени хоста: если на клиенте имя распозналось иначе чем на сервере, то авторизация не произойдет. Алгоритм един для всех случаев:
Распознается IPv4 (A) адрес машины. Именно A, AAAA не учитываются. Для определения «своего» адреса используется `hostname`, и далее резолвинг идет по стандартному алгоритму: берутся домены из поля search файла /etc/resolv.conf, и проверяется наличие в каждом из них нужного адреса. Если нету — берется следующий.
Т.е. адрес нормализуется с помощью обратки. Вытекающие нюансы и частные случаи:
Сервисные учетные записи создаются также как и пользовательские, но с параметром «-randkey»:
kadmin: addprinc -randkey сервис/адрес.машины WARNING: no policy specified for сервис/адрес.машины@ДОМЕН; defaulting to no policy Principal "сервис/адрес.машины@ДОМЕН" created.
В отличии от пользовательских учетных данных, которые хранятся исключительно на KDC, сервисные необходимо копировать на машину, которая этот сервис предоставляет. Для этого есть следующие подходы:
Первое удобно когда есть доступ с машины к KADMIN, второе — когда нету. Создание учетки и сохранение ключа само собой можно делать сразу, в одной сессии.
Keytab файлы следует держать с соответствующими правами, т.к. они не зашифрованы. Их содержимое можно посмотреть утилитой klist. По умолчанию используется системный keytab: /etc/krb5.keytab, однако переменной окружения KRB5_KTNAME можно разнести keytab’ы разных программ в разные файлы.
Так, общие сведения рассказал, а теперь к деталям разных сервисов.
Знакомый многим протокол виндового «сетевого окружения» samba/cifs далеко не единственный протокол для удаленного доступа к файлам. Например в мире unix есть вполне аналогичный протокол NFS. У NFS довольно много версий и реализаций, однако фактически они все весьма близки, и их можно разбить на две группы — с kerberos и без. Kerberos поддерживается начиная с 4й версии протокола.
Когда kerberos нет — все просто: устанавливаем NFS сервер, прописываем экспорты, и вуаля все работает. Правда с авторизацией по IP адресу (ну и максимум еще и ключевому слову). Фактически же это простой и быстрый способ реализовать обмен файлами между доверенными машинами в локальной сети (работает конечно и через инет, но завязана на фиксированные адреса, прописываемые в настройках, что мало подходит для инета. Да и передача данных совершенно открыта). Доверие к машинам тоже немаловажный момент в этом случае: доступ дается по сути всей машине, а не отдельному ее пользователю. Из-за простоты настройки такой системы не буду на ней останавливаться — man exports, man mount.nfs.
Вообще общая система довольно похожа на систему доменов на протоколе samba: также выделяется отдельный сервер для авторизации пользователей, также авторизируются и компьютеры и пользователи. Только в samba все «в одном флаконе», а тут по отдельности, что и приводит к сложностям настройки. Итак.
Пакеты, предоставляющие нужные возможности: nfs-common (для клиента) и nfs-kernel-server (для сервера).
Для того, чтобы владельцы файлов примонтированных ФС отображались нормально, а не как nobody, в файле /etc/idmapd.conf и на серверах и на клиентах прописываем:
[General] Verbosity = 0 Pipefs-Directory=/var/lib/nfs/rpc_pipefs Domain=домен [Mapping] Nobody-User=nobody Nobody-Group=nobody [Translation] Method=nsswitch
Параметр «домен» при этом должен быть одинаковым на всех машинах.
Для автоматического монтирования в /etc/fstab на клиенте следует указывать что-нибудь типа такого:
сервер:шара точка_монтирования nfs4 auto,user,rw,sec=krb5p 0 0
Для экспорта каталога можно использовать следующее (/etc/exports на сервере):
/ gss/krb5p(rw,sync,fsid=0,crossmnt,no_subtree_check) /home gss/krb5p(rw,sync,crossmnt,no_subtree_check,no_root_squash)
Нюанс: экспорт корня (fsid=0) по gss/* обязателен, иначе будет возникать ошибка вида mount.nfs4: mounting failed, reason given by server: No such file or directory
т.к. путь к экспорту не будет находиться сервером.
Параметр sec допускает следующие значения (каждый последующий включает все предыдущие):
Если указана авторизация через цербера, то для доступа к файлам будет обязателен тикет. Локальный рут будет иметь доступ как пользователь nobody (т.к. руту доступен тикет-ключ в keytab’е), но он не сможет читать/писать файлы если их права не позволяют. Менять права локальный рут также не сможет. Полноценный доступ будет только у тех локальных пользователей, у которых есть тикет от цербера.
Вот собственно и все, а напоследок еще несколько ссылок:
Возможные проблемы:
Получение почты через IMAP на примере cyrus:
Почтовые клиенты, которые умеют авторизироваться через gssapi это как минимум thunderbird и kmail. Если у вас есть тикет, то они не должны спрашивать пароль. Для kmail необходимо выбрать этот тип авторизации явно, а для thunderbird (версий до 3.1) поставить галочку «Use secure authentication» в настройках аккаунта. С версии 3.1 появился выбор механизма авторизации, в котором соответственно следует указать Kerberos/GSSAPI.
Отправка через SMTP, exim:
gssapi_sasl_server: driver = cyrus_sasl public_name = GSSAPI server_set_id = $auth1 server_mech = gssapi
Как и с получением, kmail и thunderbird умеют такую авторизацию.
Apache2:
Require valid-user AuthName "Protected area" AuthType Kerberos KrbAuthRealms ДОМЕН Krb5Keytab путь_к_keytab_файлу
Браузеры, которые поддерживают такую авторизацию (Для HTTP она называется SPNEGO, метод авторизации — Negotiate):
Также существует возможность добавить авторизацию через цербера в скриптах на PHP, Ruby, и, наверняка, не только.
auth_param negotiate program /usr/sbin/squid_kerb_auth auth_param negotiate children 10 auth_param negotiate keep_alive on acl auth proxy_auth REQUIRED http_access deny !auth http_access allow auth http_access deny all
С клиентами аналогично http.
А именно авторизация системного логина через цербера, и, соответственно, получения мастер тикета еще при логине.
/etc/pam.d/common-auth: auth sufficient pam_krb5.so minimum_uid=1000 auth required pam_unix.so try_first_pass nullok_secure
/etc/pam.d/common-session: session optional pam_krb5.so minimum_uid=1000 session required pam_unix.so
/etc/pam.d/common-account: account required pam_krb5.so minimum_uid=1000 account required pam_unix.so
/etc/pam.d/common-password: password sufficient pam_krb5.so minimum_uid=1000 password required pam_unix.so nullok obscure min=4 max=8 md5
С указанными настройками для обычных пользователей (с uid не менее 1000) в начале производится попытка авторизации через цербера (с получением мастер тикета), а потом через обычный unix password. Если клиентская машина к инету подключена редко, то порядок строк можно изменить, чтобы в начале проверялся доступ через локальную базу пользователей и паролей. Причем проверка авторизации через цербера будет производиться при любых проверках пользовательского пароля — и для системного логина, и для sudo, и вообще для всего что авторизируется через PAM и включает правило common-auth. Мастер-тикет будет выдаваться тогда, когда в настройках PAM включается правило common-session.
Мне пока не удалось настроить. Из коробки ejabberd не поддерживает gssapi, также не очень понятен статус поддержки клиентами.
Постгря должна быть скомпилирована с поддержкой GSSAPI (по умолчанию в debian это так).
hostssl all all 0.0.0.0/0 gss krb_realm=ДОМЕН hostssl all all ::/0 gss krb_realm=ДОМЕН(соответственно домен надо поставить свой)
Напрямую цербера не поддерживает, однако начиная с версии 5.5 позволяет авторизировать пользователей с помощью плагинов, в частности через PAM, который в свою очередь поддерживает kerberos. Но это конечно совсем не то, чего хотелось бы.
Here be dragons
Во всех вышеперечисленных случаях (кроме PAM, само собой) авторизация будет работать по тикету, не спрашивая пароль.
Список программ не исчерпывающий, т.к. многие программы позволяют авторизироваться через gssapi, что включает и цербера. Еще большее число программ умеет проверять пароль клиента через цербера непосредственно или через RADIUS, правда это не всегда безопасно, т.к. требует передачи пароля по сети.
Возможно позже напишу про LDAP.
Часто возникающие ошибки и проблемы:
Комментарии
Проблемы с SSO на связке SSHd + kerberos
Привет. Я уже несколько дней бьюсь над проблемой связки SSO + SSH + AD. Может вы подскажете что либо путное. Комп я завел в домен и все у меня замечательно. Полные конфиги я выложил тут с подробным вопросом http://opennet.ru/openforum/vsluhforumID10/5370.html
Меня интересует есть ли вообще способ авторизоваться через gssapi, если используется логин вида MARKET\vitto?
Самое удивительное, если префикс MARKET убрать (winbind use default domain = yes в smb.conf), то я могу авторизоваться под доменным vitto, но попаду в учетку локального vitto. Это меня и настораживает - возможно ли вообще передать логин вида MARKET\vitto для авторизации через GSSAPI?
Проблемы с SSO на связке SSHd + kerberos
Тут надо смотреть в сторону маппинга логинов: во первых можно попробовать прямо в цербере завести логины в таком виде (но если уже все заведено и настроено, а проблема только в ssh, то наверное это лишнее). Во вторых поиграться с собственно маппингом, для этого можно попробовать:
* параметр auth_to_local в реалме в krb5.conf, см. например https://superuser.com/questions/808461/cross-realm-kerberos-authenticati...
* создать в домашнем каталоге доменного пользователя файл .k5userok, в котором указать локальное имя пользователя.
Kerberos: NFS и все-все-все
Grundik, не поленился зарегистрироваться и выразить свою благодарность. Спасибо! Отличная статья. Она помогла мне чуть лучше понять принцип работы Kerberos. Сейчас, как раз пытаюсь настроить Kerberos, DNS, DHCP, NFS, Apache и т.п. на Debian 6 (Squeeze) в своей сети.
Материала по Kerberos не очень много, а понятного материала так и вообще почти нет. Документацию читать тяжеловато и там все равно не все описано. Так, что эта статья отличный вклад в общественные знания в области Kerberos.
Появился вопрос. Можно ли пользователю на Windows 7 Home Premium (без поддержки доменов) настроить прозрачный (SSO) доступ к ресурсам в сети на базе Linux (с NFS и CUPS только и без Samba вообще)? Слышал, что есть клиенты NFS для Windows и что MIT или Heimdal Kerberos отличается от Microsoft Kerberos, что вызывает проблемы.
хз
Реализация от MS конечно отличается, но на сколько мне ивестно она совместима с MIT. Как минимум в одну сторону. Но в home версиях винды нет никакой поддержки цербера, только если стороннее ставить. Так что скорее всего настроить можно, но будет это через жопу. И скорее всего через цигвин, что в принципе то же самое.