ВСЕВОЛОД СТАХОВ
TACACS
В данной статье описываются основные принципы настройки сервера и клиента (терминального сервера фирмы Cisco или иной компании) TACACS+. TACACS имеет очень широкое применение, так как может обеспечивать работу всех клиентов с единым сервером авторизации, который также позволяет настраивать привилегии различных пользователей в широких пределах, например: давать определённым пользователям доступ только к определённым командам, давать определённым лицам пользоваться различными сервисами только с заданных адресов, организовывать группы пользователей, вести лог-файл доступа пользователей (это особенно важно для маршрутизаторов Cisco, так как позволяет определить, кто и сколько пользовался определёнными сетевыми службами: ppp, slip и т. д.), выполнять для пользователей определённые команды UNIX.
Но прежде чем начинать разговор о настройке TACACS, я бы хотел определиться с терминологией:
- TACACS (terminal access controller access control system) – собственно, система управления авторизацией и аутентификацией.
- NAS (network access server) – клиент tacacs, киска. Киской в данной статье я буду называть терминальный сервер (интеллектуальный коммутатор или маршрутизатор) фирмы Cisco. Хотя в принципе с протоколом TACACS+ могут работать маршрутизаторы и других фирм.
- AV (attribute=value) – пары атрибут=значение, которые передаются между клиентом и сервером tacacs.
Теперь необходимо скачать сам сервер для *nix. Обитает он здесь: ftp://ftpeng.cisco.com/pub/tacacs (сервер ftp очень кривой, по нему особо не пороешься: не видно каталогов), к сожалению, только альфа-версия, но, похоже, из состояния альфа он не выберется никогда, т.к. сама Cisco его не поддерживает (что весьма странно) и отказывается от «любой ответственности». «Альфанутость» tacacs_plus-сервера мне довелось прочувствовать на собственной шкуре: пришлось его маленько доработать, для того чтобы он начал выполнять свои функции. Итак, вначале правим Makefile: по умолчанию раскомментированы настройки для Solaris.
# For Solaris (SUNOS 5.3, 5.4, 5.5, 5.6) uncomment the following two lines
OS=-DSOLARIS
OSLIBS=-lsocket -lnsl
Выбираем нужную ОС и раскомментируем нужные строчки:
# For LINUX
OS=-DLINUX
#
# On REDHAT 5.0 systems, or systems that use the new glibc, you might instead need the following:
OS=-DLINUX -DGLIBC
OSLIBS=-lcrypt
Добавляем пользователя и группу для сервера, пишем в Makefile UID и GID (по умолчанию эти строки закомментированы, запуск идёт от рута, что не есть хорошо, особенно для альфа-версии):
USERID = 1500
GROUPID = 25
FLAGS = -DTAC_PLUS_USERID=$(USERID) -DTAC_PLUS_GROUPID=$(GROUPID)
Указываем pid-файл:
# On startup, tac_plus creates the file /etc/tac_plus.pid (if possible), containing its process id.
# Uncomment and modify the following line to change this filename
PIDFILE = -DTAC_PLUS_PIDFILE="/var/run/tac_plus.pid"
При компиляции у меня возникли ещё две небольшие проблемы:
- все сырцы были записаны в формате DOS, поэтому пришлось вначале написать простенький скрипт:
#!/bin/sh
for i in *
do
tr -d " " < $i > .tmp
mv -f .tmp $i
rm -f .tmp
done
- возникли некоторые проблемы с описанием syserrorlist, которые, впрочем, решаются просто удалением соответствующих строчек.
Решив эти проблемы, я спокойно скомпилировал tacacs+ в NetBSD 1.5.2 компилятором egcc 1.1.2. Под Linux&gcc 2.96 также всё прошло нормально, поэтому я не вижу причин, чтобы на других машинах возникали ошибки компиляции (если возникли, то прежде всего проверьте Makefile).
Естественно, что после компиляции необходимо запустить и настроить сервер. Запускается он так:
- -C имя конфигурационного файла (обязательный параметр)
- -t не использовать log-файл, а писать в stderr
- -P проверка синтаксиса конфигурационного файла
- -g режим отладки, не происходит создания дочерних процессов
- -p port_number задание номера порта (по умолчанию tacacs+ использует 49)
- -d уровень вывода отладочных сообщений в /var/tmp/tac_plus.log
- -v вывести версию и выйти
- -L (получать имена по DNS)
- -l файл для ведения лога
- -w файл для записи журнала доступа (при включенной опции maxsess, по умолчанию – /var/tmp/tac.who_log)
- -i запуск через inetd
Пример:
tac_plus -C /etc/tacacs.config
После пробного запуска заносим нужные строчки в системные rc-файлы (хотя я бы посоветовал для начала использовать режим inetd).
Но без конфигурационного файла сервер не работает, поэтому настало самое время описать его синтаксис. Все значения записываются в формате атрибут=значение (AV-пары), если прописываются дополнительные параметры атрибутов, то они заключаются в фигурные скобки {}, символы # считаются началом однострочного комментария. Принцип построения конфигурационного файла таков: вначале задаётся ключ симметрического шифрования, осуществляемого между киской и tacacs-сервером. Этот ключ имеет аналогичное паролю значение (берётся его md5-хеш), поэтому он может содержать нормальные символы (символ " употреблять нельзя, т.к. это приведёт к ошибке работы шифрации, а экранировать его нет возможности). После определения ключа описываются группы, в которых можно определить общие права и параметры доступа всех пользователей в группе. Также обычно определяют пользователей, входящих в определённые группы (пользователь может принадлежать только одной группе). Для указания того, что пользователь или группа входят в определённую группу, в их описании необходимо использовать member=group_name. Приведу всё это на примере:
# Ключ для шифрования
key = a very secret password
group users{
# Задание пароля для всех пользователей группы пользователей в открытом виде. Можно использовать
# DES-шифрование, например: login = DES F5qT7Ha7AflP0 или указать файл в формате passwd:
# login = file /etc/tacacs_passwd, но учтите, что пока tac_plus не работает с md5-паролями, так что в этом
# файле все пароли должны быть зашифрованы методом DES
login = cleartext users_password
}
user user1{
# Пользователь принадлежит группе и наследует все параметры из определения группы, включая пароль
member = users
}
user power_user{
# Переопределение атрибута группы
login = des F5qT7Ha7AflP0
member = users
}
user lamer{
# А этот, видимо, и пароль ввести сам не может :)
login = nopassword
member = users
}
Важное замечание: если пароль указывается из файла (file path_to_file), то необходимо преобразовать стандартный файл формата passwd в формат tacacs (tacacs считает номер группы номером списка прав доступа acl). Для этого используется поставляемая утилита convert.pl -g .
Группы tacacs могут являться членами других групп, наследуя все атрибуты контейнера. Учтите, что файл конфигурации tacacs содержит некоторые пароли в незашифрованном виде, поэтому надо обязательно выполнить правильный chmod 0400 для пользователя, под которым работает tacacs. Кроме этого, для аутентификации можно использовать несколько дополнительных весьма полезных параметров:
- expires = «Month_short DD YYYY» – конец работы данной учётной записи. Пользователь получает предупреждение за 14 дней до cрока, например: expires = «JAN 12 2003» (регистр не имеет значения, не забудьте про кавычки);
- arap = cleartext arap_pass – пароль для arap;
- chap = cleartext chap_pass – пароль для chap-соединений (нельзя использовать шифрование);
- ms-chap = cleartext ms-chap_pass – пароль для ms-chap (если tacacs был собран с поддержкой этого протокола), если не был «получен ms-chap ключ от Microsoft», то работать можно только с cleartext-паролями;
- pap = cleartext pap_pass – пароль для входящих pap-соединений, его можно шифровать DESom;
- opap = cleartext opap_pass – пароль для исходящих pap-соединений (работает аналогично предыдущему).
В Cisco IOS также предусмотрен ряд специальных пользователей, соответствующих уровням доступа к системе (enable), их имена выглядят следующим образом: $enab$, где – требуемый уровень доступа к системе (имеется также пользователь $enable$ для старых версий IOS). Приведу простой пример всему вышесказанному (комментарии, думаю, будут излишни):
user admin{
login = des FgZq2fY7ZKP0l
pap = des FgZq2fY7ZKP0l
opap = des FgZq2fY7ZKP0l
expires = "JAN 01 2010"
}
user user1{
login = cleartext user_pass
pap = pap_user_pass
expires = "JAN 01 2003"
}
user $enab15${
login = des Y7jk9zAd5F7Ix
}
user $enab1${
login = cleartext level1secret
}
Сродни процессу аутентификации на сервере tac_plus, можно управлять процессом авторизации, т.е. предоставления пользователям определённых прав и запретов на использование команд или протоколов. Для определения прав авторизации используются регулярные выражения стиля grep (точнее, egerp, что позволяет использовать логические операции) и ключевые слова permit (разрешить) и deny (запретить). По умолчанию всё, что не разрешено, – запрещено. Это можно изменить, указав разрешения по умолчанию:
- default authorization = permit – на глобальном уровне, разрешить все по умолчанию;
- default service = permit – на уровне пользователя, разрешить все по умолчанию для данного пользователя;
- default attribute = permit – на уровне описания сервиса, разрешить всё по умолчанию.
В процессе авторизации ключевыми являются три понятия: сервис (например, сервисы exec, slip, ppp, arap, shell, tty-daemon, connection, system), команда (например, telnet) и протокол. Приведу пример с комментариями:
user=admin {
login = des 3EdghJk8acVB6
member = administrators
# Разрешаем всё на уровне пользователя
default service = permit
# Описание сервиса выполнения команд exec
service = exec {
# Устанавливаем список прав доступа для данного пользователя
acl = 4
# Выполняем команду при авторизации(автокоманда)
autocmd = "telnet 192.168.1.2"
}
cmd = telnet {
# Разрешаем все telnet-соединения, кроме адреса 131.108.13.*
deny 131.108.13.[0-9]+
permit .*
}
}
user=alex {
login = des 6EX027bHtSTlz
name = "Alex"
member = administrators
expires = "May 23 2005"
arap = cleartext "arap secret"
chap = cleartext "chap secret"
service = exec {
# Уровень привилегий по умолчанию
acl = 5
# Автопинг
autocmd = "ping 192.168.1.2"
}
}
В качестве команд могут использоваться любые команды IOS обычного режима (т.е. до enable). Список параметров, которые могут использоваться внутри определений авторизации, весьма широк:
- acl – список прав доступа (только при service=shell или service=exec);
- addr – сетевой адрес для service=ppp и protocol=ip;
- autocmd – только при service=shell или service=exec – автоматическое выполнение определённой команды IOS;
- callback-dialstring – номер телефона для service=ppp или shell;
- callback-line – номер линии;
- dns-server – IP-адреса серверов DNS через пробел, передаваемых клиентам PPP (service=ppp, protocol=ip);
- idletime (11.1) – время в минутах до завершения неактивной сессии (не применимо к PPP);
- inacl – определяется входной уровень доступа и применяется к интерфейсу на время сеанса (service=ppp, protocol=ip);
- interface-config – значением является любая команда конфигурации интерфейса;
- ip-addresses – возможные значения IP-адресов для конца туннеля (service=ppp and protocol=vpdn);
- link-compression – использовать ли алгоритм сжатия STAC:
- 0 – нет
- 1 – Stac
- 2 – Stac-Draft-9
- 3 – MS-Stac.
- load-threshold – порог нагрузки (от 1 до 255), после которого добавляются/удаляются дополнительные линки в multilink bundle (service=ppp and protocol=multilink);
- max-links – максимальное число линков, которые пользователь может иметь в multilink bundle (service=ppp and protocol=multilink);
- nas-password – пароль для NAS при аутентификации для L2F туннеля (service=ppp and protocol=vpdn);
- nocallback-verify – (всегда = 1), означает, что не требуется верификации при callback (service=arap, service=slip, service=ppp, service=shell);
- noescape – (true или false), запретить использовать символ прерывания ввода (service=shell);
- nohangup – (true или false), запретить отключение пользователя по завершению сеанса EXEC (service=shell);
- outacl – определяется уровень доступа для исходящего соединения и применяется к интерфейсу на время сеанса (service=ppp, protocol=ip);
- pool-def – определить пул IP-адресов;
- pool-timeout – время на проверку существования указанного адресного пула на NAS;
- ppp-vj-slot-compression – указание маршрутизатору не использовать сжатие слотов при посылке VJ-сжатых пакетов;
- priv-lvl – уровень привилегий, назначаемый процессу EXEC (0-15, 15 – наивысший);
- protocol – подмножество сервиса (в основном для ppp):
- lcp ip
- ipx atalk
- vines lat
- xremote tn3270
- telnet rlogin
- pad vpdn
- deccp osicp
- ccp (compression control protocol) bridging
- cdp (cisco discovery protocol) xns
- nbf bap
- multilink unknown
- route – определяет статический маршрут, применяемый к интерфейсу (service=ppp, protocol=ip). Указывается в виде адреса назначения, маски подсети и (возможно) шлюза. Если шлюз опущен, то через соседа (peer). По завершению сеанса маршрут удаляется.
- route – аналогично route, но позволяет нумеровать маршруты и, стало быть, иметь их много;
- routing – (true или false) обрабатывать ли информацию о маршрутизации;
- source-ip – задает исходный IP-адрес VPDN-пакетов (эквивалент команды: vpdn outgoing);
- timeout – максимальное время сессии в минутах (начиная с 11.3.8, работает и для service=ppp protocol=lcp, но выражается в секундах);
- tunnel-id – идентификатор туннеля vpdn (service=ppp and protocol=vpdn);
- wins-servers – IP-адреса серверов WINS (NetBIOS Name Service) через пробел, передаваемых клиентам MS PPP (service=ppp, protocol=ip).
- $user – имя пользователя;
- $name – имя клиента(NAS);
- $port – порт клиента;
- $address – адрес клиента;
- $priv – уровень привилегий(0 – 15);
- $method – каким способом была пройдена аутентификация:
- 1 – none
- 2 – KRB5 (kerberos, version 5)
- 3 – line (пароль, привязанный к линии)
- 4 – enable (команда изменения привилегий)
- 5 – local (в соответствии с локальной БД NAS)
- 6 – tacacs+
- 8 – guest (например, guest в ARAP)
- 16 – RADIUS
- 17 – KRB4 (kerberos, version 4)
- $type – тип соединения:
- 1 – ASCII
- 2 – PAP
- 3 – CHAP
- 4 – ARAP
- 5 – MS CHAP
- $service – номер сервиса:
- 1 – login
- 2 – enable
- 3 – ppp
- 4 – arap
- 5 – pt
- 6 – rcmd
- 7 – X25
- 8 – NASI
- 9 – FWPROXY
- $status – строка статуса работы соединения:
- pass – успешное прохождение авторизации
- fail – провал соединения
- error – ошибка работы
- unknown – неизвестная ошибка.
Указанный скрипт выполняется /bin/sh -c и должен быть составлен соответствующим образом. При создании подобных скриптов учтите, что они будут выполняться много раз для каждого пользователя, например, прохождение авторизации ppp, ip и так далее. Скрипт авторизации может сообщать о статусе работы через код завершения:
- 0 – всё нормально, авторизация разрешена;
- 1 – произошла ошибка, авторизация запрещена;
- 2 – авторизация разрешена, но на stdout скрипт кидает AV-пары, которые используются для дальнейшей авторизации (в обход настройкам tacacs), причём если в выводе содержатся пробелы, их необходимо экранировать кавычками;
- 3 – аналогично предыдущему, но авторизация запрещена.
Авторизационные скрипты – довольно полезная вещь: я, например, сделал скрипт, работающий с MySQL и исследующий пользователей, которые могут заходить на определённый свитч. Скрипты выполняются под тем же пользователем, что и tacacs-сервер, поэтому запускать его от рута не рекомендуется (см. настройки Makefile). Приведу простой пример конфигурации сервера с использованием скриптов:
group users{
# Путь к скрипту, выполняющемуся до авторизации на сервере
before authorization "/usr/libexec/tacacs/users_auth $user $name $address"
# Разрешаем сервисы по умолчанию
default service = permit
service = exec {
# Выполняем автопинг
autocmd = "ping 192.168.2.1"
}
}
Последняя вещь, о которой я хотел бы рассказать для настройки сервера tacacs, – установка учёта работы (accounting). Для начала работы системы учёта достаточно добавить строку accounting file = «path_to_file» на глобальном уровне:
accounting file = "/var/log/tacacs/accounting"
Формат данного файла различается от версии к версии, поэтому я не буду на этом останавливаться подробно (думаю, понять, что к чему, будет нетрудно). Состоит файл учёта из 5 полей (поля разделяются символами табуляции): времени, имени NAS, имени пользователя, ключевого слова assync, признак начала или окончания сессии – start и stop соответственно (особенно интересна для учёта директива stop, на основании которой можно выполнять учёт и контроль ошибок, иногда, в случае ошибки авторизации или аутентификации, директива stop может не иметь пары start) и дополнительных AV-строк (для оценки PPP-трафика интересны пары service=PPP elapsed_time={время в секундах}, а также bytes_in= и bytes_out=).
Теперь позвольте перейти к описанию настройки киски. Для начала сразу же хочу предупредить, что к этому моменту необходимо иметь нормально работающий tacacs-сервер, иначе может случиться так, что вы не сможете зайти на киску (при настройке tacacs-сервера учтите тот факт, что по умолчанию всё запрещено, поэтому не забудьте корректно настроить авторизацию). Заходим в CLI-киски в режим EXEC (привилегированный режим): Устанавливаем сервер tacacs+ в name (имя или IP-адрес):
# tacacs-server host {name}
Установка тайм-аута поиска сервера (по умолчанию 5 секунд):
# tacacs-server timeout {seconds}
Количество попыток логина на сервер:
# tacacs-server attempts {count}
Ключ для шифрации трафика должен совпадать со значением на сервере:
# tacacs-server key {key}
Смотрим информацию о tacacs:
# show tacacs
Далее настраиваем три «а»: аутентификацию, авторизацию и аккаунтинг:
# configure terminal
Включаем новую модель aaa:
# aaa new-model
Глобальные настройки логина (список методов по степени возрастания, в моём примере вначале ходим на tacacs-сервер, а затем смотрим в локальные пароли):
# aaa authentication login default line
Настройка ppp-логина:
# aaa authentication ppp default tacacs+
Выбираем линию для настройки (список линий, могут быть специальные линии или номера стандартных линий маршрутизатора):
# line {[aux, console, tty, vty]| line-numbers}
Список методов логина для линии:
# login authentication tacacs+
# exit
Смотрим полученные изменения:
# show running-config
Настраиваем аутентификацию:
# configure terminal
Авторизация через tacacs всех сетевых служб (SLIP, PPP, NCP, ARA):
# aaa authorization network tacacs+
Авторизация через tacacs сервиса exec:
# aaa authorization exec tacacs+ # exit
Настраиваем аккаунтинг:
# configure terminal
Запускаем аккаунтинг событий начала и конца для сервиса exec и сетевых сервисов:
# aaa accounting exec start-stop tacacs+
# aaa accounting network start-stop tacacs+
# exit
Можно также создать обратную связь (callback) между сервером и киской (это полезно для получения некоторых параметров ppp). Для этого добавляем в настройки aaa такие строчки:
# aaa authentication ppp pppcheck tacacs+
# int async {number_of_line}
# ppp authentication {chap | pap} pppcheck
# ppp callback accept
На сервере есть также дополнительные callback av пары, например:
user = foo{
login = cleartext login
chap = cleartext xfgb
pap = des qQkpO0AMIp7RL
opap = cleartext outgoing_pap
service = ppp protocol = lcp {
# Строка дозвона для расширений ppp lcp
callback-dialstring=123456
}
}
Но мне callback показался не очень нужным в практическом плане, поэтому подробно о нём говорить я не буду.
Подводя итог, скажу, что использование tacacs мне лично показалось весьма удобным и простым (за исключением некоторой нестабильности работы – иногда мрут дочерние процессы, что в принципе нестрашно).
Ссылки:
- http://www.bog.pp.ru/work/tacacs.html
– на мой взгляд, наиболее качественный ресурс по данной теме на русском языке (также здесь вы найдёте уйму полезной информации);
- http://cisco.opennet.ru – отличная подборка материалов по Cisco;
- http://ftpeng.cisco.com/pub/tacacs – отсюда качаем;
- http://www.easynet.de/tacacs-faq – FAQ на английском языке по tacacs;
- http://rcp.ru/faq/cisco.html – FAQ на русском языке по маршрутизаторам Cisco;
- http://stiwww.epfl.ch/tacacs/u_g_F403.html – родная документация на английском языке;
- http://www.disaster.com/tacplus – подписка на список рассылок tacacs.