Linux без /etc/passwd-/etc/shadow (по мотивам обсуждения в Курилке linuxportal.ru) | Версия для печати |
Начинающий администратор Линукса (вроде меня) по мере того как количество серверов находящихся под его контролем увеличивается, а сервисы начинают расползаться по ним, задумывается о том, как бы внедрить систему централизованного учета пользователей, сервисов и хостов. В самом деле - на одном из серверов крутится мэйлер, который выполняет свою работу для пользователей зарегистрированных на его компьютере, а на соседнем - mysqld, которым пользуются те же люди, что и почтой, но сведения о них хранятся в одной из собственных баз данных mysql. Кроме того, основной инструмент администратора - ssh - создает настолько запутанное распределение публичных и частных ключей на этих серверах (как прилежный администратор на каждом из серверов он помимо root-a держит и свой собственный логин, имя и пароль которого не всегда совпадают), что замена адресов на одном из серверов, способна надолго вывести админа из равновесия. passwd: hesiod files group: hesiod files (я считаю, что hesiod должен иметь приоритет перед локальными etc-файлами, но при этом сохраняю их как fallback механизм). Теперь можно приступать к конфигурированию Гесиода. Hesiod Как я уже говорил ранее, Гесиод передает информацию с помощью DNS. Поэтому для того, чтобы использовать Гесиод у вас должен иметься работающий сервер bind. Для нашего игрушечного примера подойдет простейший кэширующий сервер bind (конфигурационные файлы которого идут вместе с дистрибутивом bind). Единственное, что вам нужно будет сделать - это добавить туда еще одну зону, в которой будем хранить информацию Гесиода, и написать для нее файл зоны, плюс пара зон (прямая и обратная) для вашего сетевого интерфейса. Для Гесиода эти две последние зоны не столь важны, но Цербер отказывается запускаться на nonroutable интерфейсе (типа localhost). Если ваш домашний компьютер не подключен к сети, вы можете создать фиктивный ethernet интерфейс [font=Courier]ifconfig dummy0 192.168.192.1 up[/font] (требуется поддержка dummy в ядре). Мой /etc/named.conf выглядит таким вот образом: options { directory "/var/named"; }; zone "." { type hint; file "example/named.ca"; }; zone "localhost" { type master; file "example/localhost.zone"; }; zone "0.0.127.in-addr.arpa" { type master; file "example/named.local"; }; zone "ns.hesiod.info" { type master; file "example/hesiod"; }; zone "myhome.domain" { type master; file "example/myhome.domain"; }; zone "192.168.192.in-addr.arpa" { type master; file "example/myhome.domain.rev"; }; Названия зон не важны - как видите я придумал свой домен myhome.domain и зону Гесиода ns.hesiod.info (совпадать они не обязаны). Файлы зон myhome.domain* в комментариях не нуждаются: $cat /var/named/myhome.domain \$TTL 86400 @ IN SOA ns.myhome.domain. hostmaster.myhome.domain. ( 42 ; serial (d. adams) 3H ; refresh 15M ; retry 1W ; expiry 1D ) ; minimum NS ns ns A 192.168.192.1 $cat /var/named/myhome.domain.rev \$TTL 86400 @ IN SOA myhome.domain. hostmaster.myhome.domain. ( 2004092303 ; Serial 28800 ; Refresh 14400 ; Retry 3600000 ; Expire 86400 ) ; Minimum 1 IN PTR ns.myhome.domain. А зону Гесиода мы добавляем несколько TXT записей, в которых указываем по одной группе и пользователю (только в качестве примера; общее число пользователей и групп, разумеется, не ограничено). Формат этих записей соответствует формату файлов /etc/passwd, /etc/group (заметьте, что этот пользователь и группа должны иметь имена и идентификаторы не используемые локальными пользователями и группами) @ IN SOA serv.hesiod.info hostmaster.hesiod.info ( 42 ; serial (d. adams) 3H ; refresh 15M ; retry 1W ; expiry 1D ) ; minimum IN NS serv ;users info newhesiodusr.passwd TXT "newhesiodusr::2000:1200:test:/:/bin/bash" 2000.uid CNAME newhesiodusr.passwd ;groups definitions hesgr.group TXT "hesgr::1200:" 1200.gid CNAME hesgr.group То что записано после точки в названии Resource Records (гесиодовский тип записи), подсказывает libnss_hesiod как интерпретировать значение этой записи (passwd означает, что в записи указана информация о пользователе, group - о группе). Т.е. в данном примере мы создали пользователя newhesiodusr и группу hesgr к которой принадлежит newhesiodusr. Записи типа CNAME служат в качестве своего рода реверсной зоны для домена Гесиод, с их помощью библиотека hesiod может быстро находить по заданным uid и gid имена пользователей и групп. Помимо использованных в данном примере passwd, group, gid и uid, гесиодовский тип записи может принимать еще несколько предопределенных значений, среди которых интересными на мой взгляд являются две. Запись service может помочь, если вы имеете много нестандартных служб и раздаете их названия через nsswitch (вместо правки локального файла [font=Courier]/etc/services[/font]) - cм. соответствующую запись в nsswitch.conf. Запись filsys дает описание файловой системы (соответствующая Resource Record должно принимать значения вида - <имя файловой системы>,<пользователь>,<точка монтирования>:<параметры монтирования>,<удаленный сервер NFS>:<экспортируемый каталог>). По-видимому, во втором случае удается каким-то образом настроить автомонтирование домашних каталогов пользователей, экспортируемых через NFS - cм. запись automount в nsswitch.conf. Осталось создать конфигурационный файл [font=Courier]/etc/hesiod.conf[/font] (он практически стандартный, поменять вам нужно разве что rhs) rhs=.hesiod.info lhs=.ns , после чего добавить запись о локальном nameserver'e ([font=Courier]nameserver 127.0.0.1[/font]) в [font=Courier]/etc/resolv.conf[/font] (чтобы система могла воспользоваться информацией Гесиода, она, по-крайней мере, должна знать где его искать) и запустить named. Теперь проверим видны ли гесиодовские записи по DNS: $dig TXT hesgr.group.ns.hesiod.info ; <<>> DiG 9.2.2-P3 <<>> TXT hesgr.group.ns.hesiod.info ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51689 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0 ;; QUESTION SECTION: ;hesgr.group.ns.hesiod.info. IN TXT ;; ANSWER SECTION: hesgr.group.ns.hesiod.info. 86400 IN TXT "hesgr::1200:" ;; AUTHORITY SECTION: ns.hesiod.info. 86400 IN NS serv.ns.hesiod.info. ;; Query time: 2 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Oct 2 00:03:40 2004 ;; MSG SIZE rcvd: 89 $ Для упрощения отладки вы можете скачать и установить пакет c Гесиодом с МТИ - там имеется утилитка hesinfo, с которой отслеживать гесиодовские записи нeсколько удобней - печатать меньше. Вот пример: $hesinfo -bl newhesiodusr passwd hes_to_bind(newhesiodusr, passwd) expands to newhesiodusr.passwd.ns.hesiod.info which resolves to newhesiodusr::2000:1200:test:/:/bin/bash $ Помимо этого, очень полезным может оказаться [font=Courier]man hesinfo[/font], где можно почитать о допустимых гесиодовских типах и их значениях. В сущности помимо этой man странички, никакой другой информации о Гесиоде мне найти не удалось. Чтобы окончательно убедится, что Гесиод работает, залогинимся из-под root как newhesiodusr $su Password: #login newhesiodusr Linux 2.4.22. Last login: Птн Окт 1 21:35:39 +0400 2004 on ttyp2. No mail. $id uid=2000(newhesiodusr) gid=1200(hesgr) groups=1200(hesgr) $whoami newhesiodusr $echo $HOME / $echo $SHELL /bin/bash $ Как видите, система не стала спрашивать у вас пароль, а сразу дала вам шелл. Это и неудивительно, так как в записи Гесиода для newhesiodusr был указан пустой пароль. А что будет, если в эту запись добавить пароль ([font=Courier]newhesiodusr:*:2000:1200:test:/:/bin/bash[/font] - после чего необходимо перезапустить named)? Если заглянуть в [font=Courier]/etc/nsswitch.conf[/font], тот ответ становится более или менее понятен - согласно конфигурации nsswitch теневые пароли glibc будет искать в [font=Courier]/etc/shadow[/font] (строка [font=Courier] shadow: compat[/font] - оно же дефолтное значение в случае отсутствия такой строки). Поскольку в shadow ничего про newhesiodusr не сказано, то система откажется его регистрировать. В итоге - у нас остается два варианта: по-прежнему хранить теневые пароли в локальных[font=Courier] /etc/shadow [/font] (что неудобно) или обучить системный login пользоваться услугами централизованной системы аутентификации. Однако во втором случае, несмотря на его очевидное удобство, есть одна серьезная проблема, связанная с безопасностью. Но прежде чем обсуждать ее - еще несколько слов о быстродействии. В нашей игрушечной модели, когда демон named обслуживает только локальные запросы особой потери в скорости наблюдаться не должно. Однако при переносе в реальные условия (один named на локальную сеть), падение скорости может оказаться весьма значительным. Например, файловый менеджер на одном из клиентов Гесиода хочет конвертировать uid/gid владельца файлов (хранимые на файловой системе) в их имена, которые ему придется получать по DNS. Снизить нагрузку на сеть и повысить быстродействие в этом случае можно с помощью локального кэширующего сервера DNS или его облегченного варианта - Name Service Caching Daemon (команда nscd - идет вместе с библиотекой glibc). Настройка nscd гораздо проще настройки сервера DNS, в сущности нужно только указать, запросы какой из nss служб nscd должен кэшировать и параметры кэша (его объем и время жизни). Как Цербер проверяет пользователей Вернемся к вопросу, в чем же состоит основная проблема с удаленной аутентификации пользователей. Наивный подход к построению централизованной системы аутентификации мог бы быть таким - пользователь печатает свой логин и пароль на своем терминале, а потом пароль сверяется с пaролями, хранящимися на сервере. В принципе так работает telnet и именно поэтому от него постепенно отказывются. Прежде чем сравнивать введенный пароль c 'оригиналом', хранящимся на сервере, пароль нужно туда доставить - а сетевые соединения по-умолчанию небезопасны и для серьезного злоумышленника не составит большого труда перехватить пароль в процессе передачи. Таким образом и для серьезной системы аутентификации отсутствие пересылки паролей по сети - непременное условие. В Цербере эта задача решается с помощью системы билетиков (tickets). Если вспомнить о чем шла речь в начале статьи, то процедура аутентификации - это функция от двух переменных (имя, пароль) принимающая значения Истина (пароль соответствует имени и это имя известно Церберу)/ Ложь. Кому именно принадлежит это имя (пользователю,службе) при таком подходе безразлично. Поэтому с точки зрения Цербера любая сетевая служба, пользователь, хост требующие своей аутентификации выглядят совершенно одинаково и называются principals. Каждый принципал имеет имя вида [font=Courier] Аутентификация пользователя в Цербере происходит таким образом: предположим, пользователь хочет зарегистрироваться на компьютере, где установлена программа-логин c поддержкой Kerberos. После того как он вводит в логин свое имя, на Цербер отправляется запрос на билетик для принципала с этим именем. Цербер проверяет имя принципала по своей базе данных, и в случае если имя найдено, генерирует по определенным правилам билетик и отсылает его назад, предварительно закодировав его с помощью пароля этого принципала (вместе с билетиком генерируется еще и шифровальный ключ, который может быть в дальнейшем использован для создания шифрованных каналов для этого пользователя - об этом ниже). Программа логин получает этот закодированный билетик и пытается дешифровать его, используя в качестве ключа пароль пользователя, который он к этому времени уже напечатал. Если пароли не совпадают, вместо нормального билетика после дешифровки получается мусор, и в доступе пользователю отказывают. Если же пользователь успешно зарегистрировался в системе, то билетик вместе с шифровальным ключом записываются в директорию /tmp. Полученный таким образом билетик является не просто билетиком, а "единым проездным'' (ticket-granting ticket или TGT в терминологии Цербера), поскольку при его предъявлении обладатель "проездного'' может получить доступ к другим сетевым службам. Стоит отметить, что срок действия проездного ограничен (как правило - 24 часа), поэтому для его возобновления после этого срока пользователю придется снова вводить пароль и запрашивать Цербер о выдаче билета. А теперь посмотрим, как Цербер разрешает доступ пользователей к сетевым службам. Предположим, пользователь хочет получить письмо с POP сервера и как мэйл-клиент, так и POP-server поддерживают аутентификацию через Цербер. Клиент разыскивает в /tmp проездной пользователя и отправляет проездной на Цербер вместе с запросом на предоставление сервиса (в данном случае запрос является именем принципала, под которым запрашиваемый сервис зарегистрирован на Цербере, типа - [font=Courier]pop/mail.myhome.domain@...[/font]). Если же проездной не найден, то клиент должен предложить пользователю форму для ввода имени и пароля и действовать согласно ранее описанному сценарию. Цербер в ответ генерирует билетик (в случае если он распознает проездной как действительный и находит в своей базе запрашиваемый сервис), добавляет к нему шифровальный ключ, который уже знает обладатель проездного, и отсылает его клиенту в зашифрованном виде (в качестве шифровального ключа используется пароль сервиса). Мэйл-клиент просто передает полученный билетик POP-серверу. Для его расшифровки POP сервер использует свой пароль (пароли сетевых служб хранятся в файле [font=Courier]/etc/krb5.keytab[/font] на локальном диске компьютера, где работает данная служба) и из расшифрованного билетика узнает какой шифровальный ключ он должен использовать при общении с клиентом (т.е. тот же самый, который был выдан вместе с проездным пользователю). Как видите, вместо пароля по сети путешествует только закодированные билетики, пароли же не покидают сервер Цербера и терминала, на котором регистрируется пользователь. Более того, использование билетиков позволяет прозрачно (т.е. незаметно от пользователя) разрешать доступ пользователю к сетевым службам на основании проездного, полученного им при входе в систему.А в качестве побочного эффекта, у вас есть возможность средствами Цербера шифровать траффик между клиентом и сервером. Теперь пора приступать к установке Цербера. Скачиваете исходники с сайта , распаковываете их и запускаете [font=Courier]./configure --prefix=/usr --enable-shared[/font] (второй ключ позволит вам в дальнейшем с меньшей кровью компилировать приложения с поддержкой Kerberos). После чего выполняете стандартный набор команд [font=Courier]make; make install[/font]. Итак Цербер установлен и можно начать запускать его. В этой части я буквально следую рекомендациям install-guide.ps, который упакован вместе с исходниками Цербера, поэтому более подробные разъяснения вы можете прочитать там. Во первых, создаем каталог для хранения баз Цербера [font=Courier]mkdir /usr/local/var/krb5kdc[/font] и, во вторых, сочиняем конфигурационный файл Цербера ([font=Courier]/etc/krb5.conf[/font]) [libdefaults] default_realm=MYHOME.DOMAIN [realms] MYHOME.DOMAIN={ kdc=ns.myhome.domain admin_server=ns.myhome.domain } [logging] kdc=FILE:/var/log/krb5kdc.log admin_server=FILE:/var/log/kadmin.log default=FILE:/var/log/krb5.log Инициализируем базы данных Цербера. #kdb5_util create -r MYHOME.DOMAIN -s Loading random data Initializing database '/usr/local/var/krb5kdc/principal' for realm 'MYHOME.DOMAIN', master key name 'K/M@MYHOME.DOMAIN' You will be prompted for the database Master Password. It is important that you NOT FORGET this password. Enter KDC database master key: <-masterpass Re-enter KDC database master key to verify: <-masterpass # Еще вам нужен файл контроля доступа пользователей к базам данных Цербера, который вам придется написать в любимом текстовом редакторе и поместить в папку /usr/local/var/krb5kdc. В принципе для начала вот такого файла будет достаточно: cat /usr/local/var/krb5kdc/kadm5.acl */admin@MYHOME.DOMAIN * *@MYHOME.DOMIAN cil *1/admin@MYHOME.DOMAIN */*@MYHOME.DOMIAN i Смысл такого файла состоит в том, что принципалам с instance admin даны все права по модификации базы данных Цербера, любому принципалу дается возможность менять пароль и получать данные о принципалах с тем же именем и instance admin (с помощью команд [font=Courier]kadmin[/font], [font=Courier]kadmin.local[/font]), и любой принципал может просматривать данные o полученных им билетиках (команда [font=Courier]klist[/font]). После чего добавим в базу Цербера его администратора: #kadmin.local Authenticating as principal mike/admin@MYHOME.DOMAIN with password. kadmin.local: addprinc admin/admin@MYHOME.DOMAIN WARNING: no policy specified for admin/admin@MYHOME.DOMAIN; defaulting to no policy Enter password for principal "admin/admin@MYHOME.DOMAIN": adminpass Re-enter password for principal "admin/admin@MYHOME.DOMAIN": adminpass Principal "admin/admin@MYHOME.DOMAIN" created. kadmin.local: Теперь все готовo для запуска демона аутентификации krb5kdc и сервиса удаленного администрирования Цербера kadmind. Демон kadmind необязателен, если мы собираемся администрировать Цербер с локального компьютера с помощью kadmin.local. #krb5kdc #tail /var/log/krb5kdc.log Sep 25 07:27:20 ns krb5kdc[464](info): setting up network... Sep 25 07:27:20 ns krb5kdc[464](info): listening on fd 6: udp 192.168.192.1.750 Sep 25 07:27:20 ns krb5kdc[464](info): listening on fd 7: udp 192.168.192.1.88 Sep 25 07:27:20 ns krb5kdc[464](info): set up 2 sockets Sep 25 07:27:20 ns krb5kdc[465](info): commencing operation #kadmind #tail /var/log/kadmin.log Sep 25 07:28:44 ns kadmind[467](info): Seeding random number generator Sep 25 07:28:44 ns kadmind[467](info): No dictionary file specified, continuing without one. Sep 25 07:28:44 ns kadmind[468](info): starting # Теперь нам нужно добавить двух принципалов - сам хост, на котором работает Цербер, со случайно выбранным ключом в качестве пароля (помните я говорил, что хосты и служжбы с точки зрения Цербера ничем не отличаются от обычныз пользователей), и нашего newhesiodusr. #kadmin -r MYHOME.DOMAIN -p admin/admin Authenticating as principal admin/admin with password. Password for admin/admin@MYHOME.DOMAIN: adminpass kadmin: addprinc -randkey host/ns.myhome.domain WARNING: no policy specified for host/ns.myhome.domain@MYHOME.DOMAIN; defaulting to no policy Principal "host/ns.myhome.domain@MYHOME.DOMAIN" created. kadmin: addprinc newhesiodusr WARNING: no policy specified for newhesiodusr@MYHOME.DOMAIN; defaulting to no policy Enter password for principal "newhesiodusr@MYHOME.DOMAIN": hesiodpass Re-enter password for principal "newhesiodusr@MYHOME.DOMAIN": hesiodpass Principal "newhesiodusr@MYHOME.DOMAIN" created. kadmin: # Вообщем-то все. Чтобы войти в систему под именем newhesiodusr с паролем из базы данных Цербера, нам нужно воспользоваться керберизованным аналогом системной команды [font=Courier]login[/font] из дистрибутива Цербера ([font=Courier]login.krb5[/font]). Теперь ввод пароля работает! #login.krb5 login: newhesiodusr Password for newhesiodusr: newhesiodusr: Kerberos password incorrect Login incorrect login: newhesiodusr Password for newhesiodusr: Last login: Sat Sep 25 07:57:30 on ttyp2 Linux 2.4.22. $whoami newhesiodusr $id uid=2000(newhesiodusr) gid=1200(hesgr) groups=1200(hesgr) Итоги Еще раз напоминаю, что в этом тексте рассматривается только проверка идеи построения системы с централизованной регистрацией пользователей. По крайней мере на одном отдельном компьютере она работает. Перенос же модели в реальное сетевое окружение требует решения еще нескольких задач, на которые стоит обратить внимание. Во-первых, следует иметь ввиду возможность сбоя в сети - обрыв линии связи, выход из строя компьтеров, на которых работают Цербер и/или Гесиод. В таком случае ни на один из компьютеров локальной сети залогиниться не удасться. Тут можно предложить, во-первых, установить backup сервера (slave серверы DNS для Гесиода и дополнительные Kerberos Domain Controllers), и, во-вторых, иметь альтернативный вход в компьютер под локальным пользователем с локальным паролем (по крайней мере для root). На мой взгляд второй вариант можно осуществить переключеним runlevels при старте системы. Скажем, для стандартного входа в систему (runlevel 3) мы имеем запись в /etc/inittab вида: [font=Courier]c1:3:respawn:/sbin/agetty -l login.krb5 38400 tty1 linux[/font] с регистрацией в Цербере, а для экстренных случаев сохраням обычный логин [font=Courier]c1:125:respawn:/sbin/agetty 38400 tty1 linux[/font], причем в /etc/passwd - /etc/shadow для таких случаев держим минимальный набор системных пользователей и групп (достаточно ли будет одного root'a?). Теперь о недостатках. Главный недостаток - сложная интеграция Kerberos c Linux. Как видно из примера с мэйл-клиентом и POP-сервером, чтобы приложение, требующее аутентификации пользователя, могло воспользоваться услугами Цербера, в исходном коде программы автором должна быть заложены вызовы соответствующих функций Цербера, причем это справедливо как для серверной, так и клиентской частей приложения. На практике (т.е. для системного администратора) это означает необходимость патчить, искать kerberized аналоги или (в лучшем случае) перекомпилировать программы с определенными опциями (конечно же администратор может отказаться от полной керберизации ситемы, и продолжать использовать программы имеющие свои собственные базы паролей/пользователей, например samba с ее smbpasswd или mysql с его таблицей mysql.user). Керберизованные стандартные сетевые утилиты и сервисы (r*-службы, telnet, ftp и соотвтествующие демоны) присутствуют в пакете Керберос от MIT. Для NFS специальной авторизации не требуется, т.к. она контролирует доступ к файлам по системным uid/gid, полученных пользователем при входе в систему. Использование Гесиода позволяет сделать uid/gid одинаковыми для всей сети, поэтому в случае с NFS у вас автоматически решаются проблемы с доступом к разделяемым ресурсам с разных компьютеров (в классическом варианте требуется ручная синхронизация /etc/passwd на всех компьютерах в сети). Что касается других сетевых приложений (почта, сетевая файловая система, сервер баз данных...), то следует внимательно читать Release notes интересующей вас программы, чтобы понять возможна ли ее интеграция с Цербером. По моему мнению, ни samba, ни mysql керберизации не поддаются, так что, возможно, вам придется искать им замену (Coda и PostgresSQL?). Другая возможность керберизации приложений - это организовать обращение к Церберу через модули PAM. Но это применимо в случае, если инфраструктура PAM уже присутствует в вашем дистрибутиве (ее нет например в Slackware), иначе pam-ификация дистрибутива окажется занятием не менее сложным, чем его керберизация. Какие именно сетевые приложения можно использовать в рамках керберизованной системы я собираюсь расказать во второй части этой статьи. Благодарности Автор благодарит пользователей ЛинуксПортала, принявших участие в обсуждении этой темы (Logvinon,XMan,JoeUser,kaboom,Dr.Spectre) Опубликовал: geekkoo |