суббота, 2 апреля 2011 г.

Аутентификация в apache используя Active Directory и kerberos

Почти в каждой организации используется домен Microsoft Windows, в котором пользователи проходят проверку подлинности. Так же часто в IT инфраструктуре используются сервисы, предоставляемые различными дистрибутивами linux. При выдаче прав доступа администраторам windows и linux приходится вести различные базы пользователей, что конечно не удобно. Реализовав единую базу данных пользователей и прозрачную аутентификации для пользователей (single sign on) можно избавится от массы рутинной работы и устранить риски безопасности. В данном случае реализуем прозрачный доступ пользователей к некому web ресурсу. Для аутентификации будет использоваться протокол Kerberos и "Key Distribution Center" (KDC) реализованный в контроллере домена Windows. В качестве linux системы рассматривается rhel5, для других дистрибутивов возможны не принципиальные отличия в процессе настройки. Если у вас дистрибутив отличный от указанного, то стоит проверить версию библиотеки Kerberos, она должна быть не младше чем 1.5 (MIT Kerberos), т.к. начиная с этой версии поддерживается механизм согласования метода аутентификации SPNEGO (Simple and Protected Negotiate). Веб сервер должен иметь A запись на вашем днс сервере т.к. имя ресурса является частью Kerberos билета. Процесс аутентификации описан в RFC1510, обязательно прочтите как проходит процесс аутентификации.

Термины и команды:
realm - область использующая единую базу Kerberos. По соглашению реалм записывается строчными буквами, для отличия от днс домена.
principal - имя которому поставлено в соответствие набор учетных данных. Делится на три части: 1)primary - первая чать принципала Kerberos. Если это пользователь, то соответствует его имени. Если сервис - имя сервиса. 2)instance - вторая часть, служит для уточнения первой части. Может не содержатся в имени принципала, если есть - то это описание. В случае хоста - его fqdn. 3)realm - реалм идет последней частью.
ticket - набор временных данных которые подтверждают идентичность клиента или сервиса.
TGT - Ticket-Granting Ticket. Билет дающий право на получение других билетов в реалме, где был он выпущен.
keytab - файл содержащий ключи, хост или сервис использует его точно таким же образом как пользователь использует пароль.
KDC - Key Distribution Center, сервер выдающий билеты.
kinit - программа, используется для начала процесса аутентификации принципала и получения билета TGT.
klist - программа, выводит список принципалов и Kerberos билетов содержащихся в кеше, или список список ключей в keytab файле.
kvno - получает билет для указанного принципала и выдает на терминал версию ключей.
ktutil - позволяет управлять записями в keytab файле.

Начальные условия:
локальная сеть - 192.168.1.0/24
сервер Active Directory - dc01.domain.ru(192.168.1.1)
веб сервер - web.domain.ru (192.168.1.130)

Действия по шагам:
Настраиваем синхронизацию времени. 
Установите и настройте службу ntpd. В качестве сервера точного времени нужно использовать сервер Active Directory. Протокол Kerberos требует что бы время у участников аутентификации было синхронизировано.

[root@server ~]# yum install ntpd

Выполните начальную синхронизацию времени с контроллером домена:

[root@server ~]# ntpdate dc01.domain.ru

Конфигурационный файл даемона ntpd:

[user@server ~]$ egrep -v "^#" /etc/ntp.conf
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict -6 ::1
server dc01.domain.ru
server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10
driftfile /var/lib/ntp/drift
keys /etc/ntp/keys

Сейчас запустим службу и поставим ее в автозагрузку:

[root@server ~]# /etc/init.d/ntpd start
[root@server ~]# chkconfig ntpd on

Проверить состояние службы синхронизации времени можно командой:

[user@server ~]$ ntpstat
synchronised to NTP server (192.168.1.1) at stratum 5
   time correct to within 300 ms
   polling server every 512 s

Настройка Kerberos на web.domain.ru.
Ниже приведена минимальная конфигурация для использования протокола аутентификации в реалме domain.ru. Реалм в данном случае будет совпадает с доменом Windows. Обратите внимание, для работоспособности Kerberos, реалм должен быть написан прописными буквами!

[user@server ~]$ cat /etc/krb5.conf
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = DOMAIN.RU
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 forwardable = yes

[realms]
 DOMAIN.RU = {
  kdc = dc01.domain.ru
  admin_server = dc01.domain.ru
 }

[domain_realm]
 .domain.ru = DOMAIN.RU
 domain.ru = DOMAIN.RU

[appdefaults]
 pam = {
   debug = false
   ticket_lifetime = 36000
   renew_lifetime = 36000
   forwardable = true
   krb4_convert = false
 }

Если у вас в сети несколько контроллеров домена то вы можете их перечислить в секции [realms], что то вроде:

[realms]
 DOMAIN.RU = {
  kdc = dc01.domain.ru
  kdc = dc02.domain.ru
  admin_server = dc01.domain.ru
  admin_server = dc02.domain.ru
 }

Проверить работоспособность Kerberos можно с помощью kinit, и учетной записи в домене Windows. Данная команда позволяет для принципала (в данном случае для пользователя домена) получить TGT билет и поместить его в кеш. Содержимое кеша можно посмотреть командой klist:

[user@server ~]$ kinit domain_user@DOMAIN.RU
[user@server ~]$ klist

Ticket cache: FILE:/tmp/krb5cc_500
Default principal: domain_user@DOMAIN.RU

Valid starting     Expires            Service principal
03/22/11 17:43:35  03/23/11 03:43:38  krbtgt/DOMAIN.RU@DOMAIN.RU
renew until 03/23/11 17:43:35

Далее нам нужно создать аккунт сервера в в Active Directory и связать его с принципалом сервиса  в KDC. Можно сделать это самостоятельно на котроллере домена. Создать сначала аккаунт, а затем связать его с принципалом с помощью команды ktpass. Но мне больше нравится вариант с установкой samba и вводом сервера в домен, в этом случае аккаунт и принципал службы создаются автоматически. Как плюс, samba позволит нам в будущем организовать сетевые ресурсы и получать информацию из AD для разграничения доступа к службам сервера.

Настройка samba, добавление сервера web.domain.ru в домен Windows
Устанавливаем samba:

[root@server ~]# yum install samba

В конфигурации samba необходимо указать используемый реалм, указать что будет используется keytab файл, и указать что самба работает как член домена AD - параметр security=ads. Конфигурация samba достаточная для наших целей приведена ниже:

[root@server ~]# cat /etc/samba/smb.conf
[global]
workgroup = DOMAIN
realm = DOMAIN.RU
server string = Samba Server Version %v
security = ADS
passdb backend = tdbsam
 use kerberos keytab = Yes
local master = No
cups options = raw

Проверить правильность конфигурационного файла можно командой 

[root@server ~]# testparm

Если ошибок нет, то самое время добавить наш сервер в домен Windows, естественно что нужно это делать имея полномочия на добавление в домен:

[root@server ~]# net ads join -U win_admin
win_admin's password:
Using short domain name -- DOMAIN
Joined 'WEB' to realm 'DOMAIN.RU'

Если днс зона на контроллере домена не обновилась, то можно или вручную добавить запись A типа и ассоциированную с ней запись PTR или попытатся провести регистрацию имя сервера в днс следующим образом:

[root@server ~]# net ads dns register -I 192.168.1.130 -U win_admin

Проверить корректность добавления сервера в домен можно следующим образом:

[root@server ~]# net ads testjoin
Join is OK

Создание файла keytab, добавление ключа принципала сервиса "HTTP" в keytab.
Создадим keytab файл. Так как в конфигурации samba не оговорено где должен содержатся keytab файл, то будет создан файл по умолчанию /etc/krb5.keytab:

[root@server ~]# net ads keytab create -U win_admin

Теперь создадим и добавим принципал для сервиса - "HTTP", Если вы сейчас посмотрите, на контроллере домена, через консоль MMC и остнастку ADCI Edit параметр "servicePrincipalName", какие принципалы сервисов созданы для нашего сервера - это будут: "HOST/web.domain.ru" и "HOST/web".

[root@server ~]# net ads keytab add HTTP -U win_admin

Если вы теперь посмотрите в список принципалов, то заметите, что там добавились еще два - "HTTP/web.domain.ru" и "HTTP/web". В принципе это уже значит что добавление прошло успешно. Тем не менее, давайте посмотрим что сейчас находится в keytab:

[root@server ~]# klist -ek /etc/krb5.keytab 
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   2 host/web.domain.ru@DOMAIN.RU (DES cbc mode with CRC-32) 
   2 host/web.domain.ru@DOMAIN.RU (DES cbc mode with RSA-MD5) 
   2 host/web.domain.ru@DOMAIN.RU (ArcFour with HMAC/md5) 
   2 host/web@DOMAIN.RU (DES cbc mode with CRC-32) 
   2 host/web@DOMAIN.RU (DES cbc mode with RSA-MD5) 
   2 host/web@DOMAIN.RU (ArcFour with HMAC/md5) 
   2 WEB$@DOMAIN.RU (DES cbc mode with CRC-32) 
   2 WEB$@DOMAIN.RU (DES cbc mode with RSA-MD5) 
   2 WEB$@DOMAIN.RU (ArcFour with HMAC/md5) 
   2 HTTP/web.domain.ru@DOMAIN.RU (DES cbc mode with CRC-32) 
   2 HTTP/web.domain.ru@DOMAIN.RU (DES cbc mode with RSA-MD5) 
   2 HTTP/web.domain.ru@DOMAIN.RU (ArcFour with HMAC/md5) 
   2 HTTP/web@DOMAIN.RU (DES cbc mode with CRC-32) 
   2 HTTP/web@DOMAIN.RU (DES cbc mode with RSA-MD5) 
   2 HTTP/web@DOMAIN.RU (ArcFour with HMAC/md5) 

Для полной уверенности можно получить Kerberos билет от KDC для только что заведенных принципалов:

[root@server ~]# kvno HTTP/web.domain.ru@DOMAIN.RU HTTP/web@DOMAIN.RU

HTTP/web.domain.ru@DOMAIN.RU: kvno = 2
HTTP/web@DOMAIN.RU: kvno = 2

Обратите внимание, что версия ключа идентична. Посмотрим эти билеты подробнее (в выводе только интересующие нас билеты):

[root@server ~]# klist -e
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: domain_user@DOMAIN.RU

Valid starting     Expires            Service principal
03/25/11 15:37:04  03/26/11 01:35:17  HTTP/web.domain.ru@DOMAIN.RU
renew until 03/26/11 15:35:14, Etype (skey, tkt): ArcFour with HMAC/md5, ArcFour with HMAC/md5 
03/25/11 15:42:26  03/26/11 01:35:17  HTTP/web@DOMAIN.RU
renew until 03/26/11 15:35:14, Etype (skey, tkt): ArcFour with HMAC/md5, ArcFour with HMAC/md5

Обратите внимание что номера ключей билетов (колонка KVNO), имя принципала в билете и алгоритмы шифрования должны совпадать! Рекомендуется создать свой keytab для службы HTTP, где будет содержатся только нобходимые нам ключи. Сделать это можно с помощью ktutil. Расширеных функций редактирования он не поддерживает, поэтому его можно запустить через rlwrap:

[root@server ~]# rlwrap ktutil

Загрузим содержимое keytab

ktutil:  read_kt /etc/krb5.keytab

Посмотрите текущие записи:

ktutil:  list

Нас интересуют записи в которых фигурирует метка "HTTP". Удалите все лишние записи, указав в команде удаления ненужный слот записи:

ktutil:  delent 1

Должно получится так:

ktutil:  list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    2                  HTTP/web.domain.ru@DOMAIN.RU
   2    2                  HTTP/web.domain.ru@DOMAIN.RU
   3    2                  HTTP/web.domain.ru@DOMAIN.RU

Сохраним оставшиеся в другой keytab файл:

ktutil:  write_kt /etc/httpd/httpd.keytab

Сменим права доступа:

[root@server ~]# chown apache:apache /etc/httpd/httpd.keytab
[root@server ~]# chmod 0440 /etc/httpd/httpd.keytab

Переходим к заключительной части.

Установка и настройка mod_auth_kerb.
Установим модуль mod_auth_kerb:

[root@server ~]# yum install mod_auth_kerb

Вы обнаружите файл /etc/httpd/conf.d/auth_kerb.conf содержащий пример настройки mod_auth_kerb. Воспользуемся этим примером как отправной точкой. В примере ниже примере аутентификация требуется только к части сайта web.domain.ru/private. Параметр KrbServiceName должен содержать имя принципала сервиса (и соответственно ключ), которое будет использовать apache для аутентификации. На место расположения файла keytab указывает параметр Krb5KeyTab. Используйте SSL если вы включите параметр KrbMethodK5Passwd. Данный параметр  включает аутентификацию с поддержкой ввода логин/пароль, причем они будут посланы по сети практически чистым текстом ( кодировка Base64 очень слабая )

[root@snort conf.d]# cat /etc/httpd/conf.d/auth_kerb.conf

LoadModule auth_kerb_module modules/mod_auth_kerb.

<Location /private>
#  SSLRequireSSL
  AuthType Kerberos
  AuthName "Kerberos Login"
  KrbMethodNegotiate On
  KrbMethodK5Passwd Off
  KrbAuthRealms DOMAIN.RU
  Krb5KeyTab /etc/httpd/httpd.keytab
  KrbServiceName HTTP
#  require user win_user@DOMAIN.RU win2_user@DOMAIN.RU
  require valid-user
</Location>

Такой вариант настройки не очень удобен в плане гибкости. Гораздо удобнее настроить аутентификацию в .htaccess файле. Прежде чем будете пробовать второй пример - приведите к первоначальному виду файл /etc/httpd/conf.d/auth_kerb.conf, т.е. все закоментированно кроме строчки с загрузкой модуля.

[root@snort ~]# cat /var/www/html/.htaccess
#SSLRequireSSL
AuthType Kerberos
AuthName "Kerberos Login"
KrbMethodNegotiate On
KrbMethodK5Passwd Off
KrbAuthRealms DOMAIN.RU
Krb5KeyTab /etc/httpd/httpd.keytab
KrbServiceName HTTP
#require user win_user@DOMAIN.RU win2_user@DOMAIN.RU
require valid-user

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

Настройка интернет браузеров.
Начнем с internet explorer 8. Во вкладке "Безопасность" окна "Свойства обозревателя" выделите "Местная интрасеть" и нажмите на "Узлы".


В появившемся окне нажмите "Дополнительно"


Впишите свой домен как на примере:


Закройте окно, и нажмите на кнопку "Другой" в области "Уровень безопасности для этой зоны". Отметьте параметр автоматического входа в систему как показано на рисунке.


Теперь в окне "Свойства обозревателя" перейдите во вкладку "Дополнительно", и включите параметр "Разрешить встроенную проверку подлинности Windows". Для того что бы настройки вступили в силу, браузер необходимо перезапустить.



Перейдем к настройке Mozilla Firefox, здесь все проще и без перезапусков. Наберите в адресной строке "about:config", в строке фильтра - "network.neg". Впишите свой домен в две строки, как показано на рисунке.




14 комментариев:

  1. В случае, если в сети используются короткие имена (без имени домена), прописывание имени домена ничего не дает. Требуется прописывать каждый сервер через запятую.
    Чтобы этого избежать, нужно дать возможность аутентифицироваться на любом сервере, установив параметры network.negotiate-auth.delegation-uris и network.negotiate-auth.trusted-uris в значение http://,https://

    ОтветитьУдалить
  2. Не совсем вас понял. По короткой ссылке типа http://web - все корректно работает. Тикет, при этом. запрашивается на полное имя принципала.

    ОтветитьУдалить
  3. какой дистрибутив использовался при установке - CentOS, Fedora???

    ОтветитьУдалить
  4. Val.Khmyrov, у меня работает только если перечислить все серверы, либо с указанием http://,https://.
    В чем может быть проблема?

    ОтветитьУдалить
  5. sochi, такое поведения и для ie и для firefox'а?

    ОтветитьУдалить
  6. Val.Khmyrov для ie работает без дополнительных настроек.
    Для ff хоть под win, хоть под lin, нужно прописывать вышеприведенные ключи в конфиге.

    ОтветитьУдалить
  7. sochi, В данном случае ff не производит согласование протокола авторизации, потому что при использовании короткого имени, оно не попадает в шаблон в параметрах network.negotiate-auth.delegation-uris и network.negotiate-auth.trusted-uris (domain.ru). Т.е. вписывая короткое имя, тем самым мы включаем процесс согласования.

    ОтветитьУдалить
  8. Для чего здесь Samba? Это же обычный KDC, Samba вообще здесь не нужна.

    ОтветитьУдалить
  9. winterheart,samba нужна для создания принципала в KDC, создания учетки в LDAP и их взаимного связывания. В принципе ее можно удалить после настройки.

    ОтветитьУдалить
  10. Этот комментарий был удален автором.

    ОтветитьУдалить
  11. Keytap можно создать на сервере c AD, а потом скинуть его на web-сервер. Тогда samba вообще ставить не придется.

    ОтветитьУдалить
  12. При использовании kerberos авторизации samba не нужна, в этом и вера состоит что бы без ввода в домен linux srv использовать все прелести AD.

    ОтветитьУдалить
  13. Помимо apache я использую AD для ssh и sudo. Разграничение прав доступа через группы в AD. Так что мне samba нужна.

    ОтветитьУдалить