№4(5) апрель 2003 подписной индекс 81655 журнал для cистемных администраторов, вебмастеров и программистов
Настройка RADIUS-сервера Создаем VPN на основе vtun Система фильтрации интернет-трафика Компиляция FreeBSD LIDS Криптографическая защита информации
оглавление АДМИНИСТРИРОВАНИЕ
Разводной мост на Linux (Bridging Firewalls)
RADIUS В статье детально описана настройка популярных серверов протокола RADIUS, используемого для централизованной аутентификации dial-in пользователей. Radius предоставляет широкие возможности управления пользователями и создания системы учёта (биллинга). Всеволод Стахов CEBKA@smtp.ru 4
Создаем VPN на основе vtun Нужна надежная, безопасная и защищенная от «подглядывания» система связи? Единственная возможность выполнить все предъявленные требования – создание VPN. Андрей Бешков tigrisha@sysadmins.ru 14
Настройка Incoming Connections в Linux Настройка удаленного доступа к серверу. Сергей Ропчан fenix@sit-ua.com
22
Борьба за системные ресурсы Статья будет полезна системным администраторам, работающим в ОС Linux и желающим повысить производительность сервера и сети в целом. Денис Колисниченко dhsilabs@mail.ru 24
Система фильтрации интернет-трафика Экономим трафик. Настройка системы фильтрации на основе FreeBSD 4.5 + Squid + SquidGuard + Berkeley DB 3.2.9 + Apache. Андрей Бешков tigrisha@sysadmins.ru 30
Установка и настройка сервера Jabber на платформе Linux Практическое руководство. Сергей Индлин indlin@abc92.ru
Создание межсетевого экрана – моста, считающего и фильтрующего пакеты. Павел Закляков amdk7@mail.ru 42
FreeBSD. Компиляция Александр Прокошев ap@ap.kirov.ru
56
Абсолютно все о АТМ Основные концепции технологии АТМ. Сергей Ропчан fenix@sit-ua.com
60
БЕЗОПАСНОСТЬ LIDS Инструмент администрирования LIDS: защита компьютера под управлением Linux. Сергей Яремчук grinder@ua.fm
74
Система криптографической защиты информации Владимир Мешков ubob@mail.ru
78
WEB Интернет-операционные системы Игорь Тетерин keks_revda@uraltc.ru
88
Выбор веб-сервера: почему Apache? Дмитрий Галышев info@samag.ru
92
BUGTRAQ
2, 55
38 FAQ Shell
13, 37, 41
Уважаемые читатели! Рады сообщить вам, что с 1 апреля началась подписка на 2-ое полугодие 2003 года. Обратите внимание: подписной индекс по каталогу «Роспечать» со 2-го полугодия единый для организаций и частных лиц – 81655. Оформить подписку можно в любом почтовом отделении связи или через Интернет. Вы также можете получить журналы за 1-ое полугодие, прислав заявку на редакционную подписку по факсу 928-82-53 или на info@samag.ru Более подробная информация на нашем сайте www.samag.ru Желаем успехов!
№4(5), апрель 2003
1
BUGTRAQ Продолжение исследования уязвимости в IIS (WebDAV) Выпущенный патч против недавно обнаруженной уязвимости латает дырку в самом ядре операционной системы. Ее можно было использовать через переполнение, вызываемое WebDAV-запросом, однако это только один из способов. Сама проблема гораздо шире, чем может показаться, и касается не только серверов на IIS. NGSSoftware провела небольшое исследование, в результате которого были обнаружены и другие пути атаки. В основе использования уязвимости по IIS-направлению лежало отсутствие ограничения на длину имени файла при WebDAV-запросе. При обработке этого запроса используются методы: PROPFIND, LOCK, SEARCH и GET с заголовком «Translate: f». Запрос проходит через несколько функций, одной из которых является GetFileAttributesExW. В свою очередь, из нее вызывается функция RtlDosPathNameToNtPathName_U, экспортируемая из ntdll.dll. Собственно, она и является основой проблемы. RtlDosPathNameToNtPathName_U неправильно обрабатывает длину передаваемых строк. Неопределенные переменные являются 16-ти битными, следовательно, могут хранить значения от 0 до 65535. Если строка будет иметь длину 65536 байт, то будет считаться, что строка имеет длину 1, хотя реально она гораздо длиннее. Вот корень проблемы. GetFileAttributesExW не единственная функция, вызывающая RtlDosPathNameToNtPathName_U, вот еще несколько: GetShortPathNameW, CopyFileW, MoveFileW, MoveFileExW, ReplaceFileW, CreateMailslotW, GetFileAttributesW, FindFirstFileExW, CreateFileW, GetVolumeInformationW, DeleteFileW, GetDriveTypeW, GetFileAttributesExW, CreateDirectoryW, FindFirstChangeNotificationW, GetBinaryTypeW, CreateNamedPipeW, SetFileAttributesW, MoveFileWithProgressW, GetVolumeNameForVolumeMountPointW, GetDiskFreeSpaceW, CreateDirectoryExW, DefineDosDeviceW, PrivMoveFileIdentityW, GetCompressedFileSizeW, SetVolumeLabelW, CreateHardLinkW, RemoveDirectoryW. Как вы можете видеть, большинство функций используются для работы с файловой системой, атакующий может вызвать переполнение в любой из них, следовательно, все, что их использует, уязвимо. Но этим дело не заканчивается, ряд библиотек импортирует RtlDosPathNameToNtPathName_U из ntdll.dll, к ним относятся: acledit.dll, advapi32.dll, cscdll.dll, csrsrv.dll, dskquoui.dll, eventlog.dll, gdi32.dll, ifsutil.dll, lsasrv.dll, ntdll.dll, ntmarta.dll, ole32.dll, perfproc.dll, query.dll, rshx32.dll, scesrv.dll, sdbapiu.dll, setupdll.dll, sfc.dll, shell32.dll, shim.dll, srvsvc.dll, svcpack.dll, trkwks.dll, ulib.dll, wow32.dll. Следовательно, существует достаточное количество вариантов проведения атаки, которые не обязательно должны касаться IIS, это могут быть и другие win32 веб, ftp, IMAP-сервера, антивирусное ПО и т. д.
Новый RFC кардинально решает проблему сетевых атак Все гениальное, как всегда, просто – в протоколе IP v.4 достаточно незадействованных битов в поле флагов, один из которых предлагается использовать для отделения хакерских пакетов от обычных.
2
Вышел в свет эксплоит для ptrace Данный эксплоит работает за счет проблемы с ptrace в ядре ОС Линукс. На данный момент не существует официального патча для линуксовых ядер, кроме как для версии 2.4.20, что делает проблему еще более актуальной. Пример использования: gcc kernelptrace.c . /a.out [+] Attached to 24983 [+] Waiting for signal [+] Signal caught [+] Shellcode placed at 0xccfd9ef0 [-] Unable to write shellcode: Input/output error Killed ./a.out [+] Attached to 24986 [+] Waiting for signal [+] Signal caught [+] Shellcode placed at 0xccfd9ef0 [-] Unable to write shellcode: Input/output error Killed ./a.out [+] Attached to 24989 [+] Waiting for signal [+] Signal caught [+] Shellcode placed at 0x4000e8fd [+] Now wait for suid shell... sh-2.05a#
Теперь о способах защиты. Именно от этого эксплоита поможет простое «chmod 700 /proc», так как этот эксплоит пытается открыть /proc/self/exe. Кроме того, можно воспользоваться модулем ядра, который расположен по адресу: http://www.austin2600.org/mirrors/004560.html.
Анализ ntdll.dll эксплоита для WebDAV Эксплоит для NTDLL.DLL впервые был опробован на военном (military) сервере 17 марта сего года. Это было первое зарегистрированное использование «неопубликованного» эксплоита; Bugtraq лишь отчитался о ставшей известной уязвимости и о существующем эксплоите для неё. Это был случай, когда «незарелизенный» или «zero-day» эксплоит был использован для взлома до его публикации широким массам. За серьезной проблемой в Microsoft’s Internet Information Server (IIS) фактически стояла уязвимость в NTDLL.DLL, динамической библиотеке Windows, используемой всеми версиями Windows 2000, библиотеке, отвечающей непосредственно за работу с ядром системы. IIS web server – одно из множества приложений Windows 2000, использующих библиотеку NTDLL. WebDAV расшифровывается как «Web-based Distributed Authoring and Versioning». И является расширением HTTP-протокола, позволяющим пользователям безопасно редактировать и управлять файлами на удаленном веб-сервере [wbdvorg]. После публикации в Bugtraq, CERT дал описание уязвимости и линк на патч от Microsoft. Windows 2000 предоставляет поддержку протокола WebDAV, который используется по умолчанию веб-сервером IIS. Пользователь, пославший специально сформированный HTTP-запрос на машину под IIS, может удаленно выполнять команды на сервере, в контексте IIS-сервиса. MS классифицировала эту уязвимость как Critical.
ВСЕВОЛОД СТАХОВ
администрирование Протокол radius (Remote Authentication Dial In User Service) служит для аутентификации dial-up пользователей. Обычно radius используется маршрутизаторами Cisco для организации модемных линий, но возможны и варианты связки radius и pppd. В дальнейшем любого клиента radius я буду называть NAS (network access server – сервер, предоставляющий доступ в сеть). Если кто интересуется, чем же таким примечателен radius, то отвечу: данный протокол, с моей точки зрения, является логическим продолжением традиций tacacs-сервера, но он поддерживает больше возможностей и организован намного лучше. Особенно мне понравилась возможность проверки различных NAS по ключу и IP-адресу. Огорчает только относительная молодость протокола, отсутствие качественной документации по бесплатным серверам, отсутствие поддержки протокола старыми NAS. Последний пункт меня особенно опечалил: мои любимые коммутаторы Cisco Catalyst, что прекрасно работали с tacacs-сервером, наотрез отказались от работы с radius. Но в последних моделях Cisco и многие другие производители NAS поддерживают этот протокол. Для начала определюсь с терминологией: AV-пара – пара атрибут=значение. Авторизация – процесс проверки AV-пар пользователя. В ходе авторизации могут также устанавливаться определённые AV-пары (для сервера freeradius), смысл авторизации заключается в проверке достаточности информации, предоставленной пользователем, для того чтобы пользователь мог пройти аутентификацию. Аутентификация – процесс опроса внешних источников данных radius-сервером для сравнения AV-пар, предоставленных пользователем, и пар, хранящихся во внешнем источнике; выбор метода аутентификации определяется AV-парой Auth-Type. Аккаунтинг (или учёт) – процесс посылки на radius-сервер пакетов NAS, которые содержат информацию о текущем соединении (время, количество переданного трафика и т. д.), на основании этой информации скрипты счетчиков или биллинговой системы могут выполнять различные действия по ограничению доступа пользователей на NAS. Из серверов, доступных в сети, я выбрал freeradius (http://www.freeradius.org) – новая версия популярного cistron radius, который особенно меня порадовал тем, что он содержит значительное количество модулей аутентификации (например, sql, ldap, unix-passwd, samba-passwd) и стандартный (обладающий меньшими возможностями) radiusdlivingston (ftp://ftp.livingston.com/pub/le/radius/radius21.tar.Z). Эти два сервера распространяются бесплатно, и их компиляция не вызывает затруднений: $./configure $make #make install
Теперь самое время рассказать поподробнее о самом протоколе radius. Сервер radius использует протокол UDP для работы. Стандартно radius-сервер прослушивает 1812 порт. Для аккаунтинга используется другой порт – 1813 (radius-acct).
№4(5), апрель 2003
Рассмотрим, как отреагирует NAS при поступлении запроса пользователя на аутентификацию: пользователь пытается пройти аутентификацию на NAS; NAS смотрит в первый попавшийся radius-сервер и посылает пакет для установки связи (запрос на доступ); если ответ не получен в течение определённого таймаута, то NAS либо опрашивает radius-сервер ещё раз, либо ищет альтернативный сервер; radius-сервер смотрит IP-адрес NAS и проверяет ключ симметричного шифрования, если IP-адрес и ключ соответствуют тому, что написано в конфигурационном файле, то связь продолжается, иначе клиенту посылается пакет Invalid Key. Проверка осуществляется генерацией и шифрацией случайной строки. Затем данные, передаваемые между клиентом и сервером radius, шифруются этим ключом; сервер radius проверяет пароль пользователя (по сети передается md5-хеш пароля), помимо пароля сервер может также проверить IP-адрес и порт NAS, если эти данные неверны, то сервер посылает NAS пакет «Доступ запрещён», содержащий код ошибки и иногда её текстовое описание, отображаемое для пользователя; если же данные пользователя верны, то сервер посылает NAS пакет «Доступ разрешён», содержащий данные о сервисе (PPP, SLIP, login) и некоторые его специфические параметры, например, IP-адрес, номер подсети, MTU для PPP-сервиса в виде пар параметр=значение (AV-пар). После краткого теоретического отступления перейду к описанию настройки серверов. Для начала сразу же определюсь: я не ставлю своей целью рассказать о каждой опции и возможности, я просто описываю, как оно работает у меня. Настройки livingston и freeradius сильно различаются, поэтому рассматривать их я буду по отдельности. Radiusd-livingston является более ранним сервером и проще в настройке, чем freeradius, поэтому о нем – в первую очередь. Конфигурация сервера хранится в каталоге /etc/raddb (или в $PREFIX/etc/raddb) и представляет собой несколько файлов, отвечающих за работу отдельных механизмов сервера: clients – определения NAS (ключ и IP-адрес) для проверки подлинности клиента; users – файл, описывающий dial-in пользователей; proxy – настройки перенаправления запросов клиентов другим radius-серверам, если аутентификация на данном прошла неудачно (возможность роуминга или распределения пользователей); dictionary – словарь определений AV-пар для работы с клиентом. Далее я приведу примеры конфигурационных файлов с комментариями: clients: # # # #
 äàííîì ôàéëå íàõîäèòñÿ ñïèñîê êëèåíòîâ (NAS), êîòîðûå ìîãóò ïðîõîäèòü àóòåíòèôèêàöèþ. Êëèåíò ïðîõîäèò ïðîâåðêó èìåíè è êëþ÷à. Ôàéë èìååò ñîîòâåòñòâóþùóþ ñòðóêòóðó: ïîëå èìåíè è ïîëå êëþ÷à:
5
администрирование #Èìÿ êëèåíòà Êëþ÷ #---------------- ------------------NAS1 123456789cba NAS2:call 987654321abc
DEFAULT Auth-Type = System, Prefix = "S" Service-Type = Framed-User, Framed-Protocol = SLIP, Framed-IP-Address = 255.255.255.254, Framed-Compression = None
proxy: #  ýòîì ôàéëå îïèñûâàþòñÿ radius-ñåðâåðû, íà êîòîðûå # äàííûé ìîæåò ïåðåíàïðàâëÿòü çàïðîñû NAS. Òàêîå ïîâåäåíèå, # íàïðèìåð, ïîëåçíî äëÿ îðãàíèçàöèè ðîóìèíãà. Ïðåäñòàâèì # ñèòóàöèþ: ñóùåñòâóåò 2 ïðîâàéäåðà À è Á, îíè õîòÿò, ÷òîáû # êëèåíò, çàêëþ÷èâøèé äîãîâîð ñ îäíèì èç íèõ, ìîã áåñïðå# ïÿòñòâåííî çàõîäèòü è íà äðóãîé.  äàííîì ñëó÷àå â ôàéëå # ïðîïèñûâàåòñÿ radius-ñåðâåð âòîðîãî ïðîâàéäåðà, íà êîòîðûé # áóäåò îñóùåñòâëÿòüñÿ ïåðåíàïðàâëåíèå. Íàëè÷èå êëþ÷åé # ïîçâîëÿåò çàùèòèòü ñåðâåðà äîñòóïà îò ïîäìåíû äàííûõ. # Ðàññìàòðèâàåìûé ôàéë ñîäåðæèò ÷åòûðå ïîëÿ: èìÿ ñåðâåðà, # êëþ÷ äîñòóïà ê ñåðâåðó (íà óäàë¸ííîì ñåðâåðå íåîáõîäèìî # âíåñòè çàïèñü â clients, ñîîòâåòñòâóþùóþ ñåðâåðó, îñóùå# ñòâèâøåìó ïåðåíàïðàâëåíèå), îáëàñòü äåéñòâèÿ ñåðâåðà # (ò.å. êàêèõ êëèåíòîâ ñëåäóåò ïåðåíàïðàâëÿòü íà äàííûé # ñåðâåð, îïðåäåëÿåòñÿ èìåíåì êëèåíòà ïîñëå çíàêà @, íà# ïðèìåð, user@test.ru), íåîáÿçàòåëüíûå îïöèè è íîìåðà # ïîðòîâ. Äîñòóïíûå îïöèè âûãëÿäÿò ñëåäóþùèì îáðàçîì: old – # óäàëåíèå îáëàñòè äåéñòâèÿ è ñîñòîÿíèÿ ïðîêñè èç çàãîëîâêà # ñîîáùåíèÿ îò NAS, secure – âîçìîæíîñòü ïåðåñûëêè çàïðîñîâ # íà äîñòóï ñ ïðèâèëåãèÿìè àäìèíèñòðàòîðà, ipass – # èñïîëüçîâàíèå ïðîòîêîëà ipass (íåïåðåâîäèìîå ñëîâî). rad.test.ru somekey test.ru radius.ru.net papakeyyer com.net 1645 1646 secure users: # Ýòî îñíîâíîé ôàéë, ãäå õðàíÿòñÿ äàííûå î ïîëüçîâàòåëÿõ. # Îïèñàíèå èä¸ò òàê: âíà÷àëå áåç îòñòóïà èìÿ ïîëüçîâàòåëÿ, # çàòåì, îòñòóïàÿ íà òàáóëÿöèþ, èäóò AV-ïàðû (ïåðâîé # ïàðîé èä¸ò ïàðîëü). AV-ïàðû äîëæíû îïèñûâàòüñÿ â ôàéëå # ñëîâàðÿ dictionary. Ñóùåñòâóåò òàêæå ñïåöèàëüíûé ïîëüçî# âàòåëü ïî óìîë÷àíèþ, êîòîðûé èìååò ñïåöèàëüíîå èìÿ # DEFAULT. Îáû÷íî ïîëüçîâàòåëü ïî óìîë÷àíèþ ïðèìåíÿåòñÿ, # êîãäà îïèñàíèÿ ïîëüçîâàòåëåé íàõîäÿòñÿ íå â äàííîì ôàéëå, # à â /etc/passwd, íî îá ýòîì ÿ ðàññêàæó äàëåå. Äëÿ íà÷àëà # ïðèâåäó íåñêîëüêî ïðèìåðîâ îïèñàíèÿ ïîëüçîâàòåëåé (äëÿ # ïîëó÷åíèÿ ïîëíîãî ñïèñêà AV-ïàð ñìîòðèòå ôàéë ñëîâàðÿ). # Åù¸ ó÷òèòå, ÷òî èìÿ ïîëüçîâàòåëÿ ìîæåò èìåòü ìàêñèìóì 8 # ñèìâîëîâ â äëèíó, ïàðîëü â ïðèíöèïå äî 254 ñèìâîëîâ, íî # ÿ ÷àñòî ñëûøàë ïðî îãðàíè÷åíèå â 31 ñèìâîë (÷åñòíî ãîâîðÿ, # ïðåäñòàâèòü ñåáå íå ìîãó, êîãäà ìîæåò ïîíàäîáèòüñÿ ïàðîëü # äëèííåå 31 ñèìâîëà!) user1 Password = "testing", Expiration = "Dec 24 1995" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-Routing = None, Filter-Id = "std.ppp", Framed-MTU = 1500, Framed-Compression = Van-Jacobson-TCP-IP user2 Password = "moretest" Service-Type = Login-User, Login-IP-Host = 192.168.2.7, Login-Service = PortMaster user3 Password = "callme" Service-Type = Callback-Login-User, Login-IP-Host = timeshare1, Login-Service = PortMaster, Callback-Number = "1231234" #  êîíöå ôàéëà ìîæåò áûòü îïèñàíèå ïîëüçîâàòåëÿ ïî óìîë# ÷àíèþ DEFAULT.  äàííîì ñëó÷àå èñïîëüçóåòñÿ àóòåíòèôèêàöèÿ # ÷åðåç ïàðîëè â /etc/passwd, äëÿ ýòîãî ïðèìåíÿåòñÿ äèðåê# òèâà Auth-Type = System. Çíà÷åíèå ïðåôèêñà èëè ñóôôèêñà # äëÿ èìåíè ïîëüçîâàòåëÿ îçíà÷àåò, ÷òî ïðîèçâîäèòñÿ ïîèñê # äàííîãî ïðåôèêñà èëè ñóôôèêñà, à îñòàëüíàÿ ÷àñòü èìåíè # èñïîëüçóåòñÿ íåïîñðåäñòâåííî êàê èìÿ ïîëüçîâàòåëÿ. Ýòî # óäîáíî äëÿ äîáàâëåíèÿ ðàçëè÷íûõ òèïîâ äîñòóïà äëÿ ïîëüçî# âàòåëÿ â çàâèñèìîñòè îò ïðåôèêñà èëè ñóôôèêñà. # Ðàññìîòðèì ïðèìåð: # Äëÿ ïîëüçîâàòåëåé, íà÷èíàþùèõñÿ ñ áóêâû P (Pusername) # èñïîëüçóåòñÿ ñåðâèñ PPP DEFAULT Auth-Type = System, Prefix = "P" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-MTU = 1500 # Äëÿ ïðåôèêñà S - SLIP
6
# Êîìïðåññèÿ òðàôèêà - ïðåôèêñ C DEFAULT Auth-Type = System, Prefix = "C" Service-Type = Framed-User, Framed-Protocol = SLIP, Framed-IP-Address = 255.255.255.254, Framed-Compression = Van-Jacobson-TCP-IP # Çäåñü èñïîëüçóåòñÿ ñóôôèêñ %ppp, ñèãíàëèçèðóùèé # èñïîëüçîâàíèå ïðîòîêîëà PPP DEFAULT Auth-Type = System, Suffix = "%ppp" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-MTU = 1500 # Äëÿ ïîëüçîâàòåëÿ, íå ñîîòâåòñòâóþùåãî äðóãèì îïðåäåëåíèÿì, # çàïóñêàåì ïðîòîêîë PPP DEFAULT Auth-Type = System, Framed-Protocol = PPP Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-MTU = 1500 dictionary: # Äàííûé ôàéë ñîäåðæèò îïèñàíèÿ àòðèáóòîâ è çíà÷åíèé. # Êîíå÷íî æå, ÿ íå áóäó ïðèâîäèòü åãî öåëèêîì, ïðèâåäó # ïðèìåð òîëüêî îñíîâíûõ AV: ATTRIBUTE èìÿ_àòðèáóòà # ÷èñëî_ñîîòâåòñòâóþùåå_àòðèáóòó òèï_àòðèáóòà. ×èñëî äëÿ # àòðèáóòà èñïîëüçóåòñÿ êàê ñèíîíèì òåêñòà, ìîæíî íàïèñàòü # Password="text", ÷òî èäåíòè÷íî 2="text". Òèï àòðèáóòà # ìîæåò ïðèíèìàòü ñëåäóþùèå çíà÷åíèÿ: # string – ñòðîêà äëèíîé îò 0 äî 253 ñèìâîëîâ; # ipaddr – IP-àäðåñ, 4 áàéòà â ñåòåâîì ïîðÿäêå; # integer – 32-õ áèòíîå öåëîå â èíòåëîâñêîì ïîðÿäêå áàéò; # date – 32-õ áèòíîå ÷èñëî, îçíà÷àþùåå òåêóùóþ äàòó è âðåìÿ; ATTRIBUTE User-Name 1 string ATTRIBUTE Password 2 string ATTRIBUTE Framed-IP-Address 8 ipaddr ATTRIBUTE Expiration 21 date # Îïèñàíèÿ çíà÷åíèé: VALUE èìÿ_çíà÷åíèÿ èìÿ_àòðèáóòà íîìåð. # Ýòè îïèñàíèÿ îáû÷íî ñëóæàò äëÿ óñòàíîâëåíèÿ ñîîòâåòñòâèÿ # ñòðîêà-íîìåð. Òàê, íàïðèìåð, çíà÷åíèå ïðîòîêîëà èìååò # ÷èñëîâîé âèä, íî äëÿ óïðîùåíèÿ ñîñòàâëåíèÿ ôàéëà # êîíôèãóðàöèè íåêîòîðûì ÷èñëàì ñîïîñòàâëåíû ÷èñëîâûå # êîíñòàíòû (ìîæíî ïðèâåñòè àíàëîãèþ #define MACRO 1 â ñè): VALUE Service-Type Login-User 1 VALUE Service-Type Framed-User 2 VALUE Service-Type Callback-Login-User 3 VALUE Service-Type Callback-Framed-User 4 VALUE Service-Type Outbound-User 5 VALUE Service-Type Administrative-User 6 VALUE Framed-Protocol PPP 1 VALUE Framed-Protocol SLIP 2 VALUE Framed-Protocol ARAP 3 VALUE Login-Service Telnet 0 VALUE Login-Service Rlogin 1 VALUE Login-Service TCP-Clear 2 VALUE Login-Service PortMaster 3
Для проверки работы radius-сервера используется специальная программа -rad_test, но о ней я расскажу далее при описании сервера freeradius (в livingston она точно такая же). Сервер freeradius отличается исключительной функциональностью. Он может работать с SQL-серверами (в настоящее время поддерживаются mysql, postgresql, oracle), LDAP-сервером, содержит в себе достаточно много AV-словарей, отличается комплексной настройкой, поддерживает дополнительные модули, имеет веб-интерфейс для настройки и несколько весьма полезных скриптов. Конфигурация freeradius несколько похожа на настройку livingston, поэтому я буду рассказывать преимущественно о работе аутентификации пользователей radius через mysql. Общие настройки сервера размещаются в файле
администрирование radiusd.conf. Я приведу здесь несколько опций, показавшихся мне полезными: radiusd.conf # Îáùàÿ ñõåìà ôàéëîâ êîíôèãóðàöèè freeradius ïîçâîëÿåò # èñïîëüçîâàòü ñïåöèàëüíóþ äèðåêòèâó $INCLUDE äëÿ âêëþ÷åíèÿ # êîíôèãóðàöèîííûõ ôàéëîâ â äàííûé (ôîðìàò .conf) $INCLUDE ${confdir}/proxy.conf $INCLUDE ${confdir}/clients.conf # Ïîëåçíî áóäåò óêàçàòü ïîëüçîâàòåëÿ è ãðóïïó, ïîä êîòîðûìè # áóäåò ðàáîòàòü ñåðâåð.  ïðèíöèïå ëó÷øå, ÷òîáû ïðèâèëåãèé # áûëî ïîìåíüøå. Åñëè æå èñïîëüçîâàòü àóòåíòèôèêàöèþ mysql, # òî âûáîð nobody:nobody, íà ìîé âçãëÿä, ÿâëÿåòñÿ ñàìûì # íàèëó÷øèì. user = nobody group = nobody # Ìàêñèìàëüíîå âðåìÿ îáðàáîòêè çàïðîñà (â ñåêóíäàõ), ïî # èñòå÷åíèè êîòîðîãî êëèåíòó áóäåò ïîñëàí ïàêåò, ñèãíàëè# çèðóþùèé ðàçðûâ ñîåäèíåíèÿ. max_request_time = 30 # Ìàêñèìàëüíîå êîëè÷åñòâî ñîåäèíåíèé äëÿ äàííîãî ñåðâåðà # ïîëó÷àåòñÿ óìíîæåíèåì ÷èñëà NAS â ñåòè íà 256. Íàïðèìåð, # äëÿ 4 êëèåíòîâ, çíà÷åíèå áóäåò 4*256=1024 max_requests = 1024 # Çàíîñèòü â ëîã äàííûå î ïîëíîì èìåíè ïîëüçîâàòåëÿ log_stripped_names = yes # Çàíîñèòü ëè â ëîã èíôîðìàöèþ î çàïðîñàõ íà àóòåíòèôèêàöèþ log_auth = no # Çàíîñèòü ëè â ëîã äàííûå î ïåðåäàííûõ ïàðîëÿõ # (íåïðàâèëüíûõ è ïðàâèëüíûõ ñîîòâåòñòâåííî) log_auth_badpass = yes log_auth_goodpass = no # Ïðèâîäèòü ëè ê íèæíåìó ðåãèñòðó âñå èìåíà ïîëüçîâàòåëåé # è ïàðîëè (âåñüìà ïîëåçíî äëÿ íåêîòîðûõ ïîëüçîâàòåëåé). # Âîçìîæíûå çíà÷åíèÿ: no – ÷óâñòâèòåëüíûå ê ðåãèñòðó # ïàðîëü/èìÿ, before – âíà÷àëå ïðèâîäèì ê íèæíåìó ðåãèñòðó, # ïîòîì ïðîâîäèì àóòåíòèôèêàöèþ, after – âíà÷àëå ïðîâåðÿåì # àóòåíòèôèêàöèþ êàê åñòü, åñëè íå ïîëó÷èëîñü, òî ïðèâîäèì # ê íèæíåìó ðåãèñòðó è ïîâòîðÿåì ïîïûòêó. lower_user = no lower_pass = no # Óáèðàåì ïðîáåëû èç èìåíè ïîëüçîâàòåëÿ è ïàðîëÿ. Ïîëåçíî # äëÿ èì¸í è ïàðîëåé, ñîäåðæàùèõ ïðîáåëû. Âîçìîæíûå # çíà÷åíèÿ àíàëîãè÷íû ïðåäûäóùåìó ñëó÷àþ. nospace_user = no nospace_pass = no # Âåñüìà ïîëåçíûå ïàðàìåòðû ìîäóëÿ áåçîïàñíîñòè ñåðâåðà: security { # Ìàêñèìàëüíîå ÷èñëî AV-ïàð â ïàêåòå. Åñëè ÷èñëî ïàð # áîëüøå, òî ïàêåò íå îáðàáàòûâàåòñÿ. Åñëè óêàçàòü # äàííûé ïàðàìåòð ðàâíûì íóëþ, òî áóäóò îáðàáàòûâàòüñÿ # ëþáûå ïàêåòû. max_attributes = 200 # Ïàêåò îòêàçà äîñòóïà ìîæåò áûòü îòïðàâëåí ñ íåêîòîðîé # çàäåðæêîé (â ñåêóíäàõ). Òàêîå ïîâåäåíèå ïðåäîòâðàùàåò # ïðèìåíåíèå DoS-àòàêè. Åñëè æå óêàçàòü çíà÷åíèå, ðàâíîå # íóëþ, òî îòêàç áóäåò ïîñûëàòüñÿ áåç çàäåðæêè. reject_delay = 1 # Ïîñûëàòü îòâåò íà çàïðîñ NAS î ñòàòóñå ñåðâåðà. Òàêîå # ïîâåäåíèå íå îïèñàíî â rfc, ïîýòîìó ïî óìîë÷àíèþ – no # (êàê íàïèñàíî â êîììåíòàðèÿõ, «ìîæåò ïðèãîäèòüñÿ äëÿ # íåêîòîðûõ îñîáûõ NAS») status_server = no } # Îáðàáàòûâàòü ïåðåíàïðàâëåíèå çàïðîñîâ. Åñëè ïåðåíàïðàâëåíèå # îòêëþ÷åíî, òî íåîáõîäèìî îòêëþ÷èòü ôàéë proxy.conf, äàáû # èçáåæàòü îøèáîê êîíôèãóðàöèè (çàêîììåíòèðîâàòü äèðåêòèâó # $INCLUDE ${confdir}/proxy.conf). proxy_requests = yes # Äàëåå ñëåäóþò îïèñàíèÿ ìíîãî÷èñëåííûõ ìîäóëåé freeradius, # ïîçâîëÿþùèå íàñòðîèòü, ê ïðèìåðó, ìåòîäû øèôðàöèè ïàðîëåé # èëè ðàáîòó ðàçëè÷íûõ àóòåíòèôèêàöèîííûõ ïðîòîêîëîâ (PAP, # CHAP, MS-CHAP), íî îïèñûâàòü çäåñü âñ¸ ÿ íå íàìåðåí: äóìàþ, # ÷òî â ïðèìåðàõ âñå è òàê î÷åíü ïîäðîáíî îáüÿñíåíî è # ðàçîáðàòüñÿ íå ñîñòàâèò òðóäà.
Настройка клиентов производится в файле clients.conf: clients.conf #  äàííîì ôàéëå îïèñûâàþòñÿ êëèåíòû aka NAS. Ôîðìàò ôàéëà # íàïîìèíàåò ôàéë íàñòðîéêè tacacs+. Âíà÷àëå èä¸ò îïðåäåëåíèå
№4(5), апрель 2003
# êëèåíòà: client èìÿ_èëè_ip_àäðåñ, çàòåì èä¸ò ñïèñîê AV-ïàð # äëÿ äàííîãî êëèåíòà, çàêëþ÷¸ííûé â ôèãóðíûå ñêîáêè. Ïðèâåäó # íåñêîëüêî ïðèìåðîâ: client 127.0.0.1 { # Ïàðîëü äëÿ èäåíòèôèêàöèè êëèåíòà è îáìåíà ñ íèì # äàííûìè. Äàííûì êëþ÷îì òàêæå îñóùåñòâëÿåòñÿ ïðîâåðêà # íåèçìåííîñòè ïåðåäàâàåìûõ ïàêåòîâ (ïîäïèñü). secret = some_strange_secret # Êðàòêîå èìÿ äëÿ êëèåíòà. shortname = localhost # Ñëåäóþùèå òðè ïîëÿ íåîáÿçàòåëüíû, íî îíè ïîëåçíû äëÿ # ðàáîòû ñêðèïòà checkrad.pl (ïðîâåðêà ðàáîòû ïðîöåññîâ # ñåðâåðà) # Ïîëå òèïà NAS ìîæåò ïðèíèìàòü ñëåäóþùèå çíà÷åíèÿ: # Õîòÿ çà÷åì ýòî íóæíî, ÿ òàê è íå ïîíÿë. # cisco # computone # livingston # max40xx # multitech # netserver # pathras # patton # portslave # tc # usrhiper # other nastype = other # localhost îáû÷íî íå ÿâëÿåòñÿ NAS # Äâå ñëåäóþùèå ñòðî÷êè çàðåçåðâèðîâàíû íà áóäóùåå. # Âîîáùå-òî îíè äîëæíû èñïîëüçîâàòüñÿ äëÿ ïðîâåðêè # èìåíè ïîëüçîâàòåëÿ è ïàðîëÿ äëÿ äàííîãî NAS login = !root password = someadminpas
# # } client some.test.ru { secret = some_host_secret shortname = somenas } # Òàêæå ìîæíî îïðåäåëÿòü ïàðîëü äëÿ âñåõ êëèåíòîâ # íåêîòîðîé ïîäñåòè (÷åì ìåíüøå ïîäñåòü, òåì ëó÷øå, à # âîîáùå, íà ìîé âçãëÿä, ýòî íå åñòü õîðîøî èç # ñîîáðàæåíèé áåçîïàñíîñòè) client 192.168.0.0/24 { secret = a_very_long_passwd shortname = private-network }
Далее я кратко остановлюсь на особенностях настройки файла proxy.conf. В отличие от сервера livingston во freeradius опять же используется собственный конфигурационный формат. Из нововведений особенно бросается в глаза новая директива – realm, определяющая область перенаправления. Дабы не быть голословным опять же приведу несложный пример: proxy.conf # Äàííûé ôàéë ñîñòîèò èç äâóõ ðàçäåëîâ: îïèñàíèå íàñòðîåê # ñàìîãî ïðîêñè-ñåðâåðà è îïèñàíèå îáëàñòåé ïåðåíàïðàâëåíèÿ. # Íà êîíôèãóðàöèè ðàáîòû ñàìîãî ïðîêñè-ñåðâåðà ÿ îñòàíàâ# ëèâàòüñÿ íå áóäó, à ñðàçó æå ïåðåéäó ê îïèñàíèþ äèðåêòèâû # îïðåäåëåíèÿ îáëàñòè realm. Îíà âûãëÿäèò ñëåäóþùèì îáðàçîì: # realm èìÿ_îáëàñòè. Èìÿ îáëàñòè äîëæíî ÿâëÿòüñÿ èìåíåì # äîìåíà, êîòîðûé ýòîé îáëàñòüþ îïèñûâàåòñÿ. Åñëè âìåñòî # èìåíè îáëàñòè óïîòðåáëÿåòñÿ ñëîâî DEFAULT, òî â äàííóþ # îáëàñòü áóäóò ïåðåíàïðàâëÿòüñÿ çàïðîñû, íå ñîîòâåòñòâóþùèå # íè îäíîìó ïàðàìåòðó. Ïîÿñíþ ýòî íà ïðèìåðàõ: realm isp2.ru { # Òèï ñåðâåðà type = radius # Ñåðâåð radius äëÿ àóòåíòèôèêàöèè authhost = radius.isp2.com:1645 # Ñåðâåð radius äëÿ àóòåíòèôèêàöèè (îáû÷íî äðóãîé ïîðò) accthost = radius.isp2.com:1646 # Ñåêðåò äëÿ ñâÿçè secret = our_concurents_key # Íå óáèðàòü ñóôôèêñ èëè ïðåôèêñ îáëàñòè èç èìåíè ïîëüçîâàòåëÿ nostrip } # Åñëè ïåðåíàïðàâèòü çàïðîñ íà äàííûé ñåðâåð íå óäàëîñü,
7
администрирование # òî ïðîèñõîäèò âûáîðêà äðóãîãî ñåðâåðà äëÿ äàííîé îáëàñòè # èëè ñåðâåðà ïî óìîë÷àíèþ. Òàêæå ñóùåñòâóåò ñïåöèàëüíàÿ # îáëàñòü NULL äëÿ êëèåíòîâ, êîòîðûå íå îïðåäåëèëè îáëàñòü # äåéñòâèÿ, íàïðèìåð, ïðîñòî user (ñðàâíèòå user@isp2.ru) realm NULL { type = radius authhost = radius.test.ru accthost = radius.test.ru secret = our_secret_key } # Íó à äëÿ òåõ ïîëüçîâàòåëåé, ÷üÿ îáëàñòü íå îïðåäåëåíà, # èñïîëüçóåòñÿ ñåðâåð ïî óìîë÷àíèþ: realm DEFAULT { type = radius authhost = radius.test.ru accthost = radius.test.ru secret = our_secret_key } # Ó÷òèòå: â äâóõ ïîñëåäíèõ ïðèìåðàõ ïðè ïåðåíàïðàâëåíèè # çàïðîñà ê âòîðè÷íûì ñåðâåðàì radius èç èìåíè ïîëüçîâàòåëÿ # âûðåçàåòñÿ èìÿ îáëàñòè, ò.ê. íå îïðåäåëåíà îïöèÿ nostrip.
Теперь для любопытствующих кратко опишу назначение остальных конфигурационных файлов freeradius: acct_users – содержит установки учёта (аккаунтинга). Обычно используется для задания начальных и конечных скриптов для пользователя и областей репликации (см. пример). В скрипты можно передавать специальные переменные: %a Protocol (SLIP/PPP) %c Callback-Number %d request day (DD) %f Framed IP address %i Calling Station ID %l request timestamp %m request month (MM) %n NAS IP address %p Port number %s Speed (PW_CONNECT_INFO) %t request in ctime format %u User name %A radacct_dir %C clientname %D request date (YYYYMMDD) %H request hour %L radlog_dir %M MTU %R radius_dir %S request timestamp in SQL format %T request timestamp in database format %U Stripped User name %V Request-Authenticator (Verified/None) %Y request year (YYYY) Пример: DEFAULT Acct-Status-Type == Start Exec-Program = "/path/to/exec/acct/start %U" DEFAULT Acct-Status-Type == Stop Exec-Program = "/path/to/exec/acct/stop %U %n %a"
attrs – информация об AV-парах по умолчанию для каждой области действия.
clients.conf – настройки NAS. dictionary – данные об известных AV-парах. hints – информация о суффиксах и префиксах имён пользователей.
8
Пример: # Çäåñü äèðåêòèâà Strip-User-Name îïðåäåëÿåò, óäàëÿòü ëè # ïðåôèêñ èëè ñóôôèêñ èç èìåíè DEFAULT Suffix = ".ppp", Strip-User-Name = Yes Hint = "PPP", Service-Type = Framed-User, Framed-Protocol = PPP DEFAULT Prefix = "P", Strip-User-Name = Yes Hint = "PPP", Service-Type = Framed-User, Framed-Protocol = PPP
proxy.conf – информация об областях. sql.conf – настройки работы с mysql (к этому файлу я еще вернусь).
users – а вот этот файл очень важен для последующего изложения, он описывает пользователей. Описание пользователей аналогично livingston-radius: user
Auth-Type := Local, User-Password == "testing" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 172.16.3.33, Framed-IP-Netmask = 255.255.255.0, Framed-Routing = Broadcast-Listen, Framed-MTU = 1500, Framed-Compression = Van-Jacobsen-TCP-IP
но есть и отличие: использование специальных операторов присваивания и сравнения (в linvingston был только один «=»). Приведу список «новых» операторов: Атрибут посылается NAS, его значение равно Value: «Attribute = Value» Если данный атрибут не определён, то он принимает указанное значение: «Attribute := Value» Используется только для проверки значения атрибута: «Attribute == Value» Добавление нового значения атрибуту: «Attribute += Value» Различные операции сравнения: «Attribute != Value» «Attribute > Value» «Attribute >= Value» «Attribute < Value» «Attribute <= Value» Проверка соответствия значения атрибута определённому регулярному выражению: «Attribute =~ Expression» «Attribute !~ Expression» Проверка, содержит ли запрос данный атрибут, значение не играет роли: «Attribute =* Value» «Attribute !* Value» Однако если вы намереваетесь работать с большим числом пользователей, то файл users не подойдет (он целиком помещается в память). В качестве альтернативы можно взять сервера LDAP или MySQL (PostgreSQL, Oracle). LDAP, на мой взгляд, несколько практичнее, но я прекрасно понимаю, что MySQL распространён намного больше, поэтому о его использовании я и поведу речь. Для начала устанавливаем mysql (этот процесс я не описываю). Обязательно устанавливаем (если работаем
администрирование с пакетами) пакет mysql-dev. После этого перекомпилируем radius (configure скрипт сам обнаружит mysql и включит в makefile нужный модуль). После этого создаём базу в mysql: $mysql -uroot -proot_passwd mysql> create database radius
После этого выполняем mysql-сценарий для создания таблиц в базе. Для этого заходим в каталог модуля mysql: $cd {PATH_TO_RADIUS_SRC}/src/modules/rlm_sql/drivers ↵ rlm_sql_mysql
и передаём mysql-сценарий: $mysql -uroot -proot_passwd radius < db_mysql.sql
База состоит из 5-и таблиц:
Usergroup – данные о группах пользователей, например: mysql> select * from usergroup;
2 rows in set (0.00 sec)
Radcheck – AV-пары для проверки пользователя (обычно пароль), например:
2 rows in set (0.02 sec)
Radgroupcheck – проверка атрибутов для группы (не знаю, зачем это нужно).
Radreply – таблица, содержащая AV-пары, передающиеся клиенту сервером при прохождении аутентификации, например: mysql> select * from radreply;
ствляется модулем, который определён в AV-паре AuthType (в таблице radcheck можно присвоить пользователю это поле по умолчанию с помощью оператора “:=”). Существует много типов аутентификации (см. соответствующие значения атрибутов в словаре dictionary), большинство из них определяют пароль из mysql. Здесь примере для простоты приведён пример типа аутентификации Accept, который сразу же возвращает пакет разрешения доступа, применять этот тип следует лишь в тестирующих целях. Другие распространённые методы аутентификации: System – системная аутентификация (для pap-протокола), обычно нужна запись в /etc/passwd для проверки пароля, другой вариант – использование файла users. Chap – аутентификация протокола chap (пароль передаётся в открытом виде). Reject – отклонение доступа пользователя. Ms-Chap Ldap – проверка пароля через службу каталогов ldap (необходимо поправить подсекцию ldap в секции modules файла radiusd.conf). Важно знать, что для некоторых типов аутентификации (system) можно использовать зашифрованные пароли – Crypt-Password в формате Unix crypt. Для Ms-Chap необходимо использовать параметры LM-Password и NTPassword. Для изучения других параметров полезно почитать файл словаря dictionary. И ещё: иногда очень полезно взять пользователя по умолчанию DEFAULT для сообщения некоторых AV-пар, общих для всех пользователей. Для настройки radiusd необходимо проверить следующие пункты radiusd.conf: секция modules, дабы убедиться, что файл конфигурации mysql включен: modules { # Âêëþ÷åíèå ôàéëà äëÿ ðàáîòû ñ mysql, äëÿ ðàáîòû # ñ äðóãèìè ÑÓÁÄ èñïîëüçóþòñÿ ôàéëû # Postgresql: ${confdir}/postgresql.conf # MS-SQL: ${confdir}/mssql.conf $INCLUDE ${confdir}/sql.conf }
секция авторизации, настроенная для использования ldap и mysql: 6 rows in set (0.01 sec)
Radgroupreply – AV-пары, содержащиеся в ответе сервера для данной группы, например: mysql> select * from radgroupreply;
authorize { preprocess chap mschap suffix files sql ldap }
Настройка данных методов проводится в соответствующих подсекциях секции modules. В разделе аутентификации можно также объявлять собственные методы, например:
12 rows in set (0.01 sec)
Учтите тот факт, что mysql применяется для авторизации пользователя, парольная аутентификация осуще-
№4(5), апрель 2003
authenticate { authtype my_dialup { pap chap ldap } }
9
администрирование и использовать их в поле Auth-Type. В файле sql.conf также делаются некоторые изменения для указания серверу radius информации о поиске данных в mysql: sql { # Òèï áàçû äàííûõ driver = "rlm_sql_mysql" # Ïàðàìåòðû ñîåäèíåíèÿ server = "localhost" login = "root" password = "mysql_passwd"
пользователях и паролях будет намного удобнее и эффективнее. Для этого правим файл radiusd.conf: ldap { server = "ldap.test.ru" # Ýòîò ïîëüçîâàòåëü äîëæåí èìåòü ïðàâî ÷èòàòü ïàðîëè, # ïîýòîìó íåîáõîäèìî äîáàâèòü ñîîòâåòñòâóþùèé acl â ôàéë # êîíôèãóðàöèè ldap-ñåðâåðà (îá ýòîì ðàññêàçàíî â ìîåé # ñòàòüå «OpenLDAP». – æóðíàë # «Ñèñòåìíûé àäìèíèñòðàòîð». – 2003, ¹2(3). ñ.74-84.) identity = "cn=proxy,dc=test,dc=ru" password = mypass basedn = "o=test,c=ru" filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
# Áàçà äàííûõ, èñïîëüçóåìàÿ radius radius_db = "radius"
# Âêëþ÷àåì áåçîïàñíîå ñîåäèíåíèå, íå ìåíÿÿ ïîðò start_tls = yes # Áîã çíàåò ÷òî, íî âðîäå ýòî çàñòàâëÿåò øèôðîâàòü # äàííûå ïðè çàïðîñå ê ñåðâåðó tls_mode = yes #  äàííîé âåòâè õðàíÿòñÿ ïðîôèëè ïîëüçîâàòåëåé default_profile = "cn=radprofile,ou=dialup,dc=test,dc=ru" # profile_attribute = "radiusProfileDn" access_attr = "dialupAccess" #  äàííîì àòðèáóòå ïðåäïîëàãàåòñÿ õðàíåíèå ïàðîëÿ # ïîëüçîâàòåëÿ password_attribute = "userPassword" # Àòðèáóòû äëÿ ïåðåâîäà ôîðìàòà çíà÷åíèé ldap => radius dictionary_mapping = ${raddbdir}/ldap.attrmap # Îñòàëüíàÿ ÷àñòü óáðàíà, ò.ê. íå çàñëóæèâàåò îòäåëüíîãî # âíèìàíèÿ
# Ïåðâàÿ òàáëèöà õðàíèò çàïèñè íà÷àëà ñîåäèíåíèÿ (start), # âòîðàÿ – çàïèñè îêîí÷àíèÿ ñîåäèíåíèÿ (stop). Åñëè îíè # ñîâïàäàþò, òî õðàíÿòñÿ â îäíîé òàáëèöå. acct_table1 = "radacct" acct_table2 = "radacct" # Òàáëèöà àâòîðèçàöèè è óñòàíîâêè òèïà àóòåíòèôèêàöèè authcheck_table = "radcheck" authreply_table = "radreply" # Ãðóïïîâûå òàáëèöû groupcheck_table = "radgroupcheck" groupreply_table = "radgroupreply" # Ñîîòâåòñòâèå ïîëüçîâàòåëåé ãðóïïàì usergroup_table = "usergroup" # Remove stale session if checkrad does not see a # double login deletestalesessions = yes # Âñå sql-çàïðîñû âûâîäÿòñÿ â ðåæèìå îòëàäêè radiusd -x sqltrace = yes sqltracefile = /usr/local/var/log/radius/sqltrace.sql # Êîëè÷åñòâî ñîåäèíåíèé ñ ñåðâåðîì. Ïðè áîëüøîé çàãðóçêå # ðåêîìåíäóåòñÿ óâåëè÷èòü. num_sql_socks = 5 # ×èñëî ñåêóíä, ïåðåä òåì êàê ñåðâåð ïðåäïðèíèìàåò # ïîâòîðíóþ ïîïûòêó ñîåäèíåíèÿ, åñëè ïðîèçîø¸ë ñáîé # ñîåäèíåíèÿ ñ mysql. connect_failure_retry_delay = 60
Для проверки сервера используется утилита radtest (она присутствует во всех проверенных мною серверах). Формат её использования таков: radtest user_name password radius_server nas_port secret
Например, если существует пользователь testuser с паролем testing, то формат команды будет таков: $radtest testuser testing radius.test.ru 1 radius_secret
Если же у вас что-то не работает (знаю по опыту – так бывает часто, даже если всё вроде правильно сделал, напишешь что-нибудь вроде dev/null, вместо /dev/null, а потом ищешь недостающий файл), то очень может помочь опция отладки radiusd -x. При этом radius не вызывает fork, и все отладочные данные выводятся на терминал. В таком режиме как сервер он работать практически не может, зато будет ясно, какие файлы он прочитал и что он делает. Вкупе с утилитой radtest это может помочь решить любые проблемы. Ещё советую включить в файле radiusd.conf запись в логи, это поможет выявить проблемы безопасности. Иногда более целесообразно применять совместно с radius ldap, т.к. при большом количестве пользователей наличие единого источника данных о
10
}
Учтите ещё, что при компиляции radius с ldap надо иметь нужные библиотеки, иначе модуль не скомпилируется. Ну и конечно же, нужно включить аутентификацию через ldap. Делается это стандартным раскомментированием строк ldap в секциях authorize и authenticate (см. описание работы через sql). Для указания использования аутентификации через ldap данного пользователя необходимо устанавливать AV-пару Auth-Type = ldap. В частности, можно для этого применить оператор Auth-Type := ldap. Заметьте также, что ldap не различает регистр символов, поэтому возможно возникновение проблем. Для этого в radius.conf надо включить «lower_user = yes» и «lower_time = before» в основной секции (см. выше). Кроме этого, в сервер ldap необходимо включить файл схемы RADIUS-LDAPv3.schema (находится в исходниках в подкаталоге doc). Отдельного разговора заслуживает тема учёта или аккаунтинга. Фактически сервер radius состоит из двух частей: сервера авторизации и аутентификации и сервера учёта. Учёт может выполняться через различные источники, например, через sql или простые файлы. Единственное условие для работы аккаунтинга – правильная настройка NAS (далее приведён пример конфигурации маршрутизатора Cisco). Аккаунтинг может выполняться либо через внешние скрипты (файл acct_users, для livingston-radius этот метод является единственным), либо через внутренние настройки. Далее будет рассматриваться лишь второй способ, т.к. о структуре файла acct_users я уже говорил выше. В файле radiusd.conf существует секция accounting, у меня она выглядит так: accounting { # Äàííûé ìîäóëü èñïîëüçóåòñÿ äëÿ ñîçäàíèÿ óíèêàëüíîãî # èäåíòèôèêàòîðà ïàêåòà àêêàóíòèíãà, ò.ê. ýòî òðåáóþò # ìíîãèå NAS, ïîýòîìó ýòîò ìîäóëü îáû÷íî íåîáõîäèìî âêëþ÷àòü acct_unique # Äàííûé ìîäóëü ïîçâîëÿåò ñîçäàâàòü êàæäûé ÷àñ ôàéë ñ # èíôîðìàöèåé î ïîëüçîâàòåëå. Ôàéëû ñîçäàþòñÿ ïî óìîë÷àíèþ # â ôîðìàòå #detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
администрирование # # # # # # # # # # #
detail Ìîäóëü ñ÷åò÷èêà - çàñëóæèâàåò îòäåëüíîãî ðàçãîâîðà counter Ñòàíäàðòíûé wtmp-ôîðìàò unix utmp-ôàéë, ñîäåðæàùèé èìåíà ïîëüçîâàòåëåé è ïîðòû NAS radutmp utmp ôàéë, íå ñîäåðæàùèé èì¸í ïîëüçîâàòåëåé, ïîýòîìó äîñòóïíûé âñåì äëÿ ÷òåíèÿ sradutmp Ìîäóëü àêêàóíòèíãà ÷åðåç sql sql
}
Чтобы разобраться подробнее, необходимо выяснить, что же содержится в пакетах аккаунтинга (взято из документации к серверу radacct, о котором будет рассказано далее). Следующие атрибуты пакета Accounting-Request считаются обязательными: Acct-Status-Type – подтип пакета: Start (начало сессии), Stop (конец сессии) или Alive; NAS-IP-Address – IP-адрес NAS; Acct-Session-Id – идентификатор сессии NAS; User-Name – идентификатор пользователя (с возможным префиксом или суффиксом); NAS-Port – номер порта NAS. Используются также следующие опциональные атрибуты, динамически изменяемые в процессе сессии: NAS-Port-Type – тип порта NAS, по умолчанию – Async; Service-Type – тип сервиса, по умолчанию – Login; Framed-Protocol – протокол, по умолчанию – PPP (Service-Type=Framed); Framed-IP-Address – IP-адрес клиента (ServiceType=Framed); Login-IP-Host – IP-адрес сервера (Service-Type=Login); Acct-Delay-Time – задержка в предоставлении сервиса; Called-Station-Id – идентификатор вызываемой стороны (номер телефона?); Calling-Station-Id – идентификатор вызывающей стороны (номер телефона?). Следующие атрибуты определяются по окончании сессии: Acct-Session-Time – время занятия в текущей сессии; Acct-Input-Octets – количество принятых байт; Acct-Output-Octets – количество отосланных байт; Acct-Input-Packets – количество принятых пакетов; Acct-Output-Packets – количество отосланных пакетов. После этого можно понять общие принципы работы системы учёта – при успешной аутентификации пользователя на radius-сервере NAS инициирует сессию аккаунтинга, по завершении которой выдаются итоговые данные. Данные учёта могут анализироваться внешними системами или самим radius-сервером. Приведу простой пример – организацию учёта через mysql: в секции аккаунтинга файла radiusd.conf должен быть модуль sql; в настройках mysql (sql.conf) должна быть определена таблица для учёта: # Äëÿ çàïèñåé acct_table1 = # Äëÿ çàïèñåé acct_table2 =
№4(5), апрель 2003
î íà÷àëå ñåññèè "radacct" î êîíöå ñåññèè "radacct"
таблица учёта создаётся автоматически при создании структуры базы данных radius (описано выше). После настройки собственно учёта необходимо продумать политику ограничения доступа. Для этого существуют счётчики. Здесь я приведу пример счётчика sql. Счётчик работает по принципу периодической проверки данных учёта и на основании этого принимается решение о дальнейшей работе пользователя. Для этого счётчик должен быть добавлен в секцию authorize файла radiusd.conf. Конфигурацию счётчика будем хранить в файле sqlcounter.conf, имеющим приблизительно такой формат (взято из документации к серверу freeradius): # Ñ÷¸ò÷èê îáùåãî âðåìåíè sqlcounter noresetcounter { counter-name = Max-All-Session-Time # Ïðîâåðêà îïðåäåë¸ííîãî àòðèáóòà â òàáëèöå radcheck check-name = Max-All-Session # Èñïîëüçóåìûé ïðîöåññ sql sqlmod-inst = sql # Ïîëå, ïî êîòîðîìó ïðîèñõîäèò ðàñ÷¸ò âðåìåíè key = User-Name # Ñáðîñ ñ÷¸ò÷èêà, â äàííîì ñëó÷àå ñ÷¸ò÷èê íå ñáðàñûâàåòñÿ reset = never # SQL-çàïðîñ, âûïîëíÿåìûé ñ÷¸ò÷èêîì query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'" } # Ñ÷åò÷èê ñáðàñûâàåòñÿ åæåäíåâíî sqlcounter dailycounter { driver = "rlm_sqlcounter" counter-name = Daily-Session-Time check-name = Max-Daily-Session sqlmod-inst = sql key = User-Name # Ñáðîñ ñ÷¸ò÷èêà åæåäíåâíî reset = daily query = "SELECT SUM(AcctSessionTime - GREATEST ((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" } sqlcounter monthlycounter { counter-name = Monthly-Session-Time check-name = Max-Monthly-Session sqlmod-inst = sql key = User-Name reset = monthly query = "SELECT SUM(AcctSessionTime - GREATEST ((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" }
После этого в radiusd.conf включаем файл sqlcounter.conf в секции modules: modules { $INCLUDE
${confdir}/sqlcounter.conf
и включаем счётчик в секцию авторизации: authorize { ... noresetcounter dailycounter monthlycounter }
После этого счётчик не будет давать проходить авторизацию пользователям, исчерпавшим свой лимит времени. Для установления граничных значений счётчиков
11
администрирование используется таблица radcheck. Приведу некоторые примеры применения этой таблицы: Пользователь test1 может работать 15 часов (54000 секунд), тогда запись проверки данного пользователя должны выглядеть примерно так: test1
Max-All-Session := 54000, User-Password == "<cut>" Service-Type = Framed-User, Framed-Protocol = PPP
Вносим AV-пару Max-All-Session для пользователя: > INSERT into radcheck VALUES ('','test1', ↵ 'Max-All-Session',':=','54000');
Отметьте использование оператора :=. Таким образом атрибут Max-All-Session будет приобретать значение по умолчанию 54000. Можно также устанавливать пороги счетчика не для одного пользователя, а для группы – для этого используется таблица radgroupcheck. В общем, основной смысл записей в таблицах – установка значения атрибута, заданного в параметре счётчика check-name. Ещё учтите, что модуль sqlcounter работает, только если данные аккаунтинга направляются в sql. Кроме sqlcounter есть ещё обыкновенный счётчик – counter. Его использование очень похоже на sqlcounter, за исключением того, что обыкновенный счётчик выполняет функции модуля аккаунтинга и авторизации одновременно. Я не буду подробно останавливаться на этой теме по ряду причин. Желающие могут прочитать в конфигурационном файле radiusd.conf подробные комментарии к этому модулю. Очень важным недостатком вышеописанных счётчиков является отсутствие возможности отключить пользователя во время сессии при исчерпании его активов. Как было отмечено, счётчики работают на этапе авторизации, но никто не помешает пользователю, допустим, начать сессию и просидеть в день 24 часа из положенных 3-х. На следующий день счётчик может сброситься, и пользователь будет работать дальше. Не думаю, что это хорошо. Для решения этой проблемы используются различные биллинговые системы, основанные на управлении NAS при помощи SNMP. Одним из решений является использование отдельного сервера аккаунтинга (а затем настроить соответствующим образом перенаправление пакетов аккаунтинга в файле proxy.conf с помощью директивы accthost). Одним из таких серверов является radacct (http://soft.risp.ru/index.html). Отличительной особенностью является возможность работы с любым radius-сервером (учтите, что radacct не должен использовать тот же порт, что и radius-сервер) и замечательная документация на русском языке (http://soft.risp.ru/radacct/ docs.shtml). Сервер действительно рабочий и компилируется без проблем после ручной правки Makefile (нужно раскомментировать строки, касающиеся вашей системы). Так как radacct написан нашими программистами и имеет русскую документацию, то описывать его в данной статье я не буду. На этом можно было бы и завершить, но... Некоторые зададут совершенно закономерный вопрос: «А что нам с этого, у меня маршрутизатор в коробке лежит, а как его
12
заставить с radius работать?» Но это как раз одна из самых тривиальных частей настройки. Для начала добавляем запись в clients.conf, соответствующую IP-адресу данного маршрутизатора и на последнем указываем параметры radius-сервера (учтите, что ключ симметрического шифрования aka secret должен совпадать на маршрутизаторе и в файле clients.conf): # # # #
configure terminal aaa new-model ip radius source-interface Ethernet0 radius-server host {hostname | ip-address} [auth-port ↵ port-number]
[acct-port port-number] [timeout seconds] [retransmit ↵ retries] [key string] # aaa authorization network radius # aaa authorization exec radius # aaa authentication login radius_auth local radius # aaa authentication ppp ppp_auth radius # line [console | tty | vty] line-number [ending-line-number] (line)# login authentication radius_auth (line)# exit # interface async 6 (interface)# ppp authentication {chap | pap} ppp_auth (interface)# exit # aaa accounting network start-stop radius # aaa accounting connection start-stop radius # aaa accounting update periodic 1
Ну вот, собственно, и всё. Список полезных сайтов: http://www.freeradius.org – сайт одноимённого radiusсервера, есть интересные ссылки на другие ресурсы и списки рассылок. http://www.cisco.com – поиск слова radius выдаёт жидковатенький список, где, впрочем, есть весьма полезный документ «Configuring RADIUS Servers». Здесь данная уважаемая фирма даёт свои рекомендации по настройке своего оборудования для работы с radius, а также свои соображения о применимости radius в той или иной ситуации. Советую почитать всем сомневающимся. http://soft.risp.ru/index.html – radacct сервер + много дополнительных утилит для ISP. ftp://ftp.inep.net/pub/unix/radpppd.tgz – pppd для FreeBSD с поддержкой radius. http://sply.piter.net – ещё один патч для pppd для поддержки radius (в том числе системы учёта). http://www.google.com – STFW! Протокол молодой, поэтому информацию приходится собирать с миру по нитке. Если вы ищете качественный коммерческий сервер, то вам прямой путь сюда. Всем, кто решил работать с radius, советую подписаться на рассылки (см. www.freeradius.org), где очень много отзывчивых людей и, что меня удивило, довольно много русских (хотя это не повод писать в рассылку по-русски). P.S. Данная статья написана в стиле HOWTO. Я не привожу готовых примеров работы и не даю шаблонов для действия. Моя статья – попытка соединить разрозненную документацию и собственный опыт. Искренне надеюсь, что мой HOWTO поможет кому-нибудь в настройке своего radius-сервера. Ещё надеюсь, что ктонибудь из администраторов ISP поделится готовым примером работы radius.
FAQ Shell ВОПРОС: Как присвоить переменной результат выполнения команды? ОТВЕТ: Вопрос можно истолковать по-разному. Если имеется в виду присвоить переменной код завершения программы, то используется следующий синтаксис: ./some_prog RESULT=$?
На практике чаще используется проверка правильности выполнения последней команды с помощью переменной $? (при успешном завершении обычно возвращается нуль): ./some_prog if [ $? ne 0 ] then echo Bad exit code exit fi
У некоторых возникнет искушение сделать нечто подобное: echo Error!!! exit $?
Но к сожалению, такой вариант всегда возвращает нуль, т.к. последней командой было echo. В качестве решения проблемы можно присваивать код завершения сомнительной программы некой переменной, а потом безбоязненно с ней обращаться (учтите, операторы проверки [] также изменяют код завершения). Если же в данном вопросе имелся в виду не код завершения программы, а то что было выведено программой в stdout, тогда необходимо заключить команду в обратные кавычки:
ВОПРОС: Как выполнять арифметические действия над переменными? ОТВЕТ: Все переменные в shell являются строками, но существует возможность оценки числовых выражений. Для объявления числовой переменной можно воспользоваться командой let: let a=6 let b=a*2 let c=a%4 let d=c/2 echo a=$a echo b=$b echo c=$c echo d=$d
Результат работы: a=6 b=12 c=2 d=1
Второй способ – оценка cтроковых выражений командой expr: $a=2 $b=2 expr $a + $b
Выведет число 4. Заметьте, что просто $a + $b будет преобразовано в 2 + 2. ВОПРОС: Что означают перенаправления в циклах? ОТВЕТ: Смысл такой: после каждого шага цикла значение переменной цикла считывается или передаётся в конвейер. Пример удаления всех исполняемых файлов, если им соответствуют файлы .c (т.е. удаление объектных файлов):
DATE=`date` for x in *; do xargs rm -f
ВОПРОС: Где можно найти полное описание встроенных переменных bash? ОТВЕТ: ht tp://ln.com.ua/~openxs/projects/man/solaris8/ bash.html#variables ВОПРОС: Существует ли простой способ программно создать файл, содержащий несколько строк? ОТВЕТ: Да, существует. Это очень часто употребляемый прием для создания многострочных файлов с возможностью подстановки переменных скрипта: cat > cfg <<EOT name = $a And this file was generated with $EDITOR many other lines... ... EOT
[ -x $x -a -f $x.c ] && echo $x; done |
Заметьте, что если последняя команда цикла ложна, то перенаправления переменной цикла не происходит. В данном примере используется именно эта возможность. ВОПРОС: Как экранировать кавычки? ОТВЕТ: Вопрос заслуживает отдельного внимания, например, когда внутри кавычек есть другие кавычки: двойные(") – экранируются обратным слэшем, например echo "\"" выведет просто символ "; одинарные(') – обратный слэш не спасает – приходится использовать восьмеричный код символа 047: echo '\047$PATH\047' выведет '$PATH', в Linux необходимо для echo указать опцию -е; обратные(`) – экранируются аналогично двойным, т.е. обратным слэшем. Составил Всеволод Стахов
№4(5), апрель 2003
13
администрирование
СОЗДАЕМ VPN
НА ОСНОВЕ VTUN 14
администрирование
АНДРЕЙ БЕШКОВ №4(5), апрель 2003
Компания, в которой я работаю, довольно быстро развивается, появляются новые филиалы, соответственно, увеличивается количество внутренних сетей. Настал момент, когда появилась необходимость соединить эти разрозненные сети в единое пространство. Нам нужна надежная, безопасная и защищенная от «подглядывания» система связи. Единственной возможностью выполнить все предъявленные требования является создание своей корпоративной VPN. В сети так много сайтов, объясняющих каждому, как престижно иметь в своем распоряжении VPN. Но ни один из них не публикует детального описания, как этого добиться. Побродив несколько дней по просторам Интернета, но так и не найдя подробного описания процесса развертывания VPN, решил написать об этом сам. Я буду использовать vtun, написанный Максимом Краснянским на основе пакета VPPP. Главная страница проекта vtun находится по адресу: http://vtun.sourceforge.net. Вы можете спросить, почему именно vtun. Ведь можно было использовать что-либо вроде PPP поверх SSH, IPSEC или GRE. Возможно, в ближайшее время я напишу о работе с IPSEC или OpenVPN. Главными достоинствами vtun являются простота в установке, гибкость настройки и отличная документация. Vtun достаточно хорошо защищает от атак, основанных на действиях злоумышленника, находящегося между двумя машинами туннеля. Этот тип атак обычно называют MIM (Men In the Middle), чаще всего злоумышленник пытается выполнить одно или несколько из следующих действий – изменить содержимое передаваемых пакетов, повторно проиграть записанную последовательность пакетов, выдать себя за одну из сторон, участвующих в передаче данных. Поддерживаются разнообразные типы туннелей IP, Ethernet, PPP, SLIP. В качестве туннеля можно использовать даже pipe и TTY. Для шифрования потока данных используется OpenSSL. Доступны алгоритмы blowfish с ключом в 128 бит или MD5 с ключом той же длины. Компрессия потока производится с помощью библиотек lzo или zlib. Следует отметить, что zlib работает только с tcp-туннелями. Если в вашей операционной системе нет библиотек zlib или lzo, и вы не смогли установить их самостоятельно, значит придется отключить компрессию. Это снизит скорость передачи данных. Но все же не окажет решающего влияния на работу vtun. Официально vtun работает на следующих операционных системах: Linux, Solaris, FreeBSD, NetBSD, OpenBSD и другие BSD-клоны. В принципе vtun должен работать на любой платформе, для которой есть универсальный драйвер tun/tap. Устройство tun используется для туннелирования IP-фреймов, а tap соответственно для Ethernet-фреймов. С помощью tun/tap пользовательские программы получают возможность самостоятельно обрабатывать IP-пакеты. Для некоторых операционных систем необходимо перекомпилировать ядро с поддержкой tun/tap-устройств. Vtun работает на основе клиент-серверной модели. Соответственно, для создания туннеля на одном из хостов, демон vtun должен быть запущен как сервер, а на другом как клиент. Если между клиентом и сервером находится брандмауэр, значит необходимо разрешить прохождение пакетов,
15
администрирование адресованных на порт 5000. Попытки провести vpn-туннель через систему с NAT, скорее всего, завершатся фатально. Проблема в том, что NAT изменяет содержимое проходящих пакетов. Поэтому ни один пакет не пройдет проверку контрольной суммы. После запуска демон, выполняющий роль сервера, по умолчанию начинает слушать порт 5000. При попытке подсоединиться на этот порт происходит аутентификация клиента на основе пароля, записанного в конфигурационном файле /usr/local/etc/vtund.conf. Пароль применяется для аутентификации клиента всего лишь один раз на протяжении всей сессии. После успешной аутентификации сервер с помощью функции fork запускается еще один демон vtun, которому передается клиентское соединение. Новый демон будет существовать до тех пор, пока соединение не будет разорвано. В то же время родительский демон продолжает ждать новых соединений. Это значит, что единственный демон может обслуживать множество одновременных подключений. Количество поддерживаемых соединений зависит только от мощности процессора и наличия оперативной памяти. С помощью ключей командной строки можно указать другое местоположение конфигурационного файла. Это дает нам возможность запустить на одном хосте несколько демонов vtun, ожидающих соединений на разных портах. Каждый из демонов будет использовать собственные настройки. Соответственно, некоторые из них могут быть серверами, а другие клиентами. Это дает нам возможность развернуть множество не пересекающихся между собой VPN.
Давайте представим, что у нас есть филиал, магазин и офис, использующие адреса из пространства частных сетей. Необходимо эти подразделения соединить с помощью VPN. Для этих целей мы будем использовать реальные IP-адреса, выданные нам провайдером из сети 80.80.20.0. Для соединения сетей нам понадобятся три компьютера. На каждом из них будет по три сетевых интерфейса. Два реальных и один виртуальный. Более подробно это показано в приведенной выше таблице. Схема соединения сетей – на рисунке. Это значит, что каждая из наших сетей может напрямую взаимодействовать с двумя другими. Далее мы опишем установку vtun для каждой из операционных систем. Клоны BSD-систем, в отличие от Linux, сразу после установки по умолчанию имеют работающее и правильно настроенное устройство tun. Поэтому для FreeBSD нам не придется его создавать. По большей части установка одинакова для всех систем. Наиболее подробно будет обсуждаться процедура установки программного обеспечения для FreeBSD по причине наибольшей любви к этой системе. В описаниях инсталляции для других систем внима-
16
ние будет особо заостряться на отличиях. Это должно дать возможность легко поставить и настроить vtun для любой из трех обсуждаемых систем. Под FreeBSD установить vtun можно тремя способами: с помощью пакетов, через порты или ручным способом. Мне больше нравится третий вариант, так как он дает гораздо большую возможность для контроля над происходящим. Итак, приступим к установке программного обеспечения по третьему способу. Берем исходник портированной библиотеки lzo отсюда http://www.freebsd.org/cgi/pds.cgi?ports/archivers/lzo. Если не удалось скачать, то берем дистрибутив здесь: http://www.oberhumer.com/opensource/lzo/. Распаковываем и собираем в комплектации по умолчанию. # # # # # # #
tar zxvf lzo-1.08.tar.gz cd lzo-1.08 ./configure make make check make test make install
Скачиваем исходный код vtun. Конфигурируем его c указанием, где искать библиотеки и заголовочные файлы библиотеки lzo. # tar zxvf vtun-2.5.tar.gz # cd vtun # ./configure —with-lzo-headers=/usr/local/include/ — with-lzo-lib=/usr/local/lib
Случается, что команда ./configure завершается с
администрирование ошибкой. Вероятнее всего, это означает, что система не смогла обнаружить библиотеку lzo. Если вам не удастся самостоятельно избавиться от этой ошибки, значит придется отключить поддержку lzo. Vtun может работать и без библиотеки lzo. Для этого выполните команду: # ./configure —disable-lzo
А затем, как положено, выполняем компиляцию и установку. # make # make install
Если все прошло гладко, значит пришло время заняться конфигурационными файлами каждой из трех машин. В нашем случае машина vpn_office будет выполнять роль сервера, соответственно, vpn_filial и vpn_shop станут клиентами. Конфигурационный файл vtun для FreeBSD находится в директории /usr/local/etc/vtund.conf. Давайте посмотрим, из чего состоит конфигурационный файл хоста vpn_office. options { port 5000; ifconfig /sbin/ifconfig; route /sbin/route; } default { compress lzo:9; speed 0; } filial {{
# îïèñûâàåì êëèåíòà ôèëèàë
pass secret; type tun; proto udp; encr yes; keepalive yes;
up { ifconfig "%% 192.168.0.2 192.168.0.1 netmask 255.255.255.255 mtu 1450 up"; route "add -net 192.168.20.0/24 192.168.0.1"; }; down { ifconfig "%% down"; route "delete 192.168.20.0"; }; }
shop { pass secret; type tun;; proto udp; encr yes; keepalive yes;
# îïèñûâàåì êëèåíòà ìàãàçèí
up { ifconfig "%% 192.168.0.2 192.168.0.3 netmask 255.255.255.255 mtu 1450 up"; route "add -net 192.168.40.0/24 192.168.0.3"; }; down { ifconfig "%% down"; route "delete 192.168.40.0"; }; }
№4(5), апрель 2003
Разделы options и default являются глобальными и остаются неизменными на протяжении всего конфигурационного файла. Это значит, что параметры, установленные внутри этих разделов, влияют на все последующие блоки конфигурационного файла. Давайте подробно рассмотрим содержимое вышеназванных разделов. port – номер порта, на котором демон будет ждать входящие соединения от клиентов; ifconfig – путь к программе ifconfig. Эта программа необходима для управления сетевыми интерфейсами; route – путь к программе route. Используется для работы с маршрутами прохождения сетевых пакетов; compress – опция управления сжатием передаваемых данных. Может принимать значения lzo, zlib и no. Этой опцией можно указать, какую библиотеку мы будем использовать для компрессии потока. Второе значение описывает степень сжатия. Чем больше число, тем сильнее будет сжатие. Но в то же время стоит помнить: верхние значения сжатия заставят демона потреблять гораздо больше ресурсов процессора . Максимальное значение сжатия равно 9. Если компиляцию с поддержкой lzo выполнить не удалось, то можно отключить сжатие, установив значение compress no; speed – ограничение, накладываемое на скорость передачи данных. Позволяет притормозить передачу данных особо жадных до трафика клиентов; pass – пароль, используемый при аутентификации входящего соединения; type – тип соединения. Может принимать значения tun, ether, pipe, tty; proto – описывает протокол, используемый для передачи данных. Может принимать значения udp и tcp; encr – включаем шифрование соединения. Может принимать значения no или yes; keepalive – пытаться восстанавливать соединение, если оно будет прервано. Может принимать значения no или yes. Секция up описывает действия, выполняемые при удачном соединении. Рассмотрим ее на примере клиента filial. Внутри мы описываем способ конфигурирования виртуального интерфейса с адресом 192.168.0.2. Затем привязываем этот интерфейс соединением типа точка точка к другому виртуальному интерфейсу 192.168.0.1. И завершаюшим штрихом настраиваем маршрутизацию для сети 192.168.20.0/24 через интерфейс с адресом 192.168.0.1. Также стоит рассмотреть секцию down, описывающую действия, выполняемые при разрыве соединения. Нам необходимо удалить виртуальный интерфейс tun и разрушить маршрутизацию для сети 192.168.40.0/24. Комбинацией опций type и proto можно создать разные виды туннелей: Ethernet-туннель type ether ; proto udp; up { ifconfig «%% xxxxxxxx»; };
Ethernet-туннель позволяет работать с любым протоколом, работающим поверх Ethernet. Например, IP, IPX,
17
администрирование Appletalk, DECnet. Компрессию можно производить, используя lzo. Если lzo не работает, то нужно установить proto tcp и compress zlib. IP-туннель type tun; proto udp; up { ifconfig "%% xxxxxxxx"; };
SLIP- или PPP-туннель type tcp; proto udp; up { ifconfig "%% xxxxxxxx"; };
pipe- или TTY-туннель type tun; proto tcp; up { program /xx/xx "xyyyyyyyyy"; };
TTY- или pipe-туннель может работать с любыми программами. Возможно применение сжатия, шифрования и даже ограничения пропускной способности. Для туннеля типа pipe лучше всего использовать протокол proto tcp. Можно, конечно, использовать и proto udp, но работать такой туннель будет нестабильно. Итак, разобравшись с основной теорией работы туннеля, давайте перейдем к настройке хоста vpn_shop. Машина vpn_shop работает под управлением Solaris 2.7. Для нее установка программного обеспечения будет немного отличаться. Кроме упомянутых раньше lzo и vtun, нам понадобятся исходные коды универсального TUN/TAPдрайвера и библиотеки OpenSSL. Процедура установки универсального TUN/TAP драйвер хорошо автоматизирована и довольно-таки проста: # # # #
tar zxvf tun-1.0.tar.gz cd tun-1.0 ./configure make install
В стандартной поставке Solaris 2.7 OpenSSL отсутствует, как и библиотека lzo, поэтому будем ставить их сами. Взять дистрибутив OpenSSL можно на сайте проекта openssl.org. С помощью ключей указываем, что библиотеки должны установиться в /usr/local/lib, заголовочные файлы по умолчанию в /usr/local/include/openssl, а все остальное в /usr/local/openssl. # tar openssl-0.9.5a.tar.gz # cd openssl-0.9.5a # ./configure —prefix=/usr/local —openssldir=/usr/local/ openssl # make # make test # make install
Пришло время собрать lzo. Как всегда, делаем это вручную: # tar zxvf lzo-1.08.tar.gz
18
# # # # # #
cd lzo-1.08 ./configure make make check make test make install
Постепенно мы добрались и до vtun, обратите особое внимание на ключи команды configure. # tar zxvf vtun-2.5.tar.gz # cd vtun # ./configure —with-lzo-headers=/usr/local/include/ — with-lzo-lib=/usr/local/lib —with-ssl-lib=/usr/local/lib — with-ssl-headers=/usr/local/include/openssl # make # make install
Если компиляция прошла без ошибок, значит мы сделали все правильно и можем переходить к конфигурированию vtun. Файл настроек vtun находится в /usr/local/etc/ vtund.conf. Вносим в него следующие: options { port 5000; ifconfig /usr/sbin/ifconfig; route /usr/sbin/route; } default { compress lzo:9; speed 0; } shop { pass secret; type tun; proto udp; encr yes; keepalive yes; # îáðàòèòå âíèìàíèå íà ñèíòàêñèñ êîìàíä ifconfig è route # åñòü îòëè÷èÿ îò FreeBSD â îáîçíà÷åíèè ñåòåé, # à òàêæå â ñîçäàíèè è ðàçðóøåíèè ðîóòèíãà up { ifconfig "%% 192.168.0.3 netmask 255.255.255.0 192.168.0.2 up"; route "add net 192.168.30.0 192.168.0.2 1"; }; down { ifconfig "%% down"; route "delete net 192.168.30.0 192.168.0.2 1"; }; }
Для того чтобы при первом соединении с другими машинами команда route отработала корректно, нужно добавить в файл /etc/netmasks запись такого вида: 192.168.30.0 255.255.255.0
Закончив с Solaris, примемся за работу над Linux. К сожалению, с ним все не так просто, как с двумя предыдущими системами. Перед тем как воспользоваться услугами vtun, нужно вручную создать устойство tun, в стандартной поставке оно отсутствует. Наш Linux работает на ядре версии 2.4. Значит файл устройства будет находиться в /dev/net/tun. Создадим нужное нам устройство с помощью команды:
администрирование # mknod /dev/net/tun c 10 200
Установка программного обеспечения под Debian длилась дольше всего и для меня превратилась в долгую и мучительную процедуру. С помощью apt-get ставим пакет vtun, поставлявшийся вместе с Debian. Заставить его работать мне так и не удалось. Но ставить все равно стоит, потому что он разложит необходимые файлы по местам и создаст между ними нужные взаимосвязи. # apt-get install vtun
Путем чтения документации и общения с друзьями было выяснено, что для того чтобы все заработало, необходимо установить пакеты разработчика liblzo-dev и libssldev. Что мы с радостью и выполняем.
up { ifconfig "%% 192.168.0.1 pointopoint 192.168.0.2 mtu 1450"; route "add -net 192.168.30.0/24 192.168.0.2"; }; down { ifconfig "%% down"; route "delete -net 192.168.30.0"; }; }
Скачать все конфигурационные файлы можно здесь: http://onix.opennet.ru/files/vtun-cfg.tar.gz. В связи с тем, что в файлах vtund.conf находится пароль соединения, доступ к ним должен иметь только пользователь root. После всех этих манипуляций можно запускать vtun. На машине vpn_office запускаем демон в режиме сервера. vpn_office# vtund -s
# apt-get install liblzo-dev # apt-get install libssl-dev
Заметного сдвига это не принесло, и я принялся рыскать в поисках решения по Интернету. Постепенно пришло понимание, что таких бедолаг, как я, довольно много. После более тщательного исследования выяснилось, что из-за изменений, внесенных в ядро на пути к версии 2.4, vtun пакет от Debian и не должен был работать. Теперь нам нужно установить пакет демона vtund.
На другой консоли смотрим на сообщения об ошибках. vpn_office# tail -f /var/log/messages
Если ошибок не появилось, значит все у нас хорошо. Соответственно, на хостах vpn_shop и vpn_filial запускаем демоны в режиме клиента. vpn_shop# vtund -p shop 80.80.20.2 vpn_filial# vtund -p filial 80.80.20.2ô
# apt-get install vtund
После всех этих приключений берем стандартный дистрибутив vtun, используемый нами для остальных систем, и компилируем его с настройками по умолчанию. Скомпилировав исходный код, команду make install не выполняем. Вместо нее вручную заменяем старый выполняемый файл, находящийся в директории /usr/local/sbin/, своим новым файлом. Для ядра 2.4 необходимо, чтобы модуль поддержки tun был загружен в оперативную память. Такого результата можно добиться с помощью команды modprobe tun. После этого нам необходимо включить поддержку vtun в ядре. Ищем в тексте ядра строку Universal TUN/TAP device driver (CONFIG_TUN). Я думаю, вы знаете, что нужно делать, чтобы пересобрать ядро. После этого в конфигруационный файл vtun нужно внести такой текст. options { port 5000; ifconfig /sbin/ifconfig; route /sbin/route; } default { compress lzo:9; speed 0; } filial { pass secret; type tun; proto udp; encr yes; keepalive yes;
№4(5), апрель 2003
Снова ждем ошибок. Не дождавшись, смотрим, какие сетевые интерфейсы у нас подняты на каждой из машин. Больше всего нас интересуют интерфейсы vtun0 и vtun1. У вас должны получиться примерно такие данные: vpn_office# ifconfig -u ed0: flags=8843 mtu 1500 inet 192.168.30.251 netmask 0xffffff00 broadcast 192.168.30.255 inet6 fe80::280:48ff:fedf:66f7%ed0 prefixlen 64 scopeid 0x1 ether 00:80:48:df:66:f7 ed1: flags=8843 mtu 1500 inet 80.80.20.2 netmask 0xffffff00 broadcast 80.80.20.255 inet6 fe80::240:95ff:fe45:9ce2%ed1 prefixlen 64 scopeid 0x2 ether 00:40:95:45:9c:e2 lo0: flags=8049 mtu 16384 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x5 inet 127.0.0.1 netmask 0xff000000 tun0: flags=8051 mtu 1450 inet6 fe80::280:48ff:fedf:66f7%tun0 prefixlen 64 scopeid 0x8 inet 192.168.0.2 --> 192.168.0.3 netmask 0xffffffff Opened by PID 1143 tun1: flags=8051 mtu 1450 inet6 fe80::280:48ff:fedf:66f7%tun1 prefixlen 64 scopeid 0x9 inet 192.168.0.2 --> 192.168.0.1 netmask 0xffffffff Opened by PID 1150 vpn_shop# ifconfig -a lo0: flags=849 <UP,LOOPBACK,RUNNING,MULTICAST> mtu 8232 inet 127.0.0.1 netmask ff000000 le0: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 192.168.40.251 netmask ffffff00 broadcast 192.168.40.255 ether 00:80:48:b6:43:5f le1: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 80.80.20.3 netmask ffffff00 broadcast 80.80.20.255 ether 00:02:b3:65:0f:47 tun0: flags=8d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 192.168.0.3 --> 192.168.0.2 netmask ffffffff ether 0:0:0:0:0:0 vpn_filial#
/sbin/ifconfig
19
администрирование vpn_office# ifconfig -u ed0: flags=8843 mtu 1500 inet 192.168.30.251 netmask 0xffffff00 broadcast 192.168.30.255 inet6 fe80::280:48ff:fedf:66f7%ed0 prefixlen 64 scopeid 0x1 ether 00:80:48:df:66:f7 ed1: flags=8843 mtu 1500 inet 80.80.20.2 netmask 0xffffff00 broadcast 80.80.20.255 inet6 fe80::240:95ff:fe45:9ce2%ed1 prefixlen 64 scopeid 0x2 ether 00:40:95:45:9c:e2 lo0: flags=8049 mtu 16384 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x5 inet 127.0.0.1 netmask 0xff000000 tun0: flags=8051 mtu 1450 inet6 fe80::280:48ff:fedf:66f7%tun0 prefixlen 64 scopeid 0x8 inet 192.168.0.2 --> 192.168.0.3 netmask 0xffffffff Opened by PID 1143 tun1: flags=8051 mtu 1450 inet6 fe80::280:48ff:fedf:66f7%tun1 prefixlen 64 scopeid 0x9 inet 192.168.0.2 --> 192.168.0.1 netmask 0xffffffff Opened by PID 1150 vpn_shop# ifconfig -a lo0: flags=849 <UP,LOOPBACK,RUNNING,MULTICAST> mtu 8232 inet 127.0.0.1 netmask ff000000 le0: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 192.168.40.251 netmask ffffff00 broadcast 192.168.40.255 ether 00:80:48:b6:43:5f le1: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 80.80.20.3 netmask ffffff00 broadcast 80.80.20.255 ether 00:02:b3:65:0f:47 tun0: flags=8d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 192.168.0.3 --> 192.168.0.2 netmask ffffffff ether 0:0:0:0:0:0 vpn_filial# /sbin/ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Bcast:127.255.255.255 Mask:255.0.0.0 UP BROADCAST LOOPBACK RUNNING MTU:3584 Metric:1 RX packets:13072 errors:0 dropped:0 overruns:0 frame:0 TX packets:23921 errors:0 dropped:0 overruns:0 carrier:0 Collisions:0 eth0 Link encap:Ethernet HWaddr 00:80:48:c7:c7:9b inet addr:192.168.20.251 Bcast:192.168.20.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:78 errors:0 dropped:0 overruns:0 frame:10 TX packets:13 errors:0 dropped:0 overruns:0 carrier:0 Collisions:0 Interrupt:3 eth1 Link encap:Ethernet HWaddr 00:02:2e:f1:17:26 inet addr:80.80.20.1 Bcast:80.80.20.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:49 errors:1 dropped:0 overruns:0 frame:15 TX packets:22 errors:0 dropped:0 overruns:0 carrier:0 Collisions:1 Interrupt:4 tun0:
Link encap:Point-to-Point Protocol inet addr:192.168.0.1 P-t-P: 192.168.0.2 Mask:255.255.255.0 UP POINTPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:155 errors:0 dropped:0 overruns:0 frame:15 TX packets:162 errors:0 dropped:0 overruns:0 carrier:0 Collisions:0
Теперь можно попробовать, как работает наша виртуальная частная сеть. Выполним команду ping на хостах vpn_filial и vpn_office. Таким образом мы сможем проверить прохождение пакетов от vpn_filial к vpn_office и от vpn_shop к vpn_office. vpn_filial# ping 192.168.30.251 PING 192.168.30.251 (192.168.30.251): 56 64 bytes from 192.168.30.251: icmp_seq=0 64 bytes from 192.168.30.251: icmp_seq=1 64 bytes from 192.168.30.251: icmp_seq=2 64 bytes from 192.168.30.251: icmp_seq=3
20
data bytes ttl=64 time=5.788 ttl=64 time=5.724 ttl=64 time=5.683 ttl=64 time=5.685
ms ms ms ms
--- 192.168.30.251 ping statistics --4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max = 5.683/5.720/5.788 ms vpn_office# ping 192.168.40.251 PING 192.168.30.251 (192.168.30.251): 56 64 bytes from 192.168.40.251: icmp_seq=0 64 bytes from 192.168.40.251: icmp_seq=1 64 bytes from 192.168.40.251: icmp_seq=2 64 bytes from 192.168.40.251: icmp_seq=3
data bytes ttl=64 time=6.092 ttl=64 time=5.785 ttl=64 time=5.851 ttl=64 time=5.826
ms ms ms ms
--- 192.168.30.251 ping statistics --4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max/stddev = 5.785/5.888/6.092/0.120 ms
Судя по всему, туннели исправно передают пакеты в обе стороны и все работает наилучшим образом. Теперь давайте проверим, как работает шифрование. Нужно посмотреть, что и в каком виде передается по интерфейсам tun0 – 192.168.0.2 и ed1 – 80.80.20.2. Давайте начнем прослушивание интерфейсов, участвующих в передаче данных, с помощью программы tcpdump. В то же время с машины vpn_shop начинаем пинговать интерфейс 192.168.40.251, принадлежащий машине vpn_office. vpn_office# tcpdump -i tun0 -lenx 13:33:14.573619 AF 2 84: 192.168.0.2 > 192.168.40.251: icmp: echo request 4500 0054 0cc3 0000 4001 c398 c0a8 0002 c0a8 28fb 0800 edcc c904 0000 ede7 cc3d 9505 0700 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 13:33:14.573665 AF 2 84: 192.168.40.251 > 192.168.0.2: icmp: echo reply 4500 0054 1b3f 0000 4001 b51c c0a8 28fb c0a8 0002 0000 f5cc c904 0000 ede7 cc3d 9505 0700 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 13:33:15.583143 AF 2 84: 192.168.0.2 > 192.168.40.251: icmp: echo request 4500 0054 0cc6 0000 4001 c395 c0a8 0002 c0a8 28fb 0800 42a6 c904 0100 eee7 cc3d 3e2c 0700 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 13:33:15.583194 AF 2 84: 192.168.40.251 > 192.168.0.2: icmp: echo reply 4500 0054 1b43 0000 4001 b518 c0a8 28fb c0a8 0002 0000 4aa6 c904 0100 eee7 cc3d 3e2c 0700 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 13:33:16.590000 AF 2 84: 192.168.0.2 > 192.168.40.251: icmp: echo request 4500 0054 0cc6 0000 4001 c395 c0a8 0002 c0a8 28fb 0800 42a6 c904 0100 eee7 cc3d 3e2c 0700 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 13:33:16.590120 AF 2 84: 192.168.40.251 > 192.168.0.2: icmp: echo reply 4500 0054 1b43 0000 4001 b518 c0a8 28fb c0a8 0002 0000 4aa6 c904 0100 eee7 cc3d 3e2c 0700 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
На предыдущем листинге явно видно содержимое тестовых ICMP-пакетов. А теперь внимательно посмотрим, в каком виде эти пакеты путешествуют по небезопасной сети 80.80.20.0/24.
администрирование vpn_office# tcpdump -i ed1 -lenx 13:33:14.573441 0:40:95:45:9c:e2 0:2:b3:65:f:47 0800 140: 80.80.20.2.5000 > 80.80.20.3.1035: udp 98 4500 007e 0cc4 0000 4011 a506 5050 1402 5050 1403 1388 040b 006a f9e2 0060 7db0 f6ef dd81 4638 917a 5a80 7f48 87d7 7bc9 459f 97f0 b95a 95cf 87b1 29ce b2d7 8f50 228e 6b8f eafb 1f5d ae9d 7518 2085 2da9 8c85 13:33:14.574798 0:2:b3:65:f:47 0:40:95:45:9c:e2 0800 140: 80.80.20.3.1035 > 80.80.20.2.5000: udp 98 4500 007e 1b40 0000 4011 968a 5050 1403 5050 1402 040b 1388 006a 998c 0060 7db0 f6ef dd81 4638 5390 c84e 886e 466d ffcd df10 9010 5995 fcdd b315 92fb 6a1d 8f50 228e 6b8f eafb 1f5d ae9d 7518 2085 2da9 8c85 13:33:15.582910 0:40:95:45:9c:e2 0:2:b3:65:f:47 0800 140: 80.80.20.2.5000 > 80.80.20.3.1035: udp 98 4500 007e 0cc7 0000 4011 a503 5050 1402 5050 1403 1388 040b 006a 28fd 0060 7db0 f6ef dd81 4638 3048 4e92 e692 1c3d 5fa3 c2a6 bc50 8fa5 79d3 c0c2 6537 c74b 1e84 b95e c8f8 6048 3d3c 4f33 32a4 25a2 2da9 8c85 13:33:15.584332 0:2:b3:65:f:47 0:40:95:45:9c:e2 0800 140: 80.80.20.3.1035 > 80.80.20.2.5000: udp 98 4500 007e 1b44 0000 4011 9686 5050 1403 5050 1402 040b 1388 006a cd92 0060 7db0 f6ef dd81 4638 f41d cb55 f37d 1229 dbb6 14f7 14d1 08e3 a204 5045 74a0 7807 1e84 b95e c8f8 6048 3d3c 4f33 32a4 25a2 2da9 8c85 13:33:15.593910 0:40:95:45:9c:e2 0:2:b3:65:f:47 0800 140: 80.80.20.2.5000 > 80.80.20.3.1035: udp 98 4500 007e 0cc7 0000 4011 a503 5050 1402 5050 1403 1388 040b 006a 28fd 0060 7db0 f6ef dd81 4638 3048 4e92 e692 1c3d 5fa3 c2a6 bc50 8fa5 79d3 c0c2 6537 c74b 1e84 b95e c8f8 6048 3d3c 4f33 32a4 25a2 2da9 8c85 13:33:15.594237 0:2:b3:65:f:47 0:40:95:45:9c:e2 0800 140: 80.80.20.3.1035 > 80.80.20.2.5000: udp 98 4500 007e 1b44 0000 4011 9686 5050 1403 5050 1402 040b 1388 006a cd92 0060 7db0 f6ef dd81 4638 f41d cb55 f37d 1229 dbb6 14f7 14d1 08e3 a204 5045 74a0 7807 1e84 b95e c8f8 6048 3d3c 4f33 32a4 25a2 2da9 8c85
Как мы могли убедиться, все пакеты движутся через публичную сеть в зашифрованном виде. Мы создали туннели VPN1 и VPN2 между тремя частными сетями. Теперь машина vpn_office сможет общаться с любой машиной из всех трех сетей. Но в то же время машины vpn_shop и vpn_filial могут взаимодействовать лишь с машиной vpn_office, но не друг с другом. При таком способе соединения сетей у нас получилась топология типа звезда. Такая конструкция не очень надежна. Если хост vpn_office по каким-либо причинам выйдет из строя, вся система VPN перестанет существовать. Чтобы избежать подобных плачевных результатов, нам необходимо создать резервный туннель VPN3 между хостами vpn_shop и vpn_filial. Это даст им возможность работать друг с другом напрямую, не полагаясь на хост vpn_office.
№4(5), апрель 2003
В файл конфигурации хоста vpn_shop добавим настройки нового туннеля. Я надеюсь, что вы уже можете самостоятельно разобраться в том, что они значат. filial_to_shop { pass secret; type tun; proto udp; encr yes; keepalive yes; up { ifconfig "%% 192.168.0.3 netmask 255.255.255.0 192.168.0.1 up"; route "add net 192.168.20.0 192.168.0.1 1"; }; down { ifconfig "%% down"; route "delete net 192.168.20.0 192.168.0.1 1"; };
Затем запускаем сервер: vpn_shop#
vtund -s
В свою очередь, в конфигурацию хоста vpn_filial добавим вот такие строки: filial_to_shop { pass secret; type tun; proto udp; encr yes; keepalive yes; up { ifconfig "%% 192.168.0.1 pointopoint 192.168.0.3 1450"; route "add -net 192.168.30.0/24 192.168.0.3"; };
mtu
down { ifconfig "%% down"; route "delete -net 192.168.30.0 "; };
А теперь запускаем клиента : vpn_shop# vtund -p filial_to_shop 80.80.20.1
Таким образом, у нас появляется еще один туннель. Я надеюсь, что заботясь о безопасности, вы догадались поменять во всех конфигурационных файлах пароль соединения. После этого необходимо перезапустить демонов и клиентов. Теперь главное – не забыть установить на клиентских машинах трех сетей правильные адреса шлюза по умолчанию. После того как эта работа будет завершена, можно со спокойной совестью отдыхать.
21
администрирование
НАСТРОЙКА INCOMING CONNECTIONS В LINUX
Users never read manuals... «man mgetty», секция «BUGS»
В любой фирме наверняка найдётся один-два человека, которым жизненно необходимо получать почту за пределами «офисной сети». Хорошо, если ваш шеф человек с понятием и свято чтит КЗОТ, тогда он просто скажет: «Ребята, в воскресенье нужно отдыхать!». А если нет? Тогда не остается ничего другого, кроме как отвлечься на пару минут от раскладывания пасьянса и сделать это. Для тех, кто еще не понял – в статье пойдет речь о том, как настроить удаленный доступ к серверу.
СЕРГЕЙ РОПЧАН Во избежание всевозможных вопросов, в том числе и системных (и да не нарветесь вы на kernel panic), на всякий случай уточняю: В качестве модема использовалась покрытая пылью коробочка с надписью «ZyXEL 228S». Подключалось это к серийному порту почтового сервера.
22
В качестве операционной системы стоял, стоит и будет стоять ASPLinux версии 7.2. Что ж, приступим.
ШАГ 1 После того, как модем должным образом подключен и сконфигурирован, например, утилитой kudzu, попробуем его для начала протестировать на
предмет поднятия трубки. Для этого запускаем программу /sbin/mgetty (не путать с mingetty!) следующим образом: mgetty -D -s 38400 -n 4 ttyS1
То есть указываем mgetty работать с модемом на линии /dev/ttyS1 только в режиме DATA (-D) со скоростью
администрирование 38400 (-s), а трубку поднимать только после четвертого гудка (-n). Если модем действительно подключен к этой линии (а не к ttyS0, например), то при попытке дозвона вы услышите ровно четыре длинных гудка, прежде чем модем «поднимет трубку».
ШАГ 2 Все устройства, с помощью которых можно получить доступ на линуксовый сервер, должны быть должным образом прописаны в файле /etc/inittab. Программа init считывает этот файл и «принуждает» определенные программы отслеживать попытки регистрации в системе через эти устройства. Чтобы каждый раз не запускать mgetty руками, переложим это занятие на широкие плечи init. Открываем файл inittab и дописываем туда вышеуказанную командную строку следующим образом: s1:2345:respawn:/sbin/mgetty -D -s 38400 -n 4 ttyS1
То есть даем init ценное указание под кодовым названием s1: активизировать mgetty на четырех уровнях запуска (2345) и «держать его постоянно» (respawn). Даем команду ps fax|less, чтобы узнать PID процесса init (а вдруг он не равен 1?) и PID mgetty (а вдруг он остался висеть после «ручного» запуска?). Процесс mgetty, если он подгружен, убиваем обычным образом (kill <PID>), а вот init ненавязчиво просим перечитать свой конфигурационный файл при помощи сигнала «SIGHUP»: kill -SIGHUP <PID>. После этого можно попробовать тестирования ради убить несколько раз mgetty – он все равно будет появляться автоматически под новыми PID’ами. Именно подобное поведение процесса, кстати говоря, и подразумевается под параметром respawn в inittab.
ШАГ 3 Теперь необходимо сконфигурировать mgetty так, чтобы при успешном коннекте инициировалось PPP-соединение. Для этого открываем конфигурационный файл /etc/mgetty+sendfax/ login.conf и пишем там следующее (остальные строчки конфига лично я удалил):
№4(5), апрель 2003
/AutoPPP/ — ppp /usr/sbin/pppd auth chap +pap login modem crtscts lock proxyarp
/AutoPPP/ расшифровывается как «обнаруживать PPP-соединение автоматически». Далее следует путь к программе, которую нужно запустить при обнаружении попытки установить PPP-соединение и её параметры: auth означает, что перед тем как пустить клиента в сетку, необходимо провести авторизацию; -chap – не проводить chap-авторизацию; +pap – проводить pap-авторизацию; login – использовать для pap-авторизации базу зарегистрированных в системе пользователей; modem – «общаться с модемом» (ждать CD, подавать DTR); crtscts – использовать хардварный flow control (RTS/CTS) при работе с серийным портом; lock – создавать lock-файл, дабы доступ к устройству был эксклюзивным; proxyarp – «добавлять» хост клиента в локальную сеть.
ШАГ 4 Чтобы клиент успешно прошел авторизацию, необходимо сделать две вещи: добавить пользователя в систему (adduser <username>, passwd <username>) и добавить регистрационную информацию в файл /etc/ppp/ pap-secrets. #Secrets for authentication using PAP #client server secret IP addresses dialup * qwerty 192.168.1.254
Под client подразумевается имя пользователя; * server говорит о том, что пользователь под этим именем может подключаться к любым сервисам; secret – это пароль (он должен быть тем же самым, что и при добавлении пользователя в систему); IP addresses – IP-адрес, под которым дозвонившийся клиент будет работать в сети. Все, теперь можно тестировать mgetty по полной программе.
ШАГ 5 Лог mgetty находится в файле mgetty.log.ttyS1 каталога /var/log и
выглядит он следующим образом (я пронумеровал строки, чтобы было легче их комментировать). 00 — 01 09/23 14:34:28 yS1 mgetty: experimental test release 1.1.26-Apr16 02 09/23 14:34:28 yS1 check for lockfiles 03 09/23 14:34:28 yS1 locking the line 04 09/23 14:34:28 yS1 lowering DTR to reset Modem 05 09/23 14:34:29 yS1 send: \dATQ0V1H0[0d] 06 09/23 14:34:29 yS1 waiting for «OK» ** found ** 07 09/23 14:34:30 yS1 send: ATS0=0Q0&D3&C1[0d] 08 09/23 14:34:30 yS1 waiting for «OK» ** found ** 09 09/23 14:34:30 yS1 waiting... 10 09/23 14:35:25 yS1 wfr: waiting for «RING» 11 09/23 14:35:25 yS1 wfr: waiting for «RING» 12 09/23 14:35:30 yS1 wfr: waiting for «RING» 13 09/23 14:35:35 yS1 wfr: waiting for «RING» 14 09/23 14:35:40 yS1 send: ATA[0d] 15 09/23 14:35:40 yS1 waiting for «CONNECT» ** found ** 16 09/23 14:35:59 yS1 send: 17 09/23 14:35:59 yS1 waiting for «_» ** found ** 18 09/23 14:36:01 yS1 clean_line: only 500 of 5277 bytes logged 19 09/23 14:36:11 yS1 login.config: max. 9 command line arguments possible 20 09/23 14:36:11 ##### data dev=ttyS1, pid=2307, caller=’none’, conn=’38400/ V.34 28800/None’, name=’’, cmd=’/usr/ sbin/pppd’, user=’/AutoPPP/’
01–03 – блокировка линии. 04–08 – инициализация модема. 09 – ждем-c, пока кто-нибудь позвонит.
10–14 – поднятие трубки после четырех гудков.
15–18 – обмен информацией. 19 – считывание конфига. 20 – поднятие PPP и, собственно, клиент получил доступ к серверу. Теперь, когда поставленная задача решена, самое время подумать о «наворотах». Во-первых, давать ли пользователю доступ ко всей «офисной сети» или ограничить его коннектом с почтовым сервером? Во-вторых, если в вашей сети есть пользователи, считающие себя хакерами, то хранение паролей в открытом виде – не очень хороший способ. В-третьих, возможно, имеет смысл настроить mgetty таким образом, чтобы после установки соединения модем сервера прерывал его и тут же пытался дозвониться модему клиента сам...
23
администрирование
БОРЬБА ЗА СИСТЕМНЫЕ РЕСУРСЫ
Как часто пользователи нашей сети жалуются нам, системным администраторам, на недостаточную производительность сервера, низкую пропускную способность канала и тому подобные вещи? И вот наконец-то руководство выделило кругленькую сумму денег на модернизацию наших серверов, но... пользователям опять мало. Что же делать? Без конца модернизировать сервер, угождая растущим с каждым днем запросам пользователей? Я не против модернизации, но только лишь в том случае, если она экономически оправдана.
ДЕНИС КОЛИСНИЧЕНКО 24
администрирование Попробуем проанализировать, из-за чего снижается производительность нашего сервера и сети в целом? Сейчас мы не будем касаться аппаратной стороны вопроса, а затронем лишь программную. В этой статье мы рассмотрим: повышение производительности сервера; ограничение пропускной способности канала с помощью Squid; отказ от приема рекламной информации; ограничение полномочий пользователей.
вать ядро и исключить из его состава ненужный код.
Будем предполагать, что у нас уже есть настроенный и функционирующий сервер на базе операционной системы Linux.
Повышение производительности сервера Сначала попытаемся заставить наш сервер работать немного быстрее. Положительно на производительность любого компьютера влияют: Частота центрального процессора. Объем оперативной памяти. Скорость работы жесткого диска. Конечно, кроме этих показателей есть еще и другие, но в нашем случае они не столь важны – ведь у нас же сервер. Хотя, если у нас сервер X-терминалов, то для нас будет важен объем видеопамяти и общая скорость работы нашей видеоподсистемы. Нужно заметить, что в случае с Linux объем оперативной памяти более важен, чем частота процессора. Итак, начнем по порядку. Замедлить быстродействие процессора может само ядро системы. Да, это так. Заметное снижение быстродействия может наблюдаться в двух случаях: Ядро откомпилировано для другого типа процессора. Например, у вас Pentium III, а ядро собрано с расчетом на обыкновенный Pentium. Если у вас двухпроцессорная машина (или более мощная), а вы используете ядро, не поддерживающее SMP (Symmetric multi-processing support). Обе эти проблемы не решить без перекомпиляции ядра. Вы ни разу не перекомпилировали ядро? Ничего страшного – все очень просто. Следуйте приведенным ниже инструкциям. Зарегистрируйтесь в системе как пользователь root и убедитесь, что установлены исходные тексты ядра и заголовки ядра (пакеты kernel и kernel-headers соответственно). Затем перейдите в каталог /usr/src/linux и выполните команду make menuconfig (см. рис. 1). Перед внесением изменений в файл конфигурации ядра, сохраните его под другим именем: Save Configuration to an Alternative File. Во время конфигурирования ядра вы можете включать или исключать некоторые функции из состава ядра или же сделать нужную вам функцию модулем, то есть в состав ядра данная функция включена не будет, но она будет использоваться при необходимости. Например, если вы добавите в систему устройство, то будет подключен нужный модуль, при условии, что вы его откомпилировали. Главная задача – повышение производительности системы, этого можно достичь, если точно сконфигуриро-
№4(5), апрель 2003
Ðèñ. 1. Ïðîãðàììà êîíôèãóðàöèè ÿäðà make menuconfig.
Перейдите в раздел Processor type and features и установите нужный вам тип процессора. Следующая таблица поможет вам справиться с этой задачей: Òàáë. 1.Òèïû ïðîöåññîðîâ.
Примечание. Ядро можно настроить для работы с другими процессорами, например, Ahtlon или Duron. Для этого просто выберите необходимый вам тип процессора. Если у вас многопроцессорная машина, включите поддержку SMP. Также очень рекомендую включить функцию MTRR. Включение этой опции может существенно повысить производительность системы. Кроме процессоров Intel данную возможность поддерживают процессоры и посторонних производителей: Cyrix 6x86, 6x86MX, MII, AMD K6-2 (stepping 8 и выше), K6-3, Centaur C6. Некоторые BIOS устанавливают MTRR для первого процессора, но отключают для второго. Активизация данной опции также решает и эту проблему. Затем можно просмотреть все остальные параметры ядра и отключить ненужные функции. Например, если у нас нет шины USB или она попросту не используется, зачем включать в ядро лишний код? Когда все устройства сконфигурированы, нужно сохранить файл конфигурации ядра и перейти непосредственно к этапу компилирования ядра. Введите команду: # make dep
После завершения ее работы необходимо ввести команду: # make bzImage
Если исходные тексты ядра и компилятор установлены корректно, то примерно минут через 20 (это зависит от версии ядра и от быстродействия вашей системы) вы получите откомпилированное ядро. Обычно оно помещается в каталог /usr/src/linux/arch/i386/boot. Примечание. Если в процессе компиляции вы получили сообщение о том, что не найден какой-то файл, то, ско-
25
администрирование рее всего, вы отключили опцию, которая нужна для работы другой опции. Восстановите сохраненную конфигурацию ядра и попытайтесь откомпилировать ядро заново. Теперь следует откомпилировать модули, которые будут использоваться ядром: # make modules
И установить их:
Вам нужны все запущенные сервисы? Нет, так почему же они активны? Выключите все ненужные вам сервисы. Возможно, некоторые из них нужно запускать только в определенное время. Например, сервис ftp вам нужен только в рабочее время – незачем использовать ftp ночью. Или, наоборот, сервис ssh вам нужен только ночью, когда вам вздумается из дому изменить настройки сервера. Следующий фрагмент файла /etc/xinetd.conf разрешает использовать сервис ftp только в рабочее время, учитывая обеденный перерыв:
# make modules_install service ftp { socket_type wait user server server_args instances log_on_success log_on_failure # Âðåìÿ ðàáîòû ñåðâèñà access_times nice }
Перед установкой модулей сделайте резервную копию модулей старого ядра (каталог /lib/modules). Теперь можно ввести команду: # make install
Однако для установки только что созданного ядра я не рекомендую этого делать. Сначала нужно протестировать ваше ядро. С этой целью откройте в любом текстовом редакторе файл /etc/lilo.conf и добавьте в него следующие строки: image=/usr/src/linux/arch/i386/boot/bzImage label=my_linux # Ïàðàìåòðû root è mem ó âàñ, ñêîðåå âñåãî, áóäóò äðóãèìè root=/dev/hda1 append=" mem=256M" read-only
Потом введите команду lilo и перезагрузите систему. Попробуйте загрузить ядро. В случае возникновения ошибок вы всегда сможете загрузить старую версию. Надеюсь, что после проведенных действий ваша система стала работать быстрее. После рассмотрения оптимизации процессора, обратим наше внимание на оперативную память. Узнать информацию о загрузке оперативной памяти поможет команда free. Что больше всего «пожирает» оперативную память? Правильно, процессы! Одно дело, когда неблагодарный пользователь запустит большое количество процессов, но совсем другое дело, когда мы, администраторы, так нерационально используем наши ресурсы. Запустите конфигуратор setup и выберите пункт меню System Services (см. рис. 2). Если вы используете ОС Linux Mandrake, запустите конфигуратор drakxservices.
= stream = no = root = /usr/etc/in.ftpd = -l = 4 += DURATION USERID += USERID = 8:00-12:00 13:00-18:00 = 10
Для остановки того или иного сервиса введите команду service <имя> stop. Например, service httpd stop. Примечание. Для запуска сервиса используется параметр start, а для перезагрузки – restart. Вы отключили все, что можно, а памяти все равно не хватает? Тогда вам можно посоветовать только модернизацию оперативной памяти. А пока можно создать файл подкачки, который немного отложит покупку памяти. Например, если вы хотите создать файл подкачки размером 128 Мб, выполните следующие действия: Выполните команду: dd if=/dev/zero of=/swap bs=1k count=131072
Данная команда создаст пустой файл /swap размером 128 Мб. Создайте файловую систему типа Linux Swap: mkswap /swap 131072
Активизируйте созданный файл подкачки: swapon /swap
Введите команду free, чтобы убедиться, что файл подкачки подключен. Третью команду нужно добавить в сценарий загрузки системы /etc/rc.d/rc.local, чтобы не вводить ее вручную при каждой загрузке сервера. Мы еще можем увеличить производительность жесткого диска. Тут нам поможет программа hdparm. Давайте попробуем немного «разогнать» наш жесткий диск. # hdparm - d1m2c3u1 /dev/hda
Ðèñ. 2. Ñèñòåìíûå ñåðâèñû.
26
Теперь разберемся, что же мы сделали этой командой. Во-первых, мы включили DMA, затем разрешили пе-
администрирование редавать более одного слова за такт, а также включили 32-битный доступ к диску (команда с). Для просмотра установленных параметров введите команду: # hdparm /dev/hda
Запустим hdparm в режиме теста: # hdparm –t /dev/hda
В зависимости от жесткого диска у нас должно получиться не менее 14 Мб/сек. Обратите внимание на опцию m2. Данная опция позволяет передавать более одного слова за такт – два слова (m2). Если у вас современный жесткий диск, установите максимальное значение – m16. Однако если после сохранения параметров на консоли появляется сообщение Drive Seek Error, уменьшите данное значение (например, до восьми блоков за такт). Можно использовать параметры X33 и X66 для включения режимов передачи данных UDMA33 и UDMA66 соответственно. Если при использовании режимов Х33 и Х66 производительность снизилась, используйте режим Х68. Для сохранения параметров контроллера IDE используйте команду: # hdparm -k1 /dev/hda
При перезагрузке системы параметры IDE теряются, поэтому команду «разгона» винчестера нужно поместить в сценарий запуска системы. Сейчас просто добавьте команду вызова hdparm в файл /etc/rc.d/rc.local. Этот способ является наиболее универсальным, поскольку он позволяет установить отдельные параметры для разных жестких дисков, если у вас их несколько. Второй, менее универсальный способ заключается в редактировании файла /etc/sysconfig/ harddisks, в котором можно задать общие параметры для всех жестких дисков. Есть еще один «подводный камень», который состоит в следующем: при пробуждении системы и её переходе в нормальное состояние после «сна» параметры контроллера также сбрасываются. Этого можно избежать, если подправить файл конфигурации демона apmd, который отвечает за управление питанием. Параметры контроллера IDE, которые устанавливаются при переходе системы в «спящий» режим и выходе из него, задаются строками HDPARM_AT_SUSPEND и HDPARM_AT_RESUME в файле конфигурации /etc/sysconfig/apmd. Мы сделали все возможное, чтобы наш сервер работал быстрее. Теперь попробуем ограничить пропускную способность канала.
Ограничение пропускной способности канала с помощью Squid Для этого нам понадобится уже настроенный и работающий прокси-сервер Squid (сервис Squid). Предположим, что нам нужно настроить прокси-сервер таким образом, чтобы одна группа компьютеров могла работать с одной скоростью, а другая – с другой. Это может потребоваться, например, для разграничения пользователей, которые используют канал для работы (например, вы), и пользователей, которые ис-
№4(5), апрель 2003
пользуют ресурсы канала в других целях. Естественно, первым пропускная способность канала важнее, чем вторым. С помощью прокси-сервера Squid можно разделить канал. Для начала в файле конфигурации (/etc/squid/squid.conf) укажите, сколько пулов, то есть групп пользователей, у вас будет: delay_pools 2. Затем определите классы пулов. Всего существует три класса: Используется одно ограничение пропускной способности канала на всех. Одно общее ограничение и 255 отдельных для каждого узла сети класса С. Для каждой подсети класса В будет использовано собственное ограничение и отдельное ограничение для каждого узла. В файл squid.conf добавьте следующие директивы: delay_class 1 1 # îïðåäåëÿåò ïåðâûé ïóë êëàññà 1 äëÿ äîìàøíèõ ïîëüçîâàòåëåé delay_class 2 2 # îïðåäåëÿåò âòîðîé ïóë êëàññà 2 äëÿ ñëóæàùèõ
Теперь задайте узлы, которые будут относиться к пулам: acl home src àäðåñà acl workers src àäðåñà delay_access 1 allow home delay_access 1 deny all delay_access 2 allow workers delay_access 2 deny all
Затем укажите ограничения: delay_parameters 1 14400/14400 delay_parameters 2 33600/33600 16800/33600
Как я уже отмечал выше, для пула класса 1 используется одно ограничение для всех компьютеров, входящих в пул – 14400 байт. Первое число задает скорость заполнения для всего пула (байт/секунду). Второе – максимальное ограничение. Для пула класса 2, соответственно, используются ограничения на всю подсеть и отдельно на каждого пользователя.
Борьба со спамом Вы опять получили письмо с предложением купить базу данных абонентов МТС? Добавьте адрес спаммера в «черный» список – в файл /etc/mail/access. Данный файл преобразуется в файл access.db, который используется программой sendmail. В нем вы можете указать узлы, которым разрешено (запрещено) использовать ваш SMTP-сервер. Формат этого файла такой: узел | сеть | пользователь | действие. localhost.localdomain localhost 127.0.0.1 spammer@spam.ru spamworld.com 192.168.1 host.mydomain.ru mydomain.ru
RELAY RELAY OK REJECT ERROR:"550 Access denied" RELAY REJECT RELAY
В первой-третьей строках мы разрешаем самим себе использовать SMTP-сервер. Затем мы запрещаем пересылку почты пользователю spammer@spam.ru, а также всему домену spamworld.com. Шестая строка разрешает пересыл-
27
администрирование ку почты всей нашей локальной подсети – 192.168.1.*. Последняя строка разрешает использовать SMTP-сервер нашему домену, а предпоследняя запрещает использовать наш сервер одному узлу из домена mydomain.ru – host. Разница между действием OK и RELAY заключается в том, что в первом случае (ОК) пересылка разрешается, даже если другие правила sendmail запретили пересылку почты, например, если имя узла не разрешено (при использовании DNS). Для запрещения пересылки можно просто использовать REJECT. Тогда пользователь увидит сообщение «Access denied». Действие ERROR более информативно, так как вы можете указать любое свое сообщение (установить реакцию на ошибку). Действие ERROR можно записать по-другому: ERROR:D.S.N:Message, где D.S.N – это код ошибки в соответствии с RFC 1893. Для того чтобы новые правила доступа вступили в силу, введите команду: # makemap hash /etc/mail/access < /etc/mail/access
Изменения вступят в силу сразу после завершения работы программы makemap. Перезагружать sendmail при этом не нужно!
Ограничение действий пользователей Иногда нужно запретить некоторым узлам (или целым подсетям) доступ к вашему серверу. Зачем пользователям из соседнего отдела пытаться зарегистрироваться на вашем FTP-сервере? Ясное дело, что FTP-сервер не позволит им этого сделать, поскольку они не знают, точнее, не должны знать имя пользователя и пароль для доступа к этому серверу. Так зачем же нам разрешать доступ к FTP этим пользователям, если мы заведомо знаем, что им там делать нечего? Демон tcpd аутентифицирует удаленных пользователей и проверяет корректность их запросов. С помощью этого демона можно ограничить запросы с удаленных компьютеров. Файл hosts.allow содержит список хостов, которым разрешено подключаться к вашей системе, а hosts.deny – запрещено. Записи имеют формат: служба:хост.домен. Если вы хотите разрешить или запретить доступ всем, используйте модификатор ALL. Запись ALL:ALL открывает или закрывает доступ к вашей машине всем компьютерам для всех видов сервисов. Ниже приведен листинг файла hosts.allow. ftp:our_domain.firma.ru
В вышеприведенном листинге доступ к ftp разрешен только нашему домену our_domain.firma.ru. В файл hosts.deny рекомендуется добавить запись, запрещающую доступ к FTP соседям (другому отделу) или же абсолютно всем (ftp:ALL) Раз уж мы заговорили о FTPсервере, нельзя не сказать, что все приведенные выше операции можно было реализовать средствами самого сервера, но я не вижу смысла загружать сервер лишней работой, если все это можно сделать на более низком уровне. Но для полноты обзора все же рассмотрим директиву Limit, ограничивающую доступ к серверу:
28
<Limit LOGIN> DenyAll AllowUser pupkin MaxClients 5 Deny from 153.111.171.137 Deny from 192.168.2. </Limit>
Первая директива в блоке Limit запрещает регистрацию (LOGIN) всем пользователям, вторая разрешает только регистрацию пользователя pupkin, третья – задает максимальное число клиентов (5). Последние две директивы запрещают регистрацию с узла 153.111.171.137, а также из подсети 192.168.2. Кроме директив DenyAll и AllowUser существуют противоположные им по действию – AllowAll и DenyUser соответственно. Данный блок Limit нужно указать в файле конфигурации сервера ProFTPD – /etc/proftpd.conf. Теперь, когда пользователи других подсетей не смогут использовать наши ресурсы, немного ограничим своих родных пользователей. Для ограничения локальных пользователей используются файлы: access.conf console.perms limits.conf Эти файлы расположены в каталоге /etc/security. Первый файл – это таблица доступа пользователей. Когда кто-то регистрируется в системе (удаленно или локально), в этой таблице система ищет запись, содержащую имя пользователя и предоставляет соответствующий этому пользователю доступ или вообще запрещает его. Если имя пользователя не найдено, но может регистрироваться со всех терминалов (для локальной регистрации) или со всех узлов (для удаленной регистрации). Формат файла access.conf такой: Разрешение:Пользователи:Доступ. Первое поле может содержать либо символ «+», который означает, что доступ разрешен, или символ «-», запрещающий доступ. Поле Пользователи содержит список имен пользователей, разделенных пробелами. Можно указывать имя пользователя в формате user@host. Такая запись описывает пользователя user, который регистрируется из машины host. Для обозначения всех пользователей можно указать ALL в качестве значения второго поля. Третье поле (Доступ) может содержать список терминалов, из которых разрешена (или запрещена – в зависимости от значения первого поля) регистрация пользователей (для локальной регистрации). Если вас интересует регистрация по сети, вы можете указать здесь имя узла, IPадрес узла, адрес сети (заканчивается точкой), имена доменов или имена узлов локальной сети (не содержат точки). Для обозначения всех узлов локальной сети можно использовать модификатор LOCAL. Можно также использовать модификатор EXCEPT (кроме) для исключения некоторых элементов списка (во втором и в третьем полях). Рассмотрим несколько примеров: -:ALL EXCEPT den user serge:LOCAL .microsoft.com +:reboot shutdown:LOCAL +:root:tty1 -:root:LOCAL -:den user serge:LOCAL EXCEPT host1
Первое правило запрещает регистрацию всех пользо-
администрирование вателей, кроме (EXCEPT) den, user, serge из любого хоста локальной сети и домена .microsoft.com. Но эти пользователи могут регистрироваться из любого другого домена. Второе правило разрешает регистрацию пользователей reboot и shutdown из любого узла локальной сети. Третье правило разрешает регистрацию пользователя root из терминала tty1, а следующее правило – запрещает регистрацию пользователя root по сети (локальной). Последнее правило запрещает регистрацию пользователей den, user, serge из любого узла локальной сети, кроме узла host1. C точки зрения безопасности приведенные примеры не имеют никакого смысла. Я привел данный пример только в демонстрационных целях. Как видно из имен пользователей во втором правиле, первый используется для перезагрузки системы, а второй – для ее останова. То есть при регистрации этих пользователей система соответственно или перезагружается, или останавливается. Подобное практикуется многими системными администраторами, которых я знаю. Как они говорят, этих пользователей создали для удобства: если нужно перезагрузить машину, нужно просто войти в систему под пользователем reboot. Такое удобство вам может дорого обойтись, если кто-то, узнав ваш пароль, остановит машину во время вашего отсутствия, поэтому не рекомендую вам создавать подобных пользователей вообще. Третье правило разрешает регистрацию пользователя root с терминала tty1 (локальная регистрация), но не запрещает регистрацию со всех остальных. Можно было бы указать правило -:root:ALL
перед третьим правилом, но специально для этих целей служит файл /etc/securetty, о котором мы поговорим немного позже. Теперь перейдем ко второму файлу – console.perms. Этот файл определяет полномочия привилегированных пользователей, которые будут им присвоены при регистрации через консоль системы (локальная регистрация). Скорее всего, вам не нужно будет редактировать этот файл. После внесения изменений в этот файл выполните команду: pam_console_apply -r
Обычно данная команда помещается в один из инициализационных сценариев системы. Для получения более подробной информации обратитесь к справочной системе. В файле limits.conf определяются квоты системных ресурсов, например, максимальное число процессов или максимальное время процессора. Прежде чем ограничить пользователей, рассмотрим, как можно ограничить самого себя, то есть пользователя root. В файле /etc/securetty, который уже упоминался выше, указываются терминалы и виртуальные консоли, из которых может регистрироваться пользователь root. Я рекомендую вообще запретить регистрацию пользователя root из консоли. Для этого удалите (или закомментируйте) все строки в файле securety. Если вам будут нужны максимальные привилегии, используйте команду su (super user). После ввода этой команды программа запросит у вас па-
№4(5), апрель 2003
роль пользователя root, и если пароль правилен, вы получите привилегии пользователя root. В файле limits.conf определяются ограничения ресурсов системы для пользователя или группы пользователей. Формат файла такой: <domain> <type> <item> <value>. Первое поле (domain) может содержать: Имя пользователя. Имя группы. Перед именем группы нужно указать символ «@». Символ «*». Данное ограничение установлено по умолчанию. Второе поле – это тип ограничения: мягкое (soft) или жесткое (hard). Мягкое ограничение определяет число системных ресурсов, которое пользователь все еще может превысить, жесткое ограничение превысить невозможно. При попытке сделать это, пользователь получит сообщение об ошибке. Элементом ограничения (item) может быть: core – ограничение размера файла core (Кб); data – максимальный размер данных (Кб); fsize – максимальный размер файла (Кб); memlock – максимальное заблокированное адресное пространство (Кб); nofile – максимальное число открытых файлов; stack – максимальный размер стека (Кб); cpu – максимальное время процессора (минуты); nproc – максимальное число процессов; as – ограничение адресного пространства; maxlogins – максимальное число одновременных регистраций в системе; locks – максимальное число файлов блокировки. Рассмотрим несколько примеров. Например, нам нужно установить максимальное число процессов для пользователя user. Это можно сделать с помощью таких записей: user soft nproc 50 user hard nproc 60
Первая строка определяет мягкое ограничение (равное 50), а вторая – жесткое. Допустим, у нас есть группы dialup1 и dialup2. В каждую группу входят 30 пользователей. У нас есть всего 30 входящих линий, поэтому нужно обеспечить одновременную работу не более 15 пользователей из каждой группы. Это делается так: @dialup1 - maxlogins 14 @dialup2 - maxlogins 14
В первом и втором случае из каждой группы пользователей одновременно работать смогут не более 15 (maxlogins 14 – отсчет начинается с нуля). При регистрации шестнадцатый пользователь увидит сообщение: Too many logins for «dialup1». Последнее, что можно сделать, – это установить квоты для файловых систем, но квотирование выходит за рамки этой статьи (вполне возможно, что квоты будут рассмотрены в следующей моей статье). Все ваши вопросы, комментарии и пожелания присылайте на адрес dhsilabs@mail.ru.
29
администрирование
СИСТЕМА ФИЛЬТРАЦИИ
ИНТЕРНЕТ-ТРАФИКА Целью данных записок является создание простой в управлении и в то же время гибкой в настройке системы фильтрации интернет-трафика. Строить её мы будем на основе FreeBSD 4.5 + Squid + SquidGuard + Berkeley DB 3.2.9 + Apache. Стоит отметить, что обсуждаемые в этой статье приемы будут работать и на основе Linux. В принципе такой комплекс можно построить на любой Unix-совместимой системе. Главная проблема – необходимость использования версий SquidGuard и Squid для этой системы. Apache можно заменить любым другим веб-сервером или использовать уже существующий веб-сервер. Кстати, веб-сервер можно запустить на отдельной машине под управлением любой операционной системы. Не стоит отчаиваться, если база данных Berkeley DB еще не портирована для вашей платформы. SquidGuard легко может работать и без нее.
АНДРЕЙ БЕШКОВ 30
администрирование Вы можете спросить, зачем нам нужны все эти сложности? Как и любой другой ресурс, интернет-трафик имеет обыкновение заканчиваться. Да и канал от нас к провайдеру не резиновый, отсюда вывод – необходимо тем или иным способом ограничить аппетиты пользователей. С другой стороны, если начальство поймает кого-то из сотрудников за просмотром порносайтов или скачиванием mp3, нагоняй получит не только провинившийся. Администратор будет виноват в том, что позволяет сотрудникам тратить оплачиваемый организацией трафик на всякую ерунду. В то же время стоит помнить, что каждая организация имеет свои правила использования ресурсов сети Интернет. Довольно часто в списке запретов можно встретить не только эротику, но и сайты анекдотов, форумы и чаты. Например, бесплатные почтовые сайты могут быть запрещены из соображения секретности. Одновременно можно запретить пользователям скачивать из внешней сети выполняемые файлы. Это существенно снижает опасность вирусного заражения сети. Кроме того, перед нами все еще стоит задача экономии трафика. Существенно снизить его потребление поможет запрещение бесполезной для нас баннерной рекламы. Вы могли бы спросить, что в баннерах плохого? Squid – кеширующий прокси-сервер, соответственно, скачиваемые файлы ложатся в локальный кеш. При следующих запросах эти файлы уже не будут скачиваться из Интернета. Проблема в том, что баннерная реклама построена на применении механизма CGI (Common Gateway Interface), расшифровывается как «общий интерфейс шлюза». Характерным признаком которого является использование знака «?» в адресной строке запроса. Например, адрес одного из баннеров «Украинской Баннерной Сети» выглядит так: http://banner.kiev.ua/cgi-bin/ bi.cgi?h" + user + "&"+ pid + "&" + page + "&2. К сожалению, CGI используется не только для баннерной рекламы, но и для чатов, форумов, сетевых магазинов и прочей полезной сетевой функциональности. То есть везде, где необходимо получить от пользователя данные. Затем полученные данные должны быть обработаны, а результаты работы CGI необходимо вернуть пользователю. Значит для каждого пользователя не только запросы, но и ответы будут разными. Поэтому класть полученные документы в кеш squid бесполезно. По умолчанию squid не использует кеш при работе с динамическими документами. В свою очередь, это значит, что одни и те же баннеры будут выкачиваться бесконечно. Подменяя баннеры пустыми картинками с локального веб-сервера, можно значительно снизить количество потребляемого трафика. Многие администраторы, столкнувшись с этими проблемами, могут утверждать, что они легко решаются с помощью штатных средств Squid. Я не стану отрицать, что Access Control List (списки контроля доступа), сокращенно ACL, используемые в Squid, – это довольно мощный инструмент. Но для работы с ним требуется достаточно большой опыт. С другой стороны, трудно представить, как администратор будет разбираться, какие сайты он должен блокировать. Остается только вслед за пользователями ходить на все часто посещаемые сайты, и постепенно запрещать неугодные. Учитывая количество сайтов в
№4(5), апрель 2003
Интернете, а также распространенность баннерной рекламы, такой путь выглядит утопией. В начале такого ошибочного пути кажется, что нужно всего лишь записывать все запрещенные сайты в отдельные файлы с помощью ACL-записей типа: acl porno src "/usr/local/squid/etc/porno.lst" acl erotic src "/usr/local/squid/etc/erotic.lst"
А затем запрещать их всех скопом. Но обслуживание такой системы способно превратиться в головную боль уже на первой тысяче сайтов. Squid загружает списки контроля доступа в оперативную память. С добавлением новых сайтов размер файла будет постоянно расти. Соответственно, и Squid будет занимать все больше оперативной памяти. В связи с тем, что список запрещенных сайтов неупорядочен, поиск в нем будет занимать довольно продолжительное время. SquidGuard выполняет за 12 секунд 100 000 запросов к базе, содержащей 205 900 записей. Тестирование проводилось на машине с процессором Pentium 500 MHz. Такой скорости удается добиться за счет того, что SquidGuard хранит список сайтов в форме B-дерева. Как мы видим, средствами Squid все вышеописанное выполнить достаточно тяжело. И тут в поле нашего внимания попадает класс программ под названием редиректоры. С разной степенью легкости эти программы позволяют решать наши проблемы. Используемый нами SquidGuard тоже является редиректором. Давайте коротко опишем его возможности. Может разрешить доступ некоторой группе пользователей только к избранным сайтам. Блокирует доступ пользователей к определенному списку адресов. Помогает блокировать доступ к сайтам на основе списка регулярных выражений. Запрещает использовать IP-адреса вместо доменных имен внутри URL. Дает возможность перенаправить пользователей, пытающихся получить доступ к запрещенным страницам, на другую страницу, где им будет объяснена причина запрета. Помогает перенаправить запросы на доставку часто скачиваемых файлов, таких как MSIE, Netscape Navigator или ICQ, к их локальным копиям. Позволяет использовать разные политики доступа в зависимости от времени дня, текущей даты, дня недели. Дает возможность гибкой настройки процесса протоколирования обрабатываемых запросов. В качестве кандидатов на место SquidGuard претендовали squirm и Jesred. После тестирования от squirm пришлось отказаться, потому что список фильтрации поддерживается всего один на всех пользователей. Соответственно запретить что-либо конкретному пользователю не представляется возможным. Запрещать приходится либо всем, либо никому. К тому же список сайтов приходится хранить в виде довольно сложных и неудобных для восприятия регулярных выражений. По моему мнению, такое ограничение не позволяет использовать squirm в сетях средних и больших размеров.
31
администрирование Затем мне под руку попался Jesred. Несмотря на то что Jesred является модернизированным потомком squirm и имеет более гибкий синтаксис файла шаблонов, он все еще страдает от тех же проблем. Единственное улучшение в этой области – достаточно высокая скорость работы и возможность пропускать запросы некоторых пользователей без фильтрации. Как вы понимаете, в этом случае ни о каком гибком разграничении полномочий пользователей речь не идет. Ну что же, теперь, когда с формальностями и изучением начальной теории покончено, приступим к установке. Я думаю, нижеприведенных инструкций по настройке Apache и Squid хватит, чтобы установить их в комплектации по умолчанию. Для получения более подробных сведений вам стоит посетить следующие сайты: http://apache.lexa.ru http://www.squid-cache.org http://squid.opennet.ru В процессе компиляции всего программного обеспечения вместо стандартного make мною использовался gmake, но это опять же вопрос личных предпочтений. Мне кажется, что gmake работает стабильнее и быстрее. В качестве прокси-сервера я использовал squid 2.5.STABLE1. На момент написания статьи это была самая свежая версия. Взять ее можно на http://www.squidcache.org/Versions/v2/2.5/. Рекомендуется всегда использовать самые новейшие из стабильных версий программ. Такой подход позволит в дальнейшем избежать многих проблем со стабильностью и безопасностью работы тех или иных инструментов. # # # # #
tar zxvf squid-2.5.STABLE1-src.tar.gz cd squid-2.5.STABLE1 ./configure gmake gmake install
После инсталляции редактируем файл конфигурации squid, находящийся в файле /usr/local/squid/etc/squid.conf. Должно получиться примерно следующее: # Îáðàáàòûâàòü çàïðîñû íà ïîðò 3128 http_port 3128 hierarchy_stoplist cgi-bin ? # Çàïðåùàåì êåøèðîâàòü CGI acl QUERY urlpath_regex cgi-bin \? no_cache deny QUERY # Ðàçìåð îïåðàòèâíîé ïàìÿòè, îòâîäèìîé ïîä êåø cache_mem 64 MB # Òóò ìû áóäåì áðàòü ôàéëû ñòàíäàðòíûõ ñîîáùåíèé îá îøèáêàõ error_directory /usr/local/squid/share/errors/Russian-koi8-r # Ìàêñèìàëüíûé ðàçìåð îáúåêòà, çàïèñûâàåìîãî â êåø maximum_object_size 16384 KB # Çäåñü ó íàñ áóäåò õðàíèòüñÿ êåø. Îòâîäèì ïîä íåãî 5000 Ìá. # Ïðèêàçûâàåì ñîçäàòü 16 äèðåêòîðèé ïåðâîãî óðîâíÿ è 256 # âòîðîãî óðîâíÿ. cache_dir ufs /usr/local/squid/cache 5000 16 256 # Ïðîòîêîë äîñòóïà ê êåøó cache_access_log /usr/local/squid/logs/access.log # Òóò íàõîäèòñÿ ïðîòîêîë ðàáîòû êåøà cache_log /usr/local/squid/logs/cache.log # Ïðîòîêîë ðàáîòû ìåíåäæåðà êåøà cache_store_log /usr/local/squid/logs/store.log # Ïîä ýòèì ïîëüçîâàòåëåì áóäåì õîäèòü ïî Ftp ftp_user vasa@pupkin.ru # Åñëè Squid óæå ñêà÷àë 60% ôàéëà, à ïîëüçîâàòåëü îòêàçàëñÿ # åãî çàáèðàòü, òî âñå ðàâíî ïðîäîëæàòü ñêà÷èâàòü ôàéë. quick_abort_pct 60 # Âðåìÿ æèçíè çàïðîñîâ, çàâåðøèâøèõñÿ îøèáêîé. Íàïðèìåð, # «connection refused» èëè «404 Not Found» negative_ttl 1 minutes
32
# Âðåìÿ æèçíè óñïåøíîãî DNS-çàïðîñà. positive_dns_ttl 6 hours # Âðåìÿ æèçíè DNS-çàïðîñîâ, çàâåðøèâøèõñÿ îøèáêîé. negative_dns_ttl 5 minutes # Ïîääåðæêà íåñòàíäàðòíûõ http-êëèåíòîâ half_closed_clients on # Ìèíèìàëüíûå ðåêîìåíäóåìûå ïðàâà acl all src 0.0.0.0/0.0.0.0 acl manager proto cache_object acl localhost src 127.0.0.1/255.255.255.255 # Ssl acl SSL_ports port 443 563 # http acl Safe_ports port 80 # ftp acl Safe_ports port 21 # https, snews acl Safe_ports port 443 563 # gopher acl Safe_ports port 70 # wais acl Safe_ports port 210 # unregistered ports acl Safe_ports port 1025-65535 # http-mgmt acl Safe_ports port 280 # gss-http acl Safe_ports port 488 # filemaker acl Safe_ports port 591 # multiling http acl Safe_ports port 777 acl CONNECT method CONNECT # îïèñûâàåì íàøèõ ïîëüçîâàòåëåé acl users src "/usr/local/squid/etc/users.txt" # Ðàçðåøàåì ñîåäèíåíèÿ òîëüêî ïî ïðàâèëüíûì ïîðòàì. È ðàçäàåì # âñåì ïðàâà äîñòóïà http_access allow manager localhost http_access deny manager http_access deny !Safe_ports http_access allow users http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access deny all # Àäðåñ ïîëüçîâàòåëÿ, êîòîðîãî áóäóò óâåäîìëÿòü # î ïåðåïîëíåíèè êåøà cache_mgr root@test.ru # Ïîëüçîâàòåëü, îò èìåíè êîòîðîãî áóäåò ðàáîòàòü Squid cache_effective_user nobody # Ãðóïïà, îò èìåíè êîòîðîé áóäåò ðàáîòàòü Squid cache_effective_group nogroup # Âêëþ÷àòü ëè IP-àäðåñ êëèåíòà â çàãîëîâîê http-çàïðîñà forwarded_for on # Ðàçðåøàåì óïðàâëÿòü êåøåì ñ ïîìîùüþ cachemgr.cgi. #  êà÷åñòâå ïàðîëÿ áóäåì èñïîëüçîâàòü ñëîâî «passwd» cachemgr_passwd passwd all # Âêëþ÷àåì ñáîð ñòàòèñòèêè ïî êàæäîìó êëèåíòó client_db on
Обращаю ваше внимание на строку acl users src «/usr/ local/squid/etc/users.txt». Она означает, что список пользователей, которым разрешен доступ к squid, находится в файле /usr/local/squid/etc/users.txt. Файл списка имеет следующий формат: #Ïåòðîâà Íàòàëüÿ (Ñíàáæåíèå) 192.168.10.91/32 #Èâàíîâ Âëàäèìèð (Äîñòàâêà) 192.168.10.92/32 #Ñåðãååâ Èãîðü (Ïëàíîâûé îòäåë) 192.168.10.93/255.255.255.255 #Êðèâîóõèíà Èðèíà (Ëàáîðàòîðèÿ) 192.168.10.94/255.255.255.255 #Ñèíèöûíà Ñâåòëàíà (ñåêðåòàðü ãåíåðàëüíîãî äèðåêòîðà) 192.168.10.95/255.255.255.255
Реально в списке содержатся не имена пользователей, а IP-адреса их машин. Как вы смогли убедиться, все устроено достаточно просто. Решено работать с отдельным файлом, содержащим список пользователей, чтобы не перегружать главный конфигурационный файл.
администрирование Users.txt должен иметь те же права доступа, что и squid.conf, для того чтобы squid мог читать его содержимое.
ошибках появляются в файле протокола. # tail -f /var/log/messages
# chown nobody:nogroup /usr/local/squid/etc/users.txt
Возможен и другой вариант управления доступом к web. При этом доступ во внешнюю сеть средствами squid не ограничивается. Разграничением доступа в этом случае будет заниматься SquidGuard. Для тех пользователей, чей адрес не внесен в файл /usr/local/squidGuard/ squidGuard.conf, производится перенаправление на страницу запрещения. Соответственно, эти пользователи никогда Интернета не увидят. Чтобы добиться такого эффекта, нужно удалить из squid.conf строки: acl users src "/usr/local/squid/etc/users.txt" http_access allow users http_access deny all
Если все сделали правильно, тогда должны увидеть что-то подобное: Oct 3 12:15:05 dns squid[139]: Squid Parent: child process ↵ 141 started
Это значит что, squid у нас заработал. Теперь примемся за установку Russian Apache. Я использовал весрсию 1.3.27 PL30.16. Ну а вы, как всегда, берите новейший дистрибутив ftp://ftp.lexa.ru/pub/apache-rus/apache_1.3.27rusPL30.16.tar.gz. Распаковываем его и ставим в комплекте по умолчанию. # # # #
tar zxvf apache_1.3.27rusPL30.16.tar.gz ./configure gmake gmake instal
И добавить в squid.conf вместо них строку: Запускаем apache: http_access allow all /usr/local/apache/bin/apachectl start
Мне больше нравится второй вариант разграничения доступа. Если использовать традиционную схему разграничения прав, то проверка прав доступа происходит дважды. Сначала внутри Squid, а затем в SquidGuard. Мне кажется, что управлять доступом в одной точке гораздо удобнее. Но это опять же дело вкуса. Настало время создать директорию, в которой у нас будет храниться кеш squid.
Создаем директорию, где будут лежать пустой баннер и файл mp3 с каким-либо забавным звуком. # mkdir /usr/local/apache/htdocs/replace
Кладем туда 1x1.gif и my.mp3. Берем модифицированный block.cgi и копируем его в /usr/local/apache/cgi-bin Выставляем ему нужные права:
# mkdir /usr/local/squid/cache
А тут у нас будут лежать логи. # mkdir /usr/local/squid/logs
Нужно позаботиться, чтобы директории /usr/local/squid/ cache и /usr/local/squid/logs были доступны пользователю, от имени которого работает squid. Узнать имя этого пользователя можно так: # cat /usr/local/squid/etc/squid.conf | grep cache_effectiv cache_effective_user nobody ñache_effective_group nogroup
Получается, что пользователя зовут nobody, группа у него nogroup. # chown -R nobody /usr/local/squid/cache /usr/local/squid/logs # /usr/local/squid/sbin/squid -z
Внутри директории /usr/local/squid/cache создаем иерархию директорий для хранения кеш-файлов. Заглянув в /usr/local/squid/cache, вы сразу поймете, что имелось в виду под словом иерархия. Запускаем squid.
# chown nobody:wheel /usr/local/apache/cgi-bin/block.cgi # chmod 500 /usr/local/apache/cgi-bin/block.cgi
block.cgi – это perl-скрипт, который будет вызываться каждый раз, когда пользователь попытается посетить запрещенную страницу. Взять его можно из архива с дистрибутивом squidGuard. В первоначальном варианте этот скрипт назывался squidGuard-1.2.0/samples/ squidGuard.cgi.in. Можно использовать его, но все же лучше взять слегка модифицированный мною вариант. Мой скрипт, наверное, лучше, потому что руссифицированный. На его исправление ушло почти два часа. Итак, все подготовительные работы окончены, и самое время взяться за установку squidGuard 1.2.0. Для его работы необходимо иметь Berkeley DB обязательно версии 3.2.9. В свою очередь, Berkeley DB не соберется без libtool. Довольно запутаная получается цепочка. Но бояться не стоит. Берем libtool из коллекции портированных приложений (http://www.freebsd.org/cgi/pds.cgi?ports/devel/ libtool) и, как обычно, выполняем распаковку, компиляцию, а затем и установку: # tar zxvf libtool-1.3.4.tar.gz # cd libtool-1.3.4
# /usr/local/squid/sbin/squid -D
# ./configure # gmake # gmake install
А на другой консоли смотрим, какие сообщения об
С выполнением этих действий не должно возникнуть
№4(5), апрель 2003
33
администрирование никаких сложностей. Скачиваем Berkeley DB 3.2.9 с http:// www.sleepycat.com/update/index.html. Забираем два патча http://www.sleepycat.com/download/patchlogs.shtml. И снова: # tar zxvf db-3.2.9.tar.gz
Копируем патч-файлы в получившуюся после распаковки дистрибутива директорию db-3.2.9. Затем применяем их для модификации исходного кода. # # # #
cp patch.3.2.9.1 patch.3.2.9.2 ./db-3.2.9 cd /usr/local/src/db-3.2.9 patch -p0 < patch.3.2.9.1 patch -p0 < patch.3.2.9.2
А теперь снова компиляция. # # # #
cd build_unix ../dist/configure gmake gmake install
Забираем squidGuard-1.2.0 с http://www.squidguard.org/ download/. Распаковываем и компилируем: # tar zxvf squidGuard-1.2.0.tar.gz # cd squidGuard-1.2.0 # ./configure --prefix=/usr/local/squidGuard ↵ --with-db=/usr/local/BerkeleyDB.3.2 ↵ --with-sg-config=/usr/local/squidGuard/squidGuard.conf ↵ --with-sg-logdir=/usr/local/squidGuard/log ↵ --with-sg-dbhome=/usr/local/squidGuard/db
Разберемся с ключами, передаваемыми программе configure: --prefix=/usr/local/squidGuard – директория, в которую будет установлен squidGuard; --with-db=/usr/local/BerkeleyDB.3.2 – тут находится используемая в процессе компиляции библиотека BerkeleyDB.3.2; --with-sg-config=/usr/local/squidGuard/squidGuard.conf – местонахождение файла конфигурации squidGuard; --with-sg-logdir=/usr/local/squidGuard/log – директория для файлов протоколов; --with-sg-dbhome=/usr/local/squidGuard/db – тут будут находиться списки блокируемых сайтов. # gmake # gmake test # gmake install
Cоздаем для хранения файлов протоколирования работы squidGuard директорию /usr/local/squidGuard/log. # mkdir /usr/local/squidGuard/log
Официальный список блокируемых доменов можно взять на сайте squidGuard – http://www.squidguard.org/ blacklist. Также доступен список от MESD – http:// squidguard.mesd.k12.or.us/blacklists.tgz. И еще один хороший список от Dansguardian – http://blacklist.dansguardian.org/cgibin/download.pl?type=download&file=bigblacklist. Кратко сравним их между собой:
34
Итак, вполне очевидно, что лучше всего взять список MESD или Dansguardian. Какой из них выбрать – оставляю на ваше личное усмотрение. И тот, и другой обновляются довольно часто. Но во избежание перегрузки сервиса, не стоит качать списки чаще чем раз в неделю. Скачав себе один из списков, распакуем его в директорию /usr/local/squidGuard/db: # tar zxvf blacklists.tgz -C /usr/local/squidGuard # mv /usr/local/squidGuard/blacklists /usr/local/ ↵ squidGuard/db
В директории /usr/local/squidGuard/db появилось несколько поддиректорий. В свою очередь, в каждой из них лежат файлы: domains – список доменов; urls – список адресов, используемых для блокирования одельной страницы, а не всего домена; expression – выражения, используемые при поиске в url. Например, sex, hot, teens, porno и т. д. Если бы мы взяли официальный список squidGuard, то внутри каждой директории можно было бы увидеть файлы обновлений к базам с такими названиями: domains.20020825.diff domains.20020901.diff domains.20020908.diff domains.20020915.diff domains.20020922.diff
Внутри каждого из этих файлов находятся записи вида: +xratedpornsite.com +209.51.157.43 -zena.cenhost.com -scuzz.xtac.com
Также в директории находятся файлы: urls.20020825.diff urls.20020901.diff urls.20020908.diff urls.20020915.diff urls.20020922.diff
С записями вроде: -silva.org/look_at_me +recom.it/fuck/beatrice
Записи, начинающиеся знаком «+», – это запрос на
администрирование добавление строчки в главную базу. Соответственно, строки с минусом имеют обратное назначение. К сожалению, применить файлы обновления можно только к базе в формате Berkeley DB. Выполняется это действие командой: # squidGuard -u
Мне кажется, что такой способ обновления не очень удобен. Поэтому нам следует либо отказаться от списка доменов, составленного squidGuard, либо написать конвертор обновлений в нормальный формат. Разобравшись с форматом базы, приступим к конфигурированию squidGuard. Cоздаем файл /usr/local/ squidGuard/squidGuard.conf. И вносим в него вот это: # òóò ó íàñ ëåæàò ëîãè logdir /usr/local/squidGuard/log # çäåñü áàçû dbhome /usr/local/squidGuard/db # îïèñûâàåì àäðåñà îòäåëà ÈÒ src it-department { ip 192.168.10.222-192.168.10.223 } # îòäåë äîñòàâêè src dostavka { ip 192.168.10.101, 192.168.10.104 } # îòäåë ñíàáæåíèÿ src snab { ip 192.168.10.105 } # ãîâîðèì, ÷òî âñå îáðàùåíèÿ ê ôàéëàì *.mp3 íóæíî ïåðåíàï# ðàâèòü íà http://192.168.10.9/replace/my.mp3 rewrite mp3 { s@.*\.mp3$@http://192.168.10.9/replace/my.mp3@r # è çàïðîòîêîëèðîâàòü ýòî ñîáûòèå â ôàéëå # /usr/local/squidGuard/log/rewr_mp3 log rewr_mp3 } # îïèñûâàåì áàçó ïîðíîñàéòîâ dest porn { domainlist porn/domains urllist porn/urls # çàïèñàòü ïðîòîêîë â ôàéë /usr/local/squidGuard/log/porn log porn } # îïèñûâàåì áàçó ðåêëàìû dest ads { domainlist ads/domains urllist ads/urls # çàïèñàòü ïðîòîêîë â ôàéë /usr/local/squidGuard/log/ads log ads # ïîäìåíÿåì âñå áàííåðû ïðîçðà÷íûì èçîáðàæåíèåì ðàçìåðîì # 1x1 ïèêñåëü redirect http://192.168.10.9/replace/1x1.gif } # îïèñûâàåì ñâîþ ñîáñòâåííóþ áàçó áàííåðíûõ ñèñòåì dest banners { domainlist banners/domains # â ýòîì ôàéëå çàïèñàíû âûðàæåíèÿ òèïà baner, banner, ads, # show_ads expressionlist banners/expressions urllist banners/urls # ïåðåíàïðàâëÿåì âñå çàïðîñû íà ïðîçðà÷íûé gif ðàçìåðîì # 1x1 ïèêñåëü redirect http://192.168.10.9/replace/1x1.gif log banners } # îïèñûâàåì äîìåíû, êîòîðûå íèêîãäà íå äîëæíû áëîêèðîâàòüñÿ # âíå çàâèñèìîñòè îò ñïèñêà ñêà÷èâàåìîãî èç ñåòè dest local-ok { domainlist local-ok/domains urllist local-ok/urls } # îïèñûâàåì äîìåíû, êîòîðûå äîëæíû áûòü çàáëîêèðîâàíû âñåãäà # âíå çàâèñèìîñòè îò ñïèñêà ñêà÷èâàåìîãî èç ñåòè dest local-block { domainlist local-block/domains urllist local-block/urls # è ïåðåíàïðàâëÿåì âñå çàïðîñû íà block.cgi redirect http://192.168.10.9/cgi-bin/block.cgi?clientaddr= ↵
№4(5), апрель 2003
%a&clientname=%n&clientident=%i&clientgroup=%s&targetgroup=%t&url=%u } # íà÷èíàåì ðàçäàâàòü ïðàâà acl { # îòäåëó ÈÒ ìîæíî âñå, êðîìå ðåêëàìû it-department { pass local-ok !banners !ads all } dostavka { pass local-ok !porn !banners !ads !local-block all redirect http://192.168.10.9/cgi-bin/block.cgi?clientaddr=↵ %a&clientname=%n&clientident=%i&clientgroup=↵ %s&targetgroup=%t&url=%u rewrite mp3 } # îòäåëó ñíàáæåíèÿ ðàçðåøàåì òîëüêî òî, ÷òî îïðåäåëåíî # â local-ok snab { # òàê ìîæíî äàòü ïîëüçîâàòåëþ äîñòóï òîëüêî ê èçáðàííûì # ñàéòàì pass local-ok none redirect http://192.168.10.9/cgi-bin/block.cgi?clientaddr= ↵ %a&clientname=%n&clientident=%i&clientgroup= ↵ %s&targetgroup=%t&url=%u rewrite mp3 } # äåéñòâèÿ, âûïîëíÿåìûå ïî óìîë÷àíèþ, åñëè ïîëüçîâàòåëü # íå îïèñàí íè â îäíîì src default { # áëîêèðóåì âñå pass none redirect http://192.168.10.9/cgi-bin/block.cgi?clientaddr= ↵ %a&clientname=%n&clientident=%i&clientgroup= ↵ %s&targetgroup=Not_Authorized&url=%u # ïèøåì ëîãè â ôàéë /usr/local/squidGuard/log/default log default } # çàêðûâàåì ñïèñîê acl }
Кстати, не забудьте скачать мою базу баннеров: http:// onix.opennet.ru/files/banners.tar.gz. Потом вы сможете вносить в нее свои собственные записи. Иначе при запуске squidGuard будет жаловаться на ее отсутствие и становиться в режим холостой работы. В этом режиме он будет пропускать все запросы без обработки. Покончив с файлом конфигурации, продолжим настройку squidGuard. Даем права пользователю, от имени которого будет работать squidGuard на директории log и db. Так же поступаем и с файлом squidGuard.conf. # chown -R nobody /usr/local/squidGuard/log ↵ /usr/local/squidGuard/db # chown nobody /usr/local/squidGuard/squidGuard.conf
SquidGuard может работать с текстовыми базами данных, но в таком случае при каждом запуске ему приходится создавать в оперативной памяти бинарное дерево всех загружаемых баз в формате Berkeley DB. Этот процесс занимает длительное время. Подобных задержек можно избежать, если заранее самому создать базы в нужном формате. На моей машине после создания баз время загрузки сократилось почти в 10 раз. Поэтому мы напишем скрипт (http://onix.opennet.ru/files/ rebuid_base.tar.gz) для перестройки баз и перезапуска squidGuard с новыми базами. # cat > /usr/local/squidGuard/bin/rebuid_base.sh #!/bin/sh /usr/local/squidGuard/bin/squidGuard -C all chown -R nobody /usr/local/squidGuard/db killall -HUP squid ^D
Устанавливаем нужные права доступа на файл
35
администрирование rebuid_base.sh. Убедимся, что этот скрипт имеет право запускать только пользовать root. # chmod 100 /usr/local/squidGuard/bin/rebuid_base.sh # /usr/local/squidGuard/bin/rebuid_base.sh
Запустив rebuid_base.sh, необходимо дождаться нормального завершения задачи. Теперь во всех директориях, упомянутых в разделах dest конфигурационного файла, появились файлы баз данных domains.db и urls.db. Перед тем как подключать squidGuard к squid, необходимо протестировать его локально. Для начала немного теории. Squid передает данные на стандартный ввод редиректора. Редиректор, в свою очередь, обрабатывает запрос и выдает на стандарный вывод результаты своей работы. Затем squid забирает эти данные. Редиректор отвечает на запрос от squid либо пустой строкой, если перенаправление не требуется, либо измененным URL. Формат запроса от squid к редиректору выглядит так:
Для того чтобы проверить, как squidGuard будет реагировать на запросы пользователей, скачиваем написанную мною тестовую программу test.tar.gz (http:// onix.opennet.ru/files/test.tar.gz). Распаковываем ее и кладем полученный файл test.pl в /usr/local/squidGuard/bin/. Устанавливаем файлу test.pl разрешение на выполнение. Затем запускаем test.pl и вводим тестируемый адрес. После этого в файле result.txt смотрим результаты работы squidGuard. Набор тестируемых сайтов можно изменять прямо в файле test.pl. Если результаты теста вас удовлетворили, значит самое время объединить squidGuard и Squid. В файл /usr/local/squid/etc/squid.conf добавляем строки: # åñëè íè îäèí èç ýêçåìïëÿðîâ squidGuard íå îòâå÷àåò, òî # ðàáîòàòü íàïðÿìóþ redirector_bypass on # ãäå íàõîäèòñÿ squidGuard redirect_program /usr/local/squidGuard/bin/squidGuard # ñêîëüêî ýêçåìðëÿðîâ squidGuard çàïóñêàòü redirect_children 1
Перезапускаем squid. В свою очередь, squid самостоятельно выполнит перезапуск всех дочерних процессов редиректоров. # killall -HUP squid
В конце файла /usr/local/squidGuard/log/squidGuard.log ищем такие строки: 2002-10-15 16:11:04 [10653] squidGuard 1.2.0 started ↵ (1034683864.337) 2002-10-15 16:11:04 [10653] squidGuard ready for ↵ requests (1034683864.353)
Если они есть, значит все работает как положено. Теперь сделаем так, чтобы Squid и Apache запускались автоматически при каждой загрузке машины. # cat > /usr/local/etc/rc.d/apache.sh #!/bin/sh /usr/local/apache/bin/apachectl start
36
^D # cat > /usr/local/etc/rc.d/squid.sh #!/bin/sh /usr/local/squid/bin/squid -D ^D # chmod 100 /usr/local/etc/rc.d/apache.sh ↵ /usr/local/etc/rc.d/squid.sh
Настало время перезагрузить машину. Это даст нам возможность посмотреть, как сервисы поведут себя при возможных перебоях в подаче электричества. В качестве маленького бонуса можно наладить автоматическое обновление базы доменов. Для скачивания файла базы доменов нам понадобится программа wget – http://www.freebsd.org/cgi/pds.cgi?ports/ftp/wget. Конечно, можно было обойтись и стандартным fetch. Но все же wget работает гораздо надежнее. Распаковываем и ставим как обычно. # tar zxvf wget-1.8.2.tar.gz # cd wget-1.8.2 # ./configure # gmake # gmake install Ñìîòðèì, êóäà îí ó íàñ óñòàíîâèëñÿ. # where wget
Пишем скрипт (http://onix.opennet.ru/files/rebuid_base.tar.gz), который будет выкачивать обновления с сайта MESD и класть их в директорию /usr/local/squidGuard/update. Затем архив с обновлениями будет распакован и скопирован в директорию /usr/local/squidGuard/bd. После этого будет произведена перестройка баз и перезапуск squid. #cat > /usr/local/squidGuard/bin/update_blacklist.sh #!/bin/sh /usr/local/bin/wget -q --cache=off ↵ 'http://squidguard.mesd.k12.or.us/blacklists.tgz' ↵ -O /usr/local/squidGuard/update/blacklist.tgz tar zxvf /usr/local/squidGuard/update/blacklist.tgz -C ↵ /usr/local/squidGuard/update/ cp -R -f /usr/local/squidGuard/update/blacklists/* ↵ /usr/local/squidGuard/bd rm -R /usr/local/squidGuard/update/blacklists /usr/local/squidGuard/rebuid_base.sh ^D
Теперь даем нашему скрипту нужные права. # chmod 100 /usr/local/squidGuard/bin/update_blacklist.sh
Создадим временную директорию, в которую будут распаковываться обновления. # mkdir /usr/local/squidGuard/update
Настраиваем планировщик на выполнение нашего задания. # crontab -e -u root MAILTO="admin@test.ru" 1 0 * * 7 /usr/local/squidGuard/bin/update_blacklist.sh
Назначаем выполнение обновления на 0 часов 1 минуту каждого воскресенья. Уведомление о выполнении этого задания приказываем направлять на адрес admin@test.ru. Теперь осталось раздать всем пользователям подобающие права и можно отдыхать.
FAQ Shell ВОПРОС: Как работать с интерактивными программами, например, telnet или ftp? ОТВЕТ: Вопрос не относится непосредственно к shell, для решения этой задачи удобно использовать специальный пакет функций tcl -expect (http://expect.nist.gov). Данный пакет содержит функции: spawn – породить процеcc; send – послать процессу входные данные; expect – в зависимости от выводимых данных послать процессу некие входные данные. Простой пример – получение файлов по ftp в автоматическом режиме: spawn /usr/bin/ftp ftp.myhost.ru expect{ "Name*: " {send "username\r"} "Password:" {send "user_password\r"} "failed" {puts "Can`t login."; exit 1} } send "lcd /etc\r" expect "ftp> " {send "cd /pub/etc\r"} expect "ftp> " {send "get passwd\r"} expect "ftp> " {send "quit\r"} exit 0
Работа с telnet и ssh также не должна вызвать затруднений (кроме автокоманд на сервере, выполняемых при запуске командного интерпретатора). А вообще, expect – это очень полезный инструмент, позволяющий автоматизировать интерактивные операции (учтите, что для его работы необходим tcl). ВОПРОС: Как узнать, в командном или интерактивном режиме работает shell? ОТВЕТ: Можно проверить специальную переменную $- или переменную $PS1. Для первого случая можно использовать скрипт, подобный такому: case $- in *i*) # èíòåðàêòèâíûé ðåæèì ;; *) # íåèíòåðàêòèâíûé ðåæèì ;; esac
Проверка режима оказывается полезной при написании сценариев, когда неизвестно, необходимо ли выводить в stdout или stderr какие-либо данные (нет смысла в неинтерактивном режиме). Также полезно применять в инициализационных сценариях оболочки (например, чтобы выполнение отдельных команд через ssh или rsh не вызывало запуск кучи вспомогательных программ). Для оболочки C (csh, tcsh) синтаксис проверки будет несколько иным: if(! $?prompt) # íåèíòåðàêòèâíàÿ îáîëî÷êà exit else # èíòåðàêòèâíàÿ îáîëî÷êà echo Hi exit endif
№4(5), апрель 2003
ВОПРОС: А почему большинство скриптов написано на Bourne shell? Почему моя любимая tcsh обойдена вниманием? ОТВЕТ: Скажу к слову, tcsh – это и моя любимая оболочка, я работаю в ней, как в интерактивной, но скрипты всегда пишу в Bourne shell. Причина проста: скрипты на Bourne shell больше распространены, и любому администратору необходимо знать эту оболочку, по ней есть много документации, в том числе и на русском языке. Программировать в C-shell несколько привычнее, но многочисленные ошибки реализации языка (особенно в клаccическом csh) сильно затрудняют работу. В частности, не очень удобен механизм перенаправлений: sh: mpg123 ./*.mp3 > /dev/null 2>&1 csh: mpg123 ./*.mp3 > /dev/null) >& /dev/null
В оболочке C практически невозможно нормально разделить stdout и stderr. ВОПРОС: В моей системе нет команды killall. Что можно придумать? ОТВЕТ: Пишем примерно такой сценарий: #!/bin/sh kill $1 `ps ax | grep $2 | awk '{print $1}'| sed 's/\n/ /g'`
Вызываем скрипт так: killall -9 ftpd
Один минус: убивается больше процессов, чем нужно, т.к. grep находит сам себя и пытается убить лишние процессы. Хотя это несмертельно, но если такого процесса нет, то программа всё равно выводит Killed. Поэтому вывод надо дополнительно фильтровать, но мне было вполне достаточно такого варианта. ВОПРОС: Как найти в /etc/passwd записи с нулевым UID (кроме root)? ОТВЕТ: #/bin/sh for i in `awk -F: '{if($3 == "0" && $1 != "root") print $1}' /etc/passwd` do mail -s "Strange user!" root@mymail.net << EOT There is a user ${i} that has uid = 0 `date` EOT done
Удобно добавить этот скрипт в crontab (учтите, что используется gawk -параметр -F могут не понять старые версии awk, в таком случае внутри awk-скрипта надо установить FS=":").
Составил Всеволод Стахов
37
УСТАНОВКА И НАСТРОЙКА СЕРВЕРА JABBER НА ПЛАТФОРМЕ LINUX СЕРГЕЙ ИНДЛИН
администрирование Что же такое Jabber? Это открытый XML-протокол, предназначенный для мгновенного обмена сообщениями между узлами в Интернете. Коротко перечислю основные преимущества Jabber: открытый протокол: над развитием Jabber работает большое количество людей, доступны различные реализации и библиотеки. Все спецификации и документация находятся в свободном доступе; Jabber – децентрализованная система, не зависящая от единого сервера или компании. Любой пользователь может поставить свой сервер и подключить его к открытой сети или ограничить его работу локальной сетью предприятия; безопасность: большинство реализаций серверов поддерживают связь с клиентами по шифрованному каналу SSL, возможно шифрование сообщений с использованием gpg; поддержка unicode. Для нас это означает отсутствие проблем, связанных с различными кодировками русского языка; функциональность сервера можно расширять с помощью дополнительных модулей. Например, для связи с другими системами IM можно использовать агентов icq, yahoo, aim, msn. Для поддержки многопользовательских конференций также существует модуль, возможна связь с irc-сетями. На странице http://www.jabber.org/admin/serverlist.php можно найти список доступных реализаций серверов. Здесь я опишу установку и настройку свободного сервера Jabber, распространяемого под лицензией GNU GPL – jabberd 1.4.2. Несколько слов об идентификаторах. Jabber использует систему имен, аналогичную адресу электронной почты: name@host.domain, в отличие от icq, где применяются цифровые идентификаторы. Например, мой JID (Jabber ID) – serj@abc92.ru.
Установка сервера На домашней странице проекта http://jabberd.jabber studio.org можно скачать исходники сервера или готовые пакеты для различных систем. Для дистрибутивов ALT Linux сервер Jabber можно установить из репозитария Sisyphus командой apt-get install jabber. При сборке из исходников сервер не устанавливается в системные каталоги, а стартует прямо из каталога сборки. Развернем исходный тарбол в директорию, например, /usr/local/jabber. Для сборки в системе должны присутствовать, помимо обычной сборочной среды (gcc, make, библиотеки и т. д.), библиотеки libpth, libpth-devel, libssl, openssl-devel (в разных системах названия могут немного отличаться). Заходим в каталог /usr/local/jabber и даем команду ./configure —enable-ssl. Внимательно читаем вывод. Вначале должна быть строка “Searching for SSL... Found”. Если все хорошо, даем команду make и ждем, пока соберется сервер. После успешной сборки приступаем к конфигурированию. Если ваша сеть защищена фаерволом, надо учесть,
№4(5), апрель 2003
что Jabber-сервер использует порт 5222 (5223 ssl) для связи с клиентами и порт 5269 для связи между серверами. То есть если вы хотите, чтобы клиенты извне могли использовать ваш сервер, надо открыть порты 5222 и 5223. Если вы хотите, чтобы пользователи вашего сервера могли общаться с пользователями других серверов, надо открыть порт 5269. При возникновении проблем стоит прочитать руководство администратора, расположенное по адресу: http:// www.jabber.org/admin/adminguide.html.
Настройка сервера Основной файл настроек сервера называется jabber.xml и, как можно понять из названия, имеет формат xml. Конфигурационный файл хорошо документирован, для редактирования можно использовать любой xml или текстовый редактор. Итак, открываем в удобном текстовом редакторе файл /usr/local/jabber/jabber.xml и внимательно читаем комментарии. Вот что можно поменять для начала: тег host – имя сервера. Если вы хотите общаться с пользователями других серверов, или клиенты подключаются через Интернет, это имя должно быть зарегистрировано в DNS. Для сборки ALT Linux определяется в файле /etc/jabber/jabber.cfg; vCard – описание нашего сервера; welcome – сообщение, которое будет посылаться новым пользователям; cекция admin – здесь надо задать локальные идентификаторы администраторов (предварительно раскомментировав секцию). Имена в теге read будут получать административные сообщения (например, о регистрации новых пользователей), а в теге write дополнительно могут делать рассылки и задавать сообщение дня; update – проверять обновления сервера. Спокойно можно закомментировать. Теперь стоит настроить ssl-подключение к серверу для защиты трафика между клиентами и сервером. Для генерации сертификата используем следующий скрипт (http://www.jabber.org/admin/adminguide.html#security-ssl): OPENSSL=/usr/bin/openssl ## This generates the cert and key ## The key will be valid for 3650 days. ## Be sure to enter the FQDN of your Jabber ## server as the «Common Name». $OPENSSL req -new -x509 -newkey rsa:1024 -days 3650 -keyout privkey.pem -out key.pem ## This will remove the passphrase $OPENSSL rsa -in privkey.pem -out privkey.pem ## Put it all together cat privkey.pem >> key.pem ## Cleanup rm privkey.pem
При генерации ключа в качестве “Common Name” необходимо использовать имя Jabber-сервера. После того как файл с ключами готов, надо разрешить в конфиге Jabber-сервера использовать ssl-порт. В файле /usr/local/jabber/jabber.xml находим секцию io и в ней раскомментируем секцию ssl, указав полный путь
39
администрирование к файлу сертификата: /usr/local/jabber/key.pem, а в секции pthcsock надо раскомментировать строку ssl и задать ip для ssl-порта. Ну вот, теперь можно попробовать запустить сервер. Из каталога /usr/local/jabber даем команду jabberd/jabberd -D и смотрим на отладочную информацию. Берем любого клиента (под Windows я рекомендую jajc, под Linux – tkabber) и пытаемся подключиться к серверу. При первом подключении должно появиться предложение создать новую учетную запись. Посмотрим, какие же сервисы у нас есть. Для этого в клиенте открываем браузер ресурсов и видим только один сервис – адресная книга jabber.org. Давайте настроим некоторые дополнительные сервисы на нашем сервере. Подробнее об администрировании сервисов можно прочитать на странице: http://www.jabber.org/admin/ componentadminguide.html.
Адресная книга Для установки на ALT Linux достаточно дать команду aptget install jabber-jud. Для других дистрибутивов можно скачать jud (jabber user directory) со страницы http:// jabberd.jabberstudio.org/downloads. Скачав исходник, развернем его прямо в директорию /usr/local/jabber. Переходим в директорию /usr/local/jabber/jud-0.4 и даем команду make. После успешной сборки читаем файл README и копируем нужные секции в основной конфигурационный файл /usr/local/jabber/jabber.xml. Будьте внимательны: секцию “service id="jud"“ надо скопировать в корневой раздел (внутри тега jabber), а “service type="jud"“ – в раздел browse. Меняем имя хоста на реальное в обеих секциях, правим путь к jud.so на наш – ./jud-0.4/jud.so и по желанию меняем vCard. Теперь можно перезапустить сервер и наслаждаться корпоративной адресной книгой.
Конференции Новый протокол конференций muc поддерживается агентом muconference-0.3.tar.gz, доступным на странице http://mu-conference.jabberstudio.org. Скачиваем архив и разворачиваем его в директорию jabber. Переходим в новую директорию /usr/local/jabber/mu-conference и даем команду make. После успешной сборки внимательно читаем файл README и копируем оттуда нужные секции в конфигурационный файл Jabber сервера jabber.xml. Не забудьте поменять localhost.localdomain на реальное имя хоста. Если вы хотите, чтобы конференции были дос т упны из Интернета, зарегис трируйте имя conference.host.domain в службе DNS. Теперь можно перезапустить сервер и с помощью браузера ресурсов убедиться, что новый сервис доступен на сервере. В клиенте попробуйте зайти в комнату и настроить ее свойства. Комнату можно сделать постоянной, приватной, запароленной и т. д. При разговоре в комнате работают команды с префиксом “/” типа /me, /smile и множество других. В клиенте tkabber на эти команды работает дополнение клавишей tab.
40
ICQ-транспорт Для Jabber есть два транспорта icq – icqv7-t и jit. Jit мне показался более продвинутым. Он поддерживает перекодировку через параметр в конфигурационном файле (для icqv7-t нужно патчить исходный код), работает поиск icq-контактов, кроме того, jit более стабильный, чем icqv7-t. Для установки скачиваем архив с исходным кодом на странице http://jit.jabberstudio.org и раскрываем его. Jit идет со своей версией Jabber-сервера и запускается как отдельный процесс. Даем команду ./configure и make. Если все собралось без ошибок, копируем файлы jabberd/jabberd, jit/jit.so в любую директорию, например, /usr/local/jabber/jit. Туда же копируем файл jabbericq.example и переименовываем его в jabber-icq.xml. Теперь надо отредактировать этот файл, указав свои имена сервера. Так как в нашем случае этот сервис будет выполняться на той же машине, что и основной сервер Jabber, в качестве ip указываем 127.0.0.1. В теге secret задаем пароль для связи с основным сервером Jabber. Протокол icq ничего не знает про unicode, а в нашей стране исторически сложилось использование кодировки windows-1251 для icq. Поэтому сервису jit необходимо знать, в какую кодировку преобразовывать сообщения из/в unicode. Эта кодировка задается тегом charset, который надо установить в windows-1251. Внимательно читаем файл INSTALL в директории /usr/local/jabber/jit/jit и копируем из него нужные секции в конфиг jabber.xml основного сервера. Помните об иерархии тегов. Секция “service id="icq"“ должна быть вложена в тег jabber конфига, а секция “service type="icq"“ в раздел browse. Меняем, как обычно, имена сервера, в поле ip задаем 127.0.0.1, secret – тот же, что и в jabber-icq.xml и порт 5555. Эти параметры определяют, по какому порту основной сервер будет ждать связи от jit-процесса. Перезапускаем основной сервер Jabber и запускаем отдельным процессом jit: /usr/local/jabber/jit/jabber -H /usr/local/jabber/jit/ -c /usr/local/jabber/jit/jabber-icq.xml
В клиенте открываем браузер ресурсов и находим ICQ Link. Пытаемся зарегистрироваться. В качестве имени вводим свой числовой номер icq. Если все хорошо, то в ростере должен появиться агент с именем ICQ Transport. Теперь можно добавлять контакты icq в форме uin@icq.host.domain, искать через сервис ICQ Link/search или импортировать существующие контакты. Кстати, если вы использовали раньше icq с сохранением контактов на сервере, то jit их автоматически импортирует. Я надеюсь, что эта статья облегчит вам установку собственного сервера Jabber. Не так уж это и сложно. Дополнительно можно установить агентов доступа к сетям aim, jahoo, msm – ведь Jabber является открытым, расширяемым решением для взаимодействия. В качестве информации на русском языке рекомендую сервер http://www.jabber.ru, на этом же сервере можно свободно зарегистрироваться. И успешного Jabber-а!
FAQ Shell ВОПРОС: В чем состоят отличия различных оболочек? ОТВЕТ: Сравнительная таблица наиболее известных оболочек может быть найдена на http://www.looking-glass.org/ shell.html. Одной из наиболее функциональных оболочек является zsh (хотя за функциональность приходится расплачиваться некоторой потерей быстродействия). Для большинства операций обычно достаточно bash или tcsh. Вообще существует два типа оболочек – произошедшие от Bourne shell (sh, bash, ksh, zsh) и произошедшие от C-shell (csh, tcsh). Отличия в синтаксисе оболочек весьма существенны. Оболочки, произошедшие от Bourne shell, чаще используются для программирования, так как язык C-shell далёк от совершенства (хотя я бы не сказал, что tcsh многим уступает в возможностях программирования bash, но исторически csh обладал кучей огрехов, поэтому сейчас более распространён синтаксис Bourne shell). Оболочки С-shell всегда являлись больше интерактивными оболочками, но язык их скриптов намного ближе тем, кто знаком с языком С. К сожалению, русской документации по C-shell я не встречал. Может быть, в скором времени этот пробел будет заполнен. ВОПРОС: Существует ли руководство по bash на русском языке? ОТВЕТ: Да, есть: http://ln.com.ua/~openxs/projects/man/solaris8/bash.html http://www.citforum.ru/programming/shell/index.shtml ВОПРОС: Как работают текстовые замены и подстановки в bash? ОТВЕТ: Вообще текстовые замены и подстановки – это одна из самых мощных возможностей bash (в оригинальной sh эти возможности сильно урезаны). Существует несколько типов текстовых подстановок командной строки: фигурные скобки – всё, что находится в командной строке в фигурных скобках {}, расценивается как шаблон для поиска, объединённый командой ИЛИ: file{1,2} заменится на file1 file2 chown root /usr/{ucb/{ex,edit},lib/ {ex?.?*,how_ex}; подстановка $ – все, что идёт после данного символа расценивается как значение переменной или результат выполнения команды. Также полезно окружать подстановку после $ фигурными скобками (отделение от остальной части текста): echo "${HOME} – this is where you files are". echo ${`date`}; подстановка процессов; подстановка имён файлов; разбиение переменных на слова – по умолчанию интерпретатор разбивает все переменные и результаты выполнения команд, не заключённые в двойные кавычки, на слова, что позволяет обрабатывать переменные в циклах по полям. Существует достаточно много дополнительных параметров подстановки (например, подстановка подстрок или ус-
№4(5), апрель 2003
тановка переменной по умолчанию), но охватить всё в рамках данного вопроса явно не удастся, за дополнительными сведениями обращайтесь к документу http://ln.com.ua/ ~openxs/projects/man/solaris8/bash.html#expansion. ВОПРОС: В чем отличие различных кавычек в shell? ОТВЕТ: Кавычки – это очень полезный инструмент. Различные виды кавычек применяются в различных случаях (учтите, кавычки сохраняют своё значение и в интерактивной оболочке). Итак, какие бывают кавычки: двойные(") – внутри таких кавычек происходят все текстовые подстановки (см. ниже), в том числе и подстановка обратных кавычек. Например, echo "$PATH" выведет значение переменной PATH, а echo "${PATH} `date`" выведет значение PATH, поставит пробел и подставит результат выполнения программы date; одинарные(') – внутри одинарных кавычек всё печатается как есть, без подстановок: echo '$PATH' выведет $PATH; обратные(`) – подставление вывода указанной в кавычках команды, также выполняются все подстановки: `ps aux | grep $1` – выведет список заданных в аргументе $1 процессов. Учтите, что результатом могут быть несколько строк. ВОПРОС: Как прочитать несколько строк с терминала? ОТВЕТ: Для этого используется цикл while с командой read. Стандартное решение: while read line do echo $line done
Можно выполнять построчное чтение не с терминала, а из файла – для этого достаточно выполнить перенаправление цикла: while read line do echo $line done < /etc/passwd
C другой стороны, для операции со строками лучше всего использовать awk. Очень удобно использовать awk для выбора некоторых слов из строки, но программирование в awk – это большая отдельная тема. ВОПРОС: Будет ли продолжение данного FAQ? ОТВЕТ: Задавайте ваши вопросы мне: CEBKA@smtp.ru. Наиболее интересные войдут в этот список.
Составил Всеволод Стахов
41
РАЗВОДНОЙ МОСТ НА LINUX (BRIDGING FIREWALLS)
администрирование Для подключения телекоммуникационных сетей к Интернету провайдер на целую сеть обычно выделяет всего лишь один реальный IP-адрес, а далее вы организуете у себя компьютер-шлюз, за которым располагаете вашу сетку с адресами вида 192.168.x.x (либо 172.16.0.0/12, либо 10.0.0.0/8) из RFC 1918. На компьютере-шлюзе обычно имеется две сетевые карты, поднимаются прокси-сервера тех или иных сервисов либо NAT (трансляция адресов или маскарадинг), либо всё сразу. Такая конфигурация встречается очень часто, поэтому в литературе хорошо описано, что и как настраивать. Однако в случае, когда все адреса, выделенные провайдером, являются реальными, существует несколько решений по организации сети. В литературе об этом пишут меньше, поэтому об одном весьма удобном способе организации я и попробую рассказать.
ПАВЕЛ ЗАКЛЯКОВ
Ситуация с адресами на сегодняшний день критическая, в том смысле, что IP-адресов v.4 не хватает, а конечные пользователи никак не планируют свой переход на IP v.6. С одной стороны, хорошо, если все компьютеры в сети будут иметь реальные адреса. Но с другой, это породит и часть проблем, таких как сокрытие внутренней организации сети, сокрытие числа пользователей в сети, расходуемого ими трафика и получаемых в итоге доходов. Удобно, когда все внутренние хосты маскируются за одним адресом, поэтому это очень популярно у нас в России. Также это удобно с точки зрения настройки. В случае смены провайдера (или внешнего IP-адреса) менять настройки придётся на одном компьютере, а не на всех компьютерах внутренней сети. Хотя бывают случаи, когда упрощения процесса перенастройки не происходит (если используются DNS- и SMTP-сервера провайдера). Возникает логичный вопрос: «А как следует правильно развивать сети, чтобы иметь при этом меньше проблем?». Однозначного ответа на этот вопрос дать нельзя. Вопрос о том, что лучше: реальные (легитимные) или маскируемые (нелегитимные) адреса и как их использовать, на мой взгляд, заслуживает отдельной статьи. Поэтому дискуссию по этому вопросу я предлагаю перенести на форум сайта журнала. Итак, вам предстоит работать с реальными адресами. Правила организации сетей никто не отменял, и если вам нужен всего лишь один IP-адрес, то реально провайдер выделяет вам подсетку из 4-х адресов. Запишем адрес в двоичном виде и посмотрим только на два последних бита в двоичной записи: 00 – адрес сети; 11 – широковещание (broadcast), а два оставшихся – 01 и 10 – ваши адреса. Так как для общения с внешним миром в вашей сетке обязательно должен быть шлюз, которому также надо выделить один реальный адрес, пусть им будет 01. В результате для нас остаётся один-единственный адрес, заканчивающийся на 10. Небольшое замечание: при подсчёте трафика провайдер будет суммировать всё, что будет попадать на все адреса сети, в последнем примере – это 4 адреса, а не тот один, который присвоен вашему компьютеру. Так что это следует учесть и не удивляться, что при правильном учёте трафика ваши данные и данные провайдера будут расходиться не в вашу пользу. Но, как известно, всегда бывают исключения. Если же провайдером выделяется несколько большая подсесть, скажем, в два раза большая, то реально будет выделено не 8, а 8-3=5 адресов. Иметь 8 адресов подряд куда более выгоднее, чем 4+4. Вот вам и арифметика – «1+1=5». Если адресов будет 16, то возможных к использованию будет уже 16-3=13 и т. д. Обычно большие сети делятся на подсети, если адресов много, то потери невелики, и от деления получается только выгода. А вот если поделить 8 адресов, то явно будут большие потери. Легко понять, что потери кроются вроде как в лишнем адресе подсети и лишнем адресе для шлюза. Каким образом поделить сеть, чтобы не терять адреса? Это мы и попытаемся сделать. Довольно часто бывает, что шлюз, используемый в провайдерской сети, не имеет большого числа настроек, либо вообще находится на попечении провайдера и не подвластен для вашего контроля. Поэтому областью наших настроек и экспериментов будет все, что находится за зтим шлюзом.
43
администрирование Ограничим область наших действий. Для этого предлагаемые советы по организации нелегитимной сети следует сразу отклонить. Компьютеры внутри сети должны иметь реальные адреса. Для подсчёта трафика можно поставить хаб у шлюза и, подключив к нему сниффер, можно будет считать трафик – это выход. Но что делать, если надо какой-то пакет не пропустить? Скажем, если надо иметь небольшой межсетевой экран (МЭ), а не только подсчёт трафика. Собственно, зачем нужно разделение сетей на подсети? Именно для того, чтобы одни другим «не мешали». У многих для решения этого вопроса часто приходит в голову мысль: а почему бы не поставить компьютер с двумя сетевыми карточками. С одной стороны его надо соединить со шлюзом, а с другой стороны к нему подключить все компьютеры сети. Решение, вообще говоря, правильное, но далее начинаются проблемы. (Для удобства изложения наш компьютер «посередине» назовём межсетевым экраном (МЭ), а так как на нём стоит Linux, то будем называть его также и Linux.) Если вы хоть раз сталкивались с тем, что у вас справа и слева от МЭ одна и та же сетка, то вы поймёте, почему возникали проблемы. Разумный до этого (при работе NAT) компьютер перестаёт понимать, как ему работать. Наверное, он «думает», что обе карточки смотрят в одну строну, а не в разные. (Замечание: использование с одним адресом двух стоящих вместе сетевых карт в виде одной логической, более производительной сетевой карты, не новость, а способ повышения быстродействия сети при минимизации затрат.) Я спрашивал многих людей, как это сделать и мне отвечали по-разному: начиная с советов по настройке масок 255.255.255.255 на интерфейсах МЭ и заканчивая покупкой профессиональных средств, таких как CISCO PIX Firewall и др. При этом необходимость покупки обосновывалась тем, что сделать так, чтобы и слева и справа (на разных сетевых интерфейсах) у компьютера на базе Linux была одна и та же сеть, и пакеты попадали с одного интерфейса на другой – невозможно. Поэтому у меня и родилась идея написать эту статью, дабы поделиться своим опытом. Пусть карточка на МЭ, смотрящая на интернет-шлюз, будет eth0, а смотрящая в сеть с компьютерами – eth1.
* Во время подготовки статьи к печати высказывались различные замечания, которые я постарался учесть в той или иной мере. Одно замечание я привожу без изменений, так как времени проверить самому, работает это или нет, у меня не было, да и когда писал статью, я о данной возможности не знал, а давать непроверенный совет от своего имени я не могу – совесть не позволяет. Так что привожу замечание Всеволода Стахова, может быть, кто-то им воспользуется, и оно окажется более полезным, чем вся моя статья. «На самом деле это работает – читай Linux Advanced
44
Тогда даже прописанные вручную правила: # # # # #
route route route route route .. # route # route
add add add add add
-host -host -host -host -host
x.x.x.1 x.x.x.2 x.x.x.3 x.x.x.4 x.x.x.5
dev dev dev dev dev
eth0 eth0 eth1 eth1 eth1
add -host x.x.x.y dev eth1 add default gw x.x.x.1
показывающие, что тот или иной IP-адрес следует искать на том или ином интерфейсе, не помогают*. Сам компьютер, на котором стоит МЭ, «видит» все машины после прописывания подобных правил, машины сети и Интернет «видят» Linux. Но машины сети отказываются видеть шлюз, ну а шлюз, в свою очередь, отказывается видеть машины в сети. Указание в настройке машин сети шлюзом адреса x.x.x.3, привязанного к интерфейсу eth1, ни к чему не приводит, и дело кажется тупиковым. Всё это происходит, потому что умный шлюз не знает о том, что надо передавать пакеты для адресов x.x.x.4, x.x.x.5 и др. на адрес x.x.x.2. Если провести эксперимент: при вышеописанной конфигурации назначить на eth0 вместо адреса x.x.x.2 ненадолго адрес x.x.x.4, далее обратиться с него куда-либо в Интернет, чтобы шлюз его «увидел», а затем быстро поменять всё обратно, то некоторое время общение с компьютером x.x.x.4 будет нормальным. Он будет «видеть» шлюз и Интернет. Интернет также будет видеть его. Такая ситуация многих вдохновляет: заработало! Шлюз пингуется, а машины сети видны из Интернета. Но радость быстро проходит, когда происходит обновление arp-таблицы шлюза. Если шлюз ваш, то проблема в принципе решается просто. Необходимо на шлюзе для адресов, находящихся за МЭ, указать адрес x.x.x.2 в качестве gateway, подобно тому как в настройках Linux шлюзом является адрес x.x.x.1. Тогда наш шлюз будет слать пакеты на MAC-адрес eth0 и всё должно работать. Не следует искать проблем в отсутствии 1 в файле /proc/sys/net/ipv4/ ip_forward или в отсутствии поддержки ip_forward в ядре, ошибок в настройке iptables (ipchains) или где-то ещё. В нашем случае проблема состоит в том, что мы не можем перенастраивать шлюз. Существует решение этой проблемы в виде моста (bridge). Логично предположить: а кто мешает Linux брать пакеты с одной карточки из одной физической сети и передавать их в другую физическую сеть, в которую смотрит другая его карточка. Сразу хочу вас обрадовать, что у меня всё это работает (более года) довольно быстро и не требует больших ресурсов. Меня же, до того routing and traffic guide – я проверял, у меня подобное работает. Единственный минус, когда во внутренней сети много машин. В данном примере, по-моему, неправильно записаны правила. На мой взгляд, их надо записать так: # echo 200 mytable >> /etc/iproute2/rt_tables # ip rule add from x.x.x.1 dev eth0 table mytable ... # ip route add default via x.x.x.1 dev eth0 table mytable # ip route flush cache
Это работает.»
администрирование как я это сделал, многие «теоретики» уверяли, что сделать такое можно, но работать это будет медленно, особенно если я захочу, чтобы вдобавок происходила фильтрация пакетов. «О МЭ и думать забудь, – говорили они, – если у тебя не Dual Xeon». У меня AMD K7 (Duron) великолепно справляется с этой задачей, причём на 100-мегабитной сетке по команде # top
загрузка от пересылки и фильтрации не превышает 3-4%. Так что можно смело говорить о том, что при сегодняшних ценах решение получается дешёвое. Большую часть загрузки процессора забирают на себя другие процессы, как snort и httpd сервера apache, как видно из рисунка. Если же обращения к веб-серверу нечастые, то большую часть загрузки потребляет сама программа top. Данный screenshot был сделан сразу после завершения скачивания 50-мегабайтного файла, который скачивался несколько секунд.
Предполагается, что вы немного знакомы с Linux и знаете, где можно скачать нужную версию ядра. (Для тех, кто не знает – ядра лучше брать на http://www.kernel.org или http://www.ru.kernel.org.) После скачивания нужного ядра следует наложить на него патчи, которые качаем отсюда: http://bridge.sourceforge.net/ download.html. Для различных версий ядра нужны различные патчи. У меня всё работало на ядрах версий 2.4.18 и 2.4.19. С ядром версии 2.4.20 я не экспериментировал, но и патча пока не видел, возможно, ядро уже подкорректировано нужным образом, так что патч ему не нужен. Для наложения патча в версиях, требующих его применения, следует выполнить из директории, где расположено ваше ядро, команду: # patch -p0 -E <ôàéë_ñ_ïàò÷åì
Опция -p0 указывает на то, что вы будете накладывать патч, находясь в директории уровня 0, то есть где находятся файлы и директории ядра, либо: # patch -p1 -E <ôàéë_ñ_ïàò÷åì
если вы будете выполнять команду из директории, содержащей каталог с номером ядра. Первый вариант лучше, так как вашу директорию вы можете называть хоть linux, хоть linux-2.4.19 и пр. Ключ -E говорит о том, что следует удалять пустые файлы, если таковые окажутся после наложения патча. Если у вас ядро версии 2.4.19, то имя файла патча будет bridge-nf-0.0.7against-2.4.19.diff. После успешного наложения патча следует начать обычную процедуру конфигурирования ядра. Можно править руками файл .config, а можно запустить # make menuconfig
находясь в директории с ядром. (Если у вас не появляется меню или что-то не работает, то, возможно, вы не установили средства разработки ядра. Придерживайтесь выводимых сообщений об ошибках – они содержат достаточную информацию. Часто забывают установить библиотеку ncurses.)
Хочу порекомендовать следующие ссылки: http://bridge.sourceforge.net http://bridge.sourceforge.net/docs/Firewalling for Free.pdf http://www.sparkle-cc.co.uk/firewall/firewall.html В результате у вас должна появиться возможность прозрачного фильтрования и учёта трафика. Можно сказать, что мы с вами сделаем МЭ-мост, который при желании можно сделать почти неуязвимым и невидимым, но об этом чуть далее, в процессе настройки. Также за счёт фильтрования и возможной установки не двух, а более сетевых карточек, у вас появится возможность очень гибкой настройки вашей сети или ваших псевдо-подсетей. Если докупить отдельно расширитель, увеличивающий число PCI-слотов в вашей системе, то можно соорудить что-то вроде коммутатора CISCO серии 2900.
№4(5), апрель 2003
В меню настройки конфигурации ядра в разделе «Networking options» нужно поставить звёздочку (или букву М), выбрав слудующий пункт: <*> 802.1d Ethernet Bridging
45
администрирование Для .config равносильно внесению строчки CONFIG_BRIDGE=y, либо CONFIG_BRIDGE=m.
ды из директории, где установлены исходники ядра: # make dep # make clean # make bzImage
В дальнейшем я не буду акцентировать внимание о включении той или иной опции в качестве модуля. Фактически, это всё, что нужно конфигурировать в ядре для работы моста, и для проверки этого вполне хватит, но чтобы не компилировать ядро несколько раз, мы сразу включим и другие полезные для нас опции. [*] Frame Diverter (EXPERIMENTAL)
либо CONFIG_NET_DIVERT=y. Если в меню такого пункта нет, возможно, что вы не включили в самом первом меню: Code maturity level options --->
пункт [*]Prompt for development and/or incomplete code/drivers
либо CONFIG_EXPERIMENTAL=y. Далее включаем поддержку сетевого фильтра iptables, если она не была включена: [*] Network packet filtering (replaces ipchains)
либо CONFIG_NETFILTER=y. У нас появится подменю: IP: Netfilter Configuration
Далее можно скомпилировать модули, но если у вас что-то не будет грузиться, то вы зря потратите время на компиляцию модулей два раза, так что разумнее на этом этапе прописать новую конфигурацию, а модули скомпилировать потом, после того как станет ясно, что ядро у нас рабочее и не надо его перекомпилировать в новой конфигурации. Для этого надо взять созданный файл bzImage: при успешном создании он будет лежать, скорее всего, в директории /usr/src/linux-2.4.x/arch/i386/boot. Его желательно переименовать во что-то более удобное, чем bzImage, например в vmlinuz-2.4.x, и поместить в директорию /boot. Следует подправить либо /etc/lilo.conf, либо /etc/grub.conf, в зависимости от установленного у вас загрузчика. Допишите новую конфигурацию по аналогии, не удаляя при этом старую! В случае загрузчика grub можно просто перезапускаться. В случае lilo следует его запустить, чтобы он внёс необходимые изменения. # lilo
Не забудьте это сделать! Для grub файл /etc/grub.conf есть символическая ссылка на /boot/grub/grub.conf. (На всякий случай, initrd – это команда инициализации ramdisk, она прописывается для конфигурации виртуального диска в памяти и загрузки его из образа; при установке по умолчанию такой образ имеется в той же директории /boot. Строчку, содержащую initrd, копировать по аналогии совсем не обязательно.) Далее, если загрузка прошла успешно (не имеются в виду возможные ругательства системы при загрузке на отсутствие модулей), то можно довести дело до конца, скомпилировав и установив модули. Если же загрузка не проходит, возможно, что-то вы скомпилировали не так, или не тот процессор указали, или что-то ещё. Я предполагаю, что остальные пункты меню у вас настроены правильно, поэтому и не рассматриваю их. Для компиляции и установки модулей нужны следующие команды:
--->
Здесь разумно включить все, что может вам понадобиться. Если сомневаетесь, то попробуйте включить всё, лучше пусть что-то пригодится с меньшей вероятностью, чем что-то не будет работать (правда, и работать такое ядро будет чуть медленнее). При включении поддержки сетевого фильтра, под выбранным нами ранее пунктом 802.1d Ethernet Bridging, должен появиться пункт:
# make modules # make modules_install
запускать их следует из той же директории, что и make menuconfig, make dep... После успешной компиляции и установки модулей следует перезагрузиться. Если всё прошло успешно, то можно приступить к настройке моста. Для начала нам понадобятся bridge-utils. Для Red Hat-подобных Linux имеется rpm-файл, который устанавливается командой: # rpm -i bridge-utils-0.9.6-1.i386.rpm
[*] netfilter (firewalling) support
иногда пишут либо CONFIG_BRIDGE_NF=y. Выбираем его. Это нужно, чтобы мы могли фильтровать пакеты – «делать мост разводным». Далее идут стандартные шаги компиляции ядра. Запустите коман-
46
# rpm -ihv bridge-utils-0.9.6-1.i386.rpm
(Что означают те или иные ключи, смотрите man rpm.)
администрирование Обладателям RPM-несовместимых дистрибутивов придётся немного посложнее, но для них имеется .tag.gz файл почти того же самого содержания. При установке программы из него у вас не должны возникнуть проблемы. После установки можно попробовать создать новый мост. Придумаем нашему мосту разумное имя, пусть он будет называться bridge0 (можно давать имена без цифр, например, mybridge) и создадим его командой
не про МЭ начинал писать, а про организацию моста и возможную пользу из этого, помимо экономии IP-адресов. Далее можно поднять интерфейс нашего моста, присвоив ему один из IP-адресов из нашей сети. (Это разумно: зачем серверу иметь 2 адреса, если вы, уже опередивши, подумали вместо 0.0.0.0 для eth0 и eth1 прописать реальные адреса, то скажу, что работать с двумя адресами тоже будет, но один адрес будет явно «лишним».) Сделать это просто: как обычно, запустите:
# brctl addbr bridge0
Имеющийся у нас мост следует закрепить, прояснив для себя, на какие берега он будет крепиться, другими словами, выделить сетевые интерфейсы, которые будут работать с мостом. Заметьте, что карточек в сервере может быть много и совсем необязательно все из них задействовать для организации моста. Вот она, гибкость Linux! В принципе можно организовать мост при различных конфигурациях и необязательно при этом должны быть реальные адреса, о чём я писал в начале статьи. Итак, для добавления интерфейсов eth0 и eth1 следует запустить команды: # brctl addif bridge0 eth0 # brctl addif bridge0 eth0
# ifconfig mybridge x.x.x.2 netmask 255.255.y.y ↵ broadcast x.x.x.z up
далее работа компьютера ничем не будет отличаться от того, как если бы этот адрес был присвоен интерфейсу eth0. Для фильтрации пакетов, проходящих через наш мост, используется цепочка FORWARD iptables. Если она у вас по умолчанию не имеет политику пропускания или явно не прописано, что разрешено, то мост у вас работать не будет. Для обработки пакетов доступны все возможности iptables. Если у вас всё заработало, и вы не хотите каждый раз вручную поднимать мост при загрузке системы, то следующий скрипт для вас. Он делает всё вышеописанное в автоматическом режиме стандартным способом во время загрузки. Итак, файл называется bridge (вы можете назвать его по-другому), его следует поместить в директорию инициализационных скриптов /etc/rc.d/init.d.
Если что-то не будет получаться, то вызывайте помощь. # brctl --help
Далее следует поднять интерфейсы eth0 и eth1 так, чтобы они ловили все пакеты у себя в сегменте. # ifconfig eth0 0.0.0.0 promisc # ifconfig eth1 0.0.0.0 promisc
Давать интерфейсам какие-либо адреса не нужно. Это будет гарантией вашей безопасности. Если у нашего моста, в частности МЭ, нет адреса, то его и просканировать невозможно! Вот где прелесть этого метода. Я не говорю уже об атаках. Даже чтобы устроить syn-flood или какуюнибудь другую атаку на отказ в обслуживании, то надо будет очень постараться, и в конечном итоге при достаточной производительности мост будет жив и будет считать и фильтровать пролетающий через него трафик. Для конфигурирования можно использовать ещё одну доверенную сетевую карточку или делать это с консоли. В любом случае за такую высокую надёжность и безопасность можно заплатить ценой неудобного конфигурирования. Настраивать же правила для такого МЭ – одно удовольствие. При желании на МЭ можно установить систему обнаружения атак, скажем, тот же snort (www.snort.org), который сможет динамически отслеживать проходящий трафик и запускать нужный скрипт, способный переконфигурировать фильтр, добавляя или убирая правила в цепочках/таблицах iptables (ipchains). То есть можно динамически менять фильтрующую способность такой системы. Однако возможны и минусы: система может заблокировать или выкинуть нужные данные в случае ложного срабатывания. Далее я расскажу, как в ущерб безопасности можно получить удобства. Всё-таки я
№4(5), апрель 2003
#! /bin/bash # # chkconfig: 2345 11 89 # ìîé ñêðèïò ìîñòà return=$rc_done case "$1" in start) echo "Starting service bridge bridge0" brctl addbr bridge0 || return=$rc_failed brctl addif bridge0 eth0 || return=$rc_failed brctl addif bridge0 eth1 || return=$rc_failed ifconfig eth0 0.0.0.0 promisc || return=$rc_failed ifconfig eth1 0.0.0.0 promisc || return=$rc_failed brctl sethello bridge0 1 || return=$rc_failed brctl setmaxage bridge0 4 || return=$rc_failed brctl setfd bridge0 4 || return=$rc_failed ifconfig bridge0 promisc up || return=$rc_failed # ifconfig bridge0 x.x.x.x netmask 255.255.x.x ↵ broadcast x.x.x.x up || return=$rc_failed # route add default gw z.z.z.z || ↵ return=$rc_failed arp -f || return=$rc_failed echo -e "$return" ;; stop) echo "Shutting down service bridge bridge0" # route del default gw z.z.z.z || return=$rc_failed brctl delif bridge0 eth0 || return=$rc_failed brctl delif bridge0 eth1 || return=$rc_failed ifconfig bridge0 down brctl delbr bridge0 || return=$rc_failed echo -e "$return" ;; status) ifconfig bridge0 brctl show bridge0 ;; restart) $0 stop || return=$rc_failed $0 start || return=$rc_failed ;; *) echo "Usage: $0 {start|stop|status|restart}" exit 1 esac test "$return" = "$rc_done" || exit 1 exit 0
47
администрирование Если вы хотите мосту присвоить IP-адрес, то закомментируйте строчку:
вило, берущее все пакеты, уходящие в Интернет на 80-е порты с интерфейса и заворачивающее их на локальный прокси:
#ifconfig bridge0 promisc up || return=$rc_failed
а у строчек #ifconfig bridge0 x.x.x.x netmask 255.255.x.x ↵ broadcast x.x.x.x up || return=$rc_failed #route add default gw z.z.z.z || return=$rc_failed #route del default gw z.z.z.z || return=$rc_failed
снимите комментарии и запишите правильные ваши IPадрес, маску, широковещание и шлюз. Далее инициализационный файл надо включить в сценарий загрузки на нужных нам уровнях. К сожалению, командой # chkconfig bridge on
наш мост не включится, так как для такого добавления нет необходимых строчек, наличие которых усложнило бы понимание, увеличило бы размеры и очень мало прибавило бы удобства. Поэтому для автозапуска нам следует самостоятельно создать файлы для необходимых уровней. Я у себя таковыми посчитал 2-й, 3-й, 4-й и 5-й. Мне кажется, что разумнее запускать мост после сервиса network, поэтому номер для запуска я выбрал 11 (10 для network плюс один). С выключением моста ситуация обратная, я выбрал номер 89. Чем меньше номер, тем раньше произойдёт событие. Затем следует создать ссылки K89bridge во всех директориях rс?.d и S11bridge в rc2.d, rc3.d, rc4.d, rc5.d. Делается это, находясь в нужной директории командами: # ln -s ../init.d/bridge K89bridge # ln -s ../init.d/bridge S11bridge
В случае запуска мост должен подниматься в процессе загрузки (то есть опускаться, если говорить по аналогии с разводными мостами). И должен останавливаться в процессе останова/выключения системы. В принципе можно запускать мост до network и создать для него конфигурационные файлы в /etc/sysconfig/networking-scripts, но мне этот путь понравился меньше. Некоторые особенности настройки iptables и ещё одну маленькую хитрость я хотел бы написать сейчас, а именно о Frame Diverter, который может быть очень полезным средством при создании многофункциональных мостов, фактически являющихся прозрачными прокси-серверами с вытекающими удобствами. У читателя может возникнуть мысль: если можно создать прозрачный МЭ, который даже по traceroute (tracert для Windows) не виден, то почему бы не сделать прозрачными и другие функции? Скажем, вы собрались почистить вентиляторы от пыли, и можете смело выключать свой сервер в рабочий день, заменив его патчкордом. Удобно, не так ли? Или если у вас 1000 и более машин, вам не надо идти и менять на всех конфигурацию. Удобства всем понятны, так что перейдём лучше к описанию их реализации. Если вы на МЭ поднимете прокси-сервер, например, sqiud, то логично предположить, что можно сделать пра-
48
iptables -t nat -A PREROUTING -i eth1 -p tcp -d 0/0 ↵ --dport 80 -j REDIRECT --to-ports 3128 (ipchains -A input -i eth1 -p tcp -d 0/0 80 -j REDIRECT 3128 )
Но не тут-то было – эффекта нужного не будет, так как пакеты изначально не адресованы нашему МЭ. Если бы заменить MAC-адрес в пакетах, идущих на 80 порт с MAC-адреса шлюза на MAC-адрес интерфейса Linux eth1, то тогда бы такой проблемы не было. Но счастье открытого кода в том и заключается, что если кому-то одному нужно было что-то сделать, то он это написал и выложил на всеобщее пользование – так что добро пожаловать на http://diverter.sourceforge.net. К сожалению, на сегодня развитие данного проекта прекращено, последние версии упоминаемых ядер на сайте – 2.2.19 и 2.4.10. Возможно, это связано с тем, что принципиально нового ничего не появилось, ошибок не найдено, поэтому данную программу divert-utils-0.221.tar.gz можно использовать и для новых ядер. Завёртывание нужного нам трафика осуществляется парой команд: # divert on eth1 proto tcp add dst 80 # divert on eth1 enable
после чего вышеуказанные правила iptables (ipchains) работают. Для реализации такого простого решения необходимо: скомпилировать ядро с поддержкой моста (мы это уже сделали с успехом), однако если у вас старые ядра, то, возможно, вам понадобится скачать патч для вашей версии. А также необходимо скомпилировать саму программу divert-командой: # make
Любому заинтересовавшемуся в программе, не должно это всё показаться сложным. Замечание1: я не использую у себя frame diverter, так как нет необходимости (следовательно, не могу гарантировать вам его работу на 100%), что же касается моста, то всё работает великолепно, если что-то не так – пишите, попробуем разобраться. Замечание 2: если в настройках iptables не привязываться к физическим интерфейсам, то должно быть абсолютно всё равно, где у моста вход, а где выход. Иногда это удобно – не думать, как подключить. Безопасность от этого, на мой взгляд, не ухудшается. Как заставить мост разводиться, то есть пропускать нужные нам пакеты, а ненужные выбрасывать в глубоко вырытый ров? Для этого следует настроить правила фильтрации пакетов в iptables (или ipchains для старых версий). Очень полезным будет прочтение книги «Брандмауэры в Linux» [1]. К сожалению, в ней не говорится ничего об iptables, так что всё написанное вам придётся адаптировать самим. Теория изложена автором очень грамотно. Если вы изучите эту книгу и поймёте отличия ipchains от iptables (документы об их различии легко найти в сети), то вы без труда будете писать правила как для первого,
администрирование так и для второго. Набрав в поисковой системе «Packet Filtering HOWTO: применение iptables», можно найти много ссылок, содержащих русский HOWTO: http://www.3ka.mipt.ru/vlib/books/OS/Linux/howto-rus/ packet-filtering-HOWTO-7.html http://www.fedchik.org.ua/linux/netfilter/iptables/packetfiltering-HOWTO-7.html http://www.yes.net.ua/asmodeus/library/os/linux/HOWTO/ packet-filtering-HOWTO-7.html К сожалению, я не знаю, где лежит оригинальный документ, не в обиде на меня будут его авторы, да и какая разница, откуда его скачивать. Тем, кто пока сомневается в написании своих правил самостоятельно, посоветую разобраться с правилами и как они «включаются» в приведенном далее примере. Будем считать, что у нашего шлюза адрес x.x.x.1, адрес Linux будет x.x.x.2, а всё остальное – наши машины в сети. Перед запуском файла не забудьте поправить конфигурацию под вашу. Дня начала создадим скрипт, в котором напишем следующее: #!/bin/bash echo "Starting firewalling, setting rules..." # ÷òîáû íàø ïðîöåññ íå çàïóñêàëñÿ ìîë÷à, âûâåäåì èíôîðìàöèþ # Óêàæåì ïåðåìåííûå, êîòîðûå íàì ïðèãîäÿòñÿ. SERVER_IP="x.x.x.2" PRIVPORTS="0:1023" UNPRIVPORTS="1024:65535" TRACEROUTE_SRC_PORTS="32769:65535" TRACEROUTE_DST_PORTS="33434:33523" CLASS_A="10.0.0.0/8" CLASS_B="172.16.0.0/12" CLASS_C="192.168.0.0/16" OUR_NET="x.x.x.??/??" OUR_BROADCAST="x.x.x.???" # Çäåñü óêàçûâàåì IP è MAC êîìïüþòåðîâ â íàøåé ñåòè COMPUTER1_IP="x.x.x.3" COMPUTER1_MAC="XX:XX:XX:XX:XX:XX" COMPUTER2_IP="x.x.x.4" COMPUTER2_MAC="XX:XX:XX:XX:XX:XX" COMPUTER3_IP="x.x.x.5" COMPUTER3_MAC="XX:XX:XX:XX:XX:XX" COMPUTER4_IP="x.x.x.6" COMPUTER4_MAC="XX:XX:XX:XX:XX:XX" ... # Ñáðàñûâàåì âñå ïðàâèëà. iptables -F # Óñòàíàâëèâàåì íà âñåõ öåïî÷êàõ ïîëèòèêó # ïî óìîë÷àíèþ – âñ¸ çàïðåùåíî. iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP # Ïðè íåîáõîäèìîñòè ñëåäóåò ïîâòîðèòü âñ¸ òî æå ñàìîå äëÿ # äîïîëíèòåëüíûõ òàáëèö, åñëè îíè èñïîëüçóþòñÿ, íàïðèìåð, # iptables -t mangle -F # Ïðàâèëà äëÿ loopback, ðàçðåøèòü ïðîõîæäåíèå ïàêåòîâ # ïî èíòåðôåéñó îáðàòíîé ïåòëè iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # Âûêèäûâàòü âñå ïàêåòû, êîòîðûå èìåþò àäðåñ èíòåðôåéñà # îáðàòíîé ïåòëè è ïîïàäàþò ê íàì èç äðóãèõ èíòåðôåéñîâ, # îòëè÷àþùèõñÿ îò lo. Ïðè ðàáîòå ýòî ïðàâèëî íå èñïîëüçó# åòñÿ, ñêîðåå îíî ñëóæèò çàùèòîé «îò äóðàêà» èëè «óìíîãî # âçëîìùèêà». iptables -A INPUT -d 127.0.0.1/8 -i ! lo -j DROP # ñ÷èòàåì âåñü ïðèõîäÿùèé òðàôèê íà àäðåñ ñåðâåðà $SERVER_IP iptables -A INPUT -p tcp -i bridge0 -d $SERVER_IP # Çàïðåùàåì «ïëîõèì» ïàêåòàì ïðîõîæäåíèå ÷åðåç ìîñò, ÷òîáû îíè # íå ïîïàäàëè íà êîìïüþòåðû çà ìîñòîì. Äåëàåì çàïèñü â ëîãàõ. # Ïðè íîðìàëüíîé ðàáîòå ñåòè òàêèõ ïàêåòîâ áûòü íå äîëæíî. iptables -A FORWARD -p tcp -d $OUR_NET --tcp-flags ↵ ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG ↵ --log-level notice --log-prefix "NMAP-XMAS: "
№4(5), апрель 2003
iptables -A FORWARD -p ALL FIN,URG,PSH -j iptables -A FORWARD -p SYN,FIN SYN,FIN -m --log-level notice iptables -A FORWARD -p SYN,FIN SYN,FIN -j iptables -A FORWARD -p SYN,RST SYN,RST -m --log-level notice iptables -A FORWARD -p SYN,RST SYN,RST -j
tcp -d $OUR_NET --tcp-flags ↵ DROP tcp -d $OUR_NET --tcp-flags ↵ limit --limit 5/minute -j LOG ↵ --log-prefix "SYN/FIN: " tcp -d $OUR_NET --tcp-flags ↵ DROP tcp -d $OUR_NET --tcp-flags ↵ limit --limit 5/minute -j LOG ↵ --log-prefix "SYN/RST: " tcp -d $OUR_NET --tcp-flags ↵ DROP
# Òî æå ñàìîå, íî çàïðåùàåì «ïëîõèì» ïàêåòàì ïîïàäàíèå # íà ñåðâåð. iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG ↵ --log-level notice --log-prefix "NMAP-XMAS: " iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ ALL FIN,URG,PSH -j DROP iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ SYN,FIN SYN,FIN -m limit --limit 5/minute -j LOG ↵ --log-level notice --log-prefix "SYN/FIN: " iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ SYN,FIN SYN,FIN -j DROP iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ SYN,RST SYN,RST -m limit --limit 5/minute -j LOG ↵ --log-level notice --log-prefix "SYN/RST: " iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ SYN,RST SYN,RST -j DROP # # # #
Ââîäèì ïðàâèëà, îãðàíè÷èâàþùèå ÷èñëî RST/ACK-ïàêåòîâ è äåëàþùèå çàïèñü â ëîã-ôàéëå, ÷òîáû ÷åðåç ïèíãîâàíèå õîñòîâ áûëè òðóäíîñòè ñ îïðåäåëåíèåì ÎÑ, óñòàíîâëåííîé íà ýòèõ õîñòàõ.
#Drop RST/ACKs to limit OS detection through pinging iptables -A FORWARD -p tcp -d $OUR_NET --tcp-flags ↵ RST RST,ACK -m limit --limit 5/minute -j LOG ↵ --log-level notice --log-prefix "SYN/RST: " iptables -A FORWARD -p tcp -d $OUR_NET --tcp-flags ↵ RST RST,ACK -j DROP iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ RST RST,ACK -m limit --limit 5/minute -j LOG ↵ --log-level notice --log-prefix "SYN/RST: " iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ RST RST,ACK -j DROP # Çàùèòà îò Syn-flood, (ïðèíöèï ðàáîòû ïîäðîáíåå # ñì. âûøå â HOWTO) iptables -A FORWARD -p tcp -d $OUR_NET --syn -m limit ↵ --limit 1/s -j ACCEPT iptables -A INPUT -p tcp -d $SERVER_IP --syn -m limit ↵ --limit 1/s -j ACCEPT # Çàùèòà îò ñêðûòîãî ñêàíèðîâàíèÿ ïîðòîâ # (Furtive port scanner) iptables -A FORWARD -p tcp -d $OUR_NET --tcp-flags ↵ SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT iptables -A INPUT -p tcp -d $SERVER_IP --tcp-flags ↵ SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT # Ping of Death iptables -A FORWARD -p icmp -d $OUR_NET --icmp-type ↵ echo-request -m limit --limit 1/s -j ACCEPT iptables -A INPUT -p icmp -d $SERVER_IP --icmp-type ↵ echo-request -m limit --limit 1/s -j ACCEPT # Ðàçðåøàåì ïðîõîæäåíèå ïàêåòîâ îò è ê íàøåìó http (https) # ñåðâåðó. Îáðàùåíèå ê âåá-ñåðâåðó èç âíóòðåííåé ñåòè # ñ÷èòàòü áóäåì îòäåëüíî iptables -A INPUT -p tcp -i bridge0 -s $OUR_NET ↵ --sport $UNPRIVPORTS -d $SERVER_IP --dport 80 -j ACCEPT iptables -A OUTPUT -p tcp -o bridge0 -d $OUR_NET ↵ --dport $UNPRIVPORTS -s $SERVER_IP --sport 80 -j ACCEPT # îñòàëüíûå îáðàùåíèÿ iptables -A INPUT -p tcp -i bridge0 --sport $UNPRIVPORTS ↵ -d $SERVER_IP --dport 80 -j ACCEPT iptables -A OUTPUT -p tcp -o bridge0 --dport $UNPRIVPORTS ↵ -s $SERVER_IP --sport 80 -j ACCEPT iptables -A INPUT -p tcp -i bridge0 --sport $UNPRIVPORTS ↵ -d $SERVER_IP --dport 443 -j ACCEPT iptables -A OUTPUT -p tcp -o bridge0 --dport $UNPRIVPORTS ↵ -s $SERVER_IP --sport 443 -j ACCEPT # Çàäà¸ì àäðåñà, ñ êîòîðûõ ìîæíî àäìèíèñòðèðîâàòü íàø ñåðâåð # ÷åðåç ssh, ïóñòü ýòî áóäóò COMPUTER1 è COMPUTER2 iptables -A INPUT -p tcp -i bridge0 -s $COMPUTER1_IP ↵
49
администрирование --sport $UNPRIVPORTS -d $SERVER_IP --dport 22 -m mac ↵ --mac-source $COMPUTER1_MAC -j ACCEPT iptables -A OUTPUT -p tcp -o bridge0 -s $SERVER_IP ↵ --sport 22 -d $COMPUTER1_IP --dport $UNPRIVPORTS -j ACCEPT iptables -A INPUT -p tcp -i bridge0 -s $COMPUTER2_IP ↵ --sport $UNPRIVPORTS -d $SERVER_IP --dport 22 -m mac ↵ --mac-source $COMPUTER2_MAC -j ACCEPT iptables -A OUTPUT -p tcp -o bridge0 -s $SERVER_IP ↵ --sport 22 -d $COMPUTER2_IP --dport $UNPRIVPORTS -j ACCEPT
iptables -A OUTPUT -p udp -s $SERVER_IP ↵ --sport $UNPRIVPORTS -d $OUR_NET --dport 138 -j ACCEPT iptables -A INPUT -p udp -s $OUR_NET --sport 138 ↵ -d $SERVER_IP --dport $UNPRIVPORTS -j ACCEPT
# Âûáðàñûâàåì âñå íåëåãèòèìíûå ïàêåòû (RFC 1918). Ïðè ïðàâèëü# íîé íàñòðîéêå èõ íå äîëæíî áûòü â ñåòè ñ ðåàëüíûìè àäðåñàìè. iptables -A FORWARD -s $CLASS_A -j DROP iptables -A FORWARD -s $CLASS_B -j DROP iptables -A FORWARD -s $CLASS_C -j DROP # Áëîêèðóåì ïàêåòû, êîòîðûå ìû ñ÷èòàåì íåíóæíûìè. Äîïèøèòå # ïðàâèëà ñàìè. Íèæå áëîêèðóåòñÿ «ñåòåâîå îêðóæåíèå # (smb-ïðîòîêîë)» è èæå ñ íèì. ×òîáû èç âíåøíåé ñåòè # íèêòî íå íàø¸ë çàáûòûå share-ðåñóðñû â ëîêàëüíîé ñåòè, # åñëè êòî-òî ÷òî-òî çàáûë çàêðûòü. # À èç ñåòè â Èíòåðíåò âðÿä ëè êòî-òî ïîëåçåò. iptables -A FORWARD -s ! $OUR_NET -d $OUR_NET -p tcp ↵ --dport 137:139 -j DROP iptables -A FORWARD -s ! $OUR_NET -d $OUR_NET -p udp ↵ --dport 137:139 -j DROP iptables -A FORWARD -s $OUR_NET -d ! $OUR_NET -p tcp ↵ --dport 137:139 -j DROP iptables -A FORWARD -s $OUR_NET -d ! $OUR_NET -p udp ↵ --dport 137:139 -j DROP # Ó ìåíÿ âîçíèêëî æåëàíèå ïðèêðûòü ÷àñòî ïðèõîäÿùèå ïðî# âåðêè íà íàëè÷èå proxy è mssql â ïðîöåññå ðàáîòû ìîñòà. iptables -A FORWARD -d $OUR_NET -p tcp --dport 1433 -j DROP iptables -A FORWARD -d $OUR_NET -p tcp --dport 3128 -j DROP
iptables -A INPUT -p udp -s $OUR_NET --sport 138 ↵ -d $OUR_NET --dport 138 -j ACCEPT iptables -A OUTPUT -p udp -s $OUR_NET --sport 138 ↵ -d $OUR_NET --dport 138 -j ACCEPT
# Ðàçðåøèì ñåðâåðó îáùàòüñÿ ñ DNS-ñåðâåðàìè, åñëè åñòü # îïàñåíèÿ î áåçîïàñíîñòè, òî ïðàâèëà ìîæíî ïåðåïèñàòü # äëÿ êîíêðåòíûõ ïðîâåðåííûõ DNS-cåðâåðîâ. iptables -A OUTPUT -p tcp -s $SERVER_IP ↵ --sport $UNPRIVPORTS --dport 53 -j ACCEPT iptables -A INPUT -p tcp --syn -d $SERVER_IP ↵ --dport $UNPRIVPORTS --sport 53 -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP ↵ --sport $UNPRIVPORTS --dport 53 -j ACCEPT iptables -A INPUT -p udp -d $SERVER_IP ↵ --dport $UNPRIVPORTS --sport 53 -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP --sport 53 ↵ --dport 53 -j ACCEPT iptables -A INPUT -p udp -d $SERVER_IP --dport 53 ↵ --sport 53 -j ACCEPT # Ðàçðåøàåì iptables -A --sport iptables -A --dport
whois (ó ìåíÿ ýòèõ ïðàâèë íåò çà íåíàäîáíîñòüþ) OUTPUT -p tcp -s $SERVER_IP ↵ $UNPRIVPORTS --dport 43 -j ACCEPT INPUT -p tcp ! --syn -d $SERVER_IP ↵ $UNPRIVPORTS --sport 43 -j ACCEPT
# Åñëè ó íàñ ñòîèò SAMBA, òî ðàçðåøàåì SMB to/from server # âíóòðè ëîêàëüíîé ñåòè iptables -A INPUT -p tcp -s $OUR_NET --sport $UNPRIVPORTS ↵ -d $SERVER_IP --dport 139 -j ACCEPT iptables -A OUTPUT -p tcp -s $SERVER_IP --sport 139 ↵ -d $OUR_NET --dport $UNPRIVPORTS -j ACCEPT iptables -A OUTPUT -p tcp -s $SERVER_IP ↵ --sport $UNPRIVPORTS -d $OUR_NET --dport 139 -j ACCEPT iptables -A INPUT -p tcp -s $OUR_NET --sport 139 ↵ -d $SERVER_IP --dport $UNPRIVPORTS -j ACCEPT iptables -A INPUT -p udp -s $OUR_NET --sport $UNPRIVPORTS ↵ -d $SERVER_IP --dport 139 -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP --sport 139 ↵ -d $OUR_NET --dport $UNPRIVPORTS -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP ↵ --sport $UNPRIVPORTS -d $OUR_NET --dport 139 -j ACCEPT iptables -A INPUT -p udp -s $OUR_NET --sport 139 ↵ -d $SERVER_IP --dport $UNPRIVPORTS -j ACCEPT iptables -A INPUT -p udp -s $OUR_NET --sport $UNPRIVPORTS ↵ -d $SERVER_IP --dport 137 -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP --sport 137 ↵ -d $OUR_NET --dport $UNPRIVPORTS -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP ↵ --sport $UNPRIVPORTS -d $OUR_NET --dport 137 -j ACCEPT iptables -A INPUT -p udp -s $OUR_NET --sport 137 ↵ -d $SERVER_IP --dport $UNPRIVPORTS -j ACCEPT iptables -A INPUT -p udp -s $OUR_NET --sport $UNPRIVPORTS ↵ -d $SERVER_IP --dport 138 -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP --sport 138 ↵ -d $OUR_NET --dport $UNPRIVPORTS -j ACCEPT
50
iptables -A INPUT -p udp -s $OUR_NET --sport 137 ↵ -d $OUR_NET --dport 137 -j ACCEPT iptables -A OUTPUT -p udp -s $OUR_NET --sport 137 ↵ -d $OUR_NET --dport 137 -j ACCEPT
iptables -A INPUT -p udp -s $OUR_NET --sport 138 ↵ -d $OUR_BROADCAST --dport 138 -j ACCEPT iptables -A OUTPUT -p udp -s $SERVER_IP --sport 138 ↵ -d $OUR_BROADCAST --dport 138 -j ACCEPT # Çàïðåùàåì Ping of Death è ïðîïóñêàåì îáû÷íûå ping âíóòðü iptables -A INPUT -p icmp --icmp-type echo-request ↵ -m limit --limit 1/s -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT # ðåêîìåíäóþ èñïðàâèòü è çàïðåòèòü, ìíîãèå ñêàíåðû âíà÷àëå # ïèíãóþò õîñò, ïðåæäå ÷åì åãî ñêàíèðîâàòü. # Ðàçðåøàåì ïðîõîæäåíèå icmp-ïàêåòîâ. Ïðè òðåáîâàíèÿõ # ïîâûøåííîé áåçîïàñíîñòè ìîæíî ïåðåñìîòðåòü (çàïðåòèòü) # ýòè ïðàâèëà. iptables -A INPUT -p icmp --icmp-type source-quench ↵ -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type source-quench ↵ -j ACCEPT iptables -A INPUT -p icmp --icmp-type parameter-problem ↵ -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type parameter-problem ↵ -j ACCEPT iptables -A INPUT -p icmp ↵ --icmp-type destination-unreachable -j ACCEPT iptables -A OUTPUT -p icmp ↵ --icmp-type destination-unreachable -j ACCEPT iptables -A OUTPUT -p icmp ↵ --icmp-type fragmentation-needed -j ACCEPT iptables -A INPUT -p icmp --icmp-type time-exceeded ↵ -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type time-exceeded ↵ -j ACCEPT # Ðàçðåøàåì íà ñåðâåðå äåëàòü ping è ïîëó÷àòü îòâåòû iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT # Äëÿ ðàáîòû traceroute íà ñåðâåðå iptables -A OUTPUT -p udp -s $SERVER_IP ↵ --sport $TRACEROUTE_SRC_PORTS ↵ --dport $TRACEROUTE_DST_PORTS -j ACCEPT # Îòáðàñûâàåì ñ óâåäîìëåíèåì âñå ïàêåòû, ÷òî ñåðâåð ïûòàåòñÿ # ïîñëàòü íàðóæó. Ïðè ãðàìîòíîé íàñòðîéêå ïàêåòû íå äîëæíû # äîõîäèòü äî ýòîãî ïðàâèëà. iptables -A OUTPUT -s $SERVER_IP -j REJECT # Ñ÷¸ò÷èêè òðàôèêà + ðàçðåøåíèå íà ïðîïóñêàíèå òðàôèêà ÷åðåç # ìîñò: åñëè ìîæíî ðàçðåøèòü, ìîæíî è çàïðåòèòü. Èñõîäÿùèé # òðàôèê ïðèâÿçûâàåì ê MAC-àäðåñó ñåòåâûõ êàðòî÷åê iptables -A FORWARD -s $COMPUTER1_IP -m mac ↵ --mac-source $COMPUTER1_MAC -j ACCEPT iptables -A FORWARD -d $COMPUTER1_IP -j ACCEPT iptables -A FORWARD -s $COMPUTER2_IP -m mac ↵ --mac-source $COMPUTER2_MAC -j ACCEPT iptables -A FORWARD -d $COMPUTER2_IP -j ACCEPT iptables -A FORWARD -s $COMPUTER3_IP -m mac ↵ --mac-source $COMPUTER3_MAC -j ACCEPT iptables -A FORWARD -d $COMPUTER3_IP -j ACCEPT .... iptables -A FORWARD -s $COMPUTERn_IP -m mac ↵ --mac-source $COMPUTERn_MAC -j ACCEPT iptables -A FORWARD -d $COMPUTERn_IP -j ACCEPT # Ïðàâèëà òîëüêî äëÿ ïîäñ÷¸òà ñëåäóåò ïèñàòü áåç -j îïöèè # iptables -A FORWARD -s $COMPUTER001_IP -m mac ↵ --mac-source $COMPUTER001_MAC # iptables -A FORWARD -d $COMPUTER001_IP # ïîýêñïåðèìåíòèðóéòå
администрирование Далее, после запуска созданного вами файла, мост должен фильтровать пакеты так, как вы этого хотите. В случае если у вас всё настроено правильно, то при выключении правила должны автоматически сохраняться и загружаться заново при включении компьютера с сохранением всех значений счётчиков. Способ, описываемый в книге «Брандмауэры в Linux» [1] имеет этот недостаток: после перезапуска значения счётчиков не восстанавливаются. Я правил у себя файл /etc/rc.d/init.d/iptables, чтобы при выключении (опция stop) он сохранял параметры, а после останавливал интерфейс. Возможно, вам также следует сделать небольшие изменения. Для просмотра значений (простейший биллинг) используйте команду: # iptables -L -v -x -n
-L выводит все цепочки; -v – информативный вывод, у цепочек выводятся значения счётчиков;
-x означает, что значения счётчиков не округляются до Кб и Мб и выводятся точно в байтах;
-n означает, что не надо преобразовывать IP-адреса и номера портов/сервисов в их имена. Последняя опция часто не указывается, так как вроде бы является бесполезной, однако необходимость в ней появляется тогда, когда у вас пропадет Интернет, а точнее, перестанут правильно работать DNS-сервера. В случае падения DNS ответ от iptables может задерживаться до 10 минут, а если указать -n, то вывод цепочек будет быстрым, как обычно. Если iptables запускается у вас из других скриптов, то задержка его выполнения «повесит» эти скрипты и приведёт к глюкам. В частности, поначалу у меня mrtg не понимал тот факт, что ему передавались пустые значения. Для удобного просмотра статистики без захода на сервер под правами администратора можно создать небольшой cgi-скрипт. Чтобы не усложнять задачу, я напишу вывод только нескольких значений, а далее развить идею, я думаю, вы сможете сами. Создадим небольшой файл на perl и, придав ему исполняемые атрибуты, поместим в директорию для cgiскриптов (в RedHat 7.3 /var/www/cgi-bin), рекомендую книгу «CGI-программирование» [2]. Результат его исполнения можно увидеть на рисунке:
#!/usr/bin/perl $SERVER_IP="x.x.x.2"; $COMPUTER1_IP="x.x.x.3"; $COMPUTER1_MAC="XX:XX:XX:XX:XX:XX"; $COMPUTER2_IP="x.x.x.3"; $COMPUTER2_MAC="XX:XX:XX:XX:XX:XX"; ... # ñîçäàäèì ôóíêöèþ, êîòîðàÿ áóäåò ñòàâèòü òî÷êè, óäîáíåå # ñìîòðåòü íà 10.000.000.000 ÷åì íà 10000000000 sub DOTS { # ðàññòàâëåíèå òî÷åê ðàçðÿäîâ $string1 = shift; if(not($string1 =~ /\D/)){ $string1 =~s/(\d{3})$/\.$1/; while ($string1 =~ /^\d{3}/){$string1 =~s/(\d{3}\.\d)/\.$1/;} } $string1 =~s/(^\.)(.*)/$2/; return $string1; } print "Content-type:text/html; charset=koi8-r\n\n"; print "<html>\n<head>"; print "<TITLE>Traffic shower</TITLE>\n<META ↵ NAME=\"content\" CONTENT=\"text/html; ↵ charset=koi8-r\">\n"; print "</HEAD><BODY BGCOLOR=\"white\" ↵ LINK=\"red\"\nleftmargin=\"10\" marginwidth=\"10\" ↵ topmargin=\"2\" marginheight=\"2\">\n"; $date = localtime time; $ip=$ENV{"REMOTE_ADDR"}; print $date,"\n<br>"; # Äëÿ ðàáîòû ïðîãðàììû ïðèä¸òñÿ îòäåëüíî ñîçäàòü ôàéë-êîïèþ # äëÿ iptables c óñòàíîâëåííûì ôëàãîì SETUID, èíà÷å ðàáîòàòü # íå áóäåò, ôàéë-êîïèþ ìîæíî ïîìåñòèòü êóäà óãîäíî, ñêàæåì, # â /dir1. C òî÷êè çðåíèÿ áåçîïàñíîñòè òóò âîçìîæíû ñëàáûå # ìåñòà. system "/dir1/iptables -L -v -x -n >/temp/traffic-dump"; # Âûâîä ñáðàñûâàåòñÿ â îòäåëüíûé ôàéë, ÷òîáû ìîæíî áûëî ýòîò # ôàéë ïî íåñêîëüêó ðàç ïðîñìàòðèâàòü. Åñëè çàïóñêàòü # iptables íåñêîëüêî ðàç, òî ïðè êàæäîì íîâîì çàïóñêå # áóäåò íîâàÿ ñèòóàöèÿ (íà ìîìåíò çàïóñêà). # îòêðûâàåì ôàéë è "âûðåçàåì" èç íåãî íóæíûå íàì çíà÷åíèÿ, # ïîìåùàÿ èõ â íóæíûå íàì ïåðåìåííûå. open(TRAFFIC,"/temp/traffic-dump") or die ("Cannot open ↵ file trafic-dump"); for ($index=1; !eof(TRAFFIC); $index++) { $str=<TRAFFIC>; chomp($str); ###### Web server 80 port ######### if ($str=~/tcp -- bridge0 \* 0.0.0.0\/0 $SERVER_IP ↵ tcp spts:1024:65535 dpt:80/) { if ($str=~/\s*(\d+)\s+(\d+)\s(.*)/) {$webserver_in=$2;} } if ($str=~/tcp -- \* bridge0 $SERVER_IP 0.0.0.0\/0 tcp ↵ spt:80 dpts:1024:65535/) { if ($str=~/\s*(\d+)\s+(\d+)\s(.*)/) {$webserver_out=$2;} } # Âî âðåìÿ îòëàäêè îáðàòèòå âíèìàíèå íà ÷èñëî ïðîáåëîâ è # ñèìâîëû, çàïèñûâàåìûå ÷åðåç "\": ïðè íå ñîâïàäåíèè ñòðî÷êè # ñ ýòàëîíîì áóäåò âûâåäåíî ïóñòîå çíà÷åíèå. # Çíà÷åíèÿ äëÿ ñðàáàòûâàíèÿ ðåãóëÿðíûõ âûðàæåíèé ñëåäóåò # áðàòü èç ôàéëà /temp/traffic-dump, èíà÷å, åñëè ÷òî-òî íå # òàê ñ ïðîáåëàìè è ïð, òî ó âàñ ìîãóò ïîëó÷èòüñÿ ïóñòûå # çíà÷åíèÿ â ïåðåìåííûõ $webserver_in, $webserver_out # $str=~/\s*(\d+)\s+(\d+)\s(.*)/ äîëæíî ïåðåäàâàòü çíà÷åíèå # âòîðîãî ñòîëáöà â ïåðåìåííóþ $2 (ïîäðîáíåå ñì. êíèãó # À.Ïàâëîâà [2] èëè ëþáîé ñïðàâî÷íèê ïî Perl, ðàçäåë # «Ðåãóëÿðíûå âûðàæåíèÿ») ###### Computer1 ######### if ($str=~/all -- \* \* $COMPUTER1_IP 0.0.0.0\/0 ↵ MAC $COMPUTER1_MAC/) { if ($str=~/\s*(\d+)\s+(\d+)\s(.*)/) {$COMPUTER1_out=$2;} } if ($str=~/all -- \* \* 0.0.0.0\/0 $COMPUTER1_IP/) { if ($str=~/\s*(\d+)\s+(\d+)\s(.*)/) {$COMPUTER1_in=$2;} } ###### Computer2 ######### if ($str=~/all -- \* \* $COMPUTER2_IP 0.0.0.0\/0 ↵ MAC $COMPUTER2_MAC/) { if ($str=~/\s*(\d+)\s+(\d+)\s(.*)/) {$COMPUTER2_out=$2;} } if ($str=~/all -- \* \* 0.0.0.0\/0 $COMPUTER2_IP/) { if ($str=~/\s*(\d+)\s+(\d+)\s(.*)/) {$COMPUTER2_in=$2;} } # ... è òàê äàëåå äëÿ äðóãèõ êîìïüþòåðîâ...
№4(5), апрель 2003
51
администрирование } # for ($index=1; !eof(TRAFFIC); $index++) close(TRAFFIC); # Äàëåå, èç ïîëó÷åííûõ çíà÷åíèé ìû ñîçäà¸ì ñîáñòâåííî # html-îò÷¸ò. Äëÿ ýòîãî ïðîâåðÿåì IP-àäðåñ, ñ êîòîðîãî çà# ïðîøåí ñêðèïò, è âûâîäèì çíà÷åíèÿ. Åñëè ýòî IP àäìèíèñò# ðàòîðà ($COMPUTER1_IP), òî âûâîäèì áîëåå ñëîæíûé îò÷¸ò, # ñî âñåìè ïîëüçîâàòåëÿìè. Åñëè ýòî äðóãîé IP, òî âûâîäèì # äëÿ íåãî ñâîé îò÷¸ò – îáû÷íî ýòî ñòàòèñòèêà òîëüêî íà # ýòîò àäðåñ è âñ¸. if ($ip eq $COMPUTER1_IP) {
до обнуления. Если же разбираться с БД вам не хочется, а хочется иметь что-то красивое, чтобы видеть визуально, как расходуется трафик, то за 10 минут можно установить mrtg. Для тех, кто не знает – это небольшая программа, считающая трафик и рисующая красивые графики. Это не единственно возможная программа своего класса.
print "\n\n<table cellpadding=\"3\" border=\"1\">\n"; print "<tr align=\"center\"><td>&nbsp;</td> ↵ <td>output</td> <td>input</td></tr>\n"; print "<tr><td>Computer1</td> ↵ <td>",DOTS($COMPUTER1_out),"</td>"; print "<td>",DOTS($COMPUTER1_in),"</td>"; print "</tr>\n"; print "<tr><td>Webserver 80 port</td> ↵ <td>",DOTS($webserver_out),"</td>"; print "<td>",DOTS($webserver_in),"</td>"; print "</tr>\n"; print "<tr><td>Computer2</td> ↵ <td>",DOTS($COMPUTER2_out),"</td>"; print "<td>",DOTS($COMPUTER2_in),"</td>"; print "</tr>\n"; #(è òàê äàëåå äëÿ äðóãèõ êîìïüþòåðîâ). $total_out=$webserver_out+$COMPUTER1_out+$COMPUTER2_out; $total_in=$webserver_in+$COMPUTER1_in+$COMPUTER2_in; print print print print
"<tr><td>Total</td>"; "<td>",DOTS($total_out),"</td>"; "<td>",DOTS($total_in),"</td></tr>\n"; "</table>\n\n";
} elsif ($ip eq $COMPUTER2_IP) { print "\n\n<table cellpadding=\"3\" border=\"1\">\n"; print "<tr align=\"center\"><td>&nbsp;</td> ↵ <td>output</td> <td>input</td></tr>\n"; print "<tr><td>Computer2</td> ↵ <td>",DOTS($COMPUTER2_out),"</td>"; print "<td>",DOTS($COMPUTER2_in),"</td>"; print "</tr>\n"; print "</table>\n\n"; } #elsif ($ip eq ...) { # ... #} } else { print "Unknown IP!";} print " </body>"; print "</html>";
Для начала такая статистика очень даже подойдёт. Реально же рекомендуется поднимать БД, в которую периодически заносить показания счётчиков, а сами счётчики обнулять (iptables -Z) во избежание их переполнения и последующей выдачи неправильных значений. Хотя в RedHat 7.x/8.x проблема переполнения менее актуальна, чем в более ранних версиях. Для повышения точности можно одновременно просматривать и обнулять. # iptables -L -v -x -n -Z
При таком способе снятия показаний точно ничего не проскочит неучтённым после момента снятия значений, но
52
Для тех, кто любит изучать первоисточники, сообщу следующие ссылки: http://www.bog.pp.ru/work/mrtg.html http://www.bog.pp.ru/work/rrdtool.html Для остальных скажу, что в поставке Red Hat 7.3 mrtg идёт в комплекте и чаще уже установлен. Единственным узким местом по его настройке становится его конфигурационный файл, про который я кратко расскажу. Если мы посмотрим в файл /etc/crontab, то увидим строчку вида: 0-59/5 * * * * root /usr/bin/mrtg /etc/mrtg/mrtg.cfg ↵ --logging /var/log/mrtg.log
или похожую. Если таковой нет, напишем сами. (Так как mrtg есть в стандартном дистрибутиве, считаю его уже установленным у вас.) Как видим, конфигурационный файл для mrtg называется mrtg.cfg и находится в /etc/mrtg. Идём туда, делаем резервную копию и правим его до следующего вида: # Multi Router Traffic Grapher -- Example Configuration File # Minimal mrtg.cfg #-------------------WorkDir: /var/www/html/mrtg Language:ru Target[computer1]:`/sbin/stat/comp1` MaxBytes[computer1]: 125000000000 Title[computer1]: Traffic Analysis for Computer1 PageTop[computer1]: <H1>Stats for Computer1</H1> Directory[computer1]: comp1 XSize[computer1]: 600 YSize[computer1]: 160 Options[computer1]: growright
администрирование Target[computer2]:`/sbin/stat/comp2` MaxBytes[computer2]: 125000000000 Title[computer2]: Traffic Analysis for Computer2 PageTop[computer2]: <H1>Stats for Computer2</H1> Directory[computer2]: comp2 XSize[computer2]: 600 YSize[computer2]: 160 Options[computer2]: growright Target[web]:`/sbin/stat/web` MaxBytes[web]: 125000000000 Title[web]: Traffic Analysis for Web server 80 PageTop[web]: <H1>Stats for Web server 80</H1> Directory[web]: webdir XSize[web]: 600 YSize[web]: 160 Options[web]: growright
Эту конфигурацию следует понимать так: рабочей директорией для mrtg будет /var/www/html/mrtg. В ней будут создаваться поддиректории по именам аккаунтов: /var/www/html/mrtg/comp1 /var/www/html/mrtg/comp2 /var/www/html/mrtg/webdir При желании можно писать всё в одну директорию, хотя это не очень удобно. Файлы для просмотра будут соответственно: /var/www/html/mrtg/comp1/computer1.html /var/www/html/mrtg/comp2/computer2.html /var/www/html/mrtg/webdir/web.html Теперь осталось настроить сенсоры или датчики, которые будут сообщать mrtg сами значения счётчиков. Это в нашем примере файлы: /sbin/stat/comp1 /sbin/stat/comp2 /sbin/stat/web У вас это могут быть любые файлы и лежать они могут где угодно. Сначала разумнее создать и проверить работу этих файлов, а после править mrtg.cfg. Рассмотрим на примере файла /sbin/stat/web: #!/bin/bash # web/80 (íå çàáóäüòå èñïðàâèòü íà ñâîé IP) ip=x.x.x.2 # Òàê êàê ñòàòèñòèêà ñíèìàåòñÿ ðàç â 5 ìèíóò, è ó íàñ ìîæåò # áûòü ìíîãî ñ÷¸ò÷èêîâ, òî íåðàçóìíî çàïóñêàòü êàæäûé ðàç # iptables. Ïîýòîìó ìû âûâîä iptables ñêèäûâàåì â ôàéë è # äàëåå ðàáîòàåì ñ ôàéëîì, ÷èòàÿ åãî ñêîëü óãîäíî ðàç. # ñìîòðèì, êîãäà ñîçäàí ôàéë: åñëè äàâíî (>5 ìèíóò), òî # äåëàåì åãî çàíîâî (îáðàòèòå âíèìàíèå: ' è ` ðàçëè÷íû): if [ -f /temp/traffic-dump ] then currenttime=`date +%s` locktime=`date -r /temp/traffic-dump +%s` secondsdiff=`expr $currenttime - $locktime` if [ $secondsdiff -gt 300 ] # åñëè ôàéë óñòàðåâøèé, òî åñòü ñîçäàííûé áîëåå 5 ìèíóò # íàçàä – ãåíåðèðóåì íîâûé: then /sbin/www/iptables -L -v -x -n >/temp/traffic-dump fi else /sbin/www/iptables -L -v -x -n >/temp/traffic-dump fi # äëÿ ñîâïàäåíèÿ âàæíî ÷èñëî ïðîáåëîâ out=`cat /temp/traffic-dump |grep ↵ "ACCEPT tcp -- \* bridge0 $ip 0.0.0.0/0 ↵ tcp spt:80 dpts:1024:65535"` out=`echo $out|cut -d" " -f2` in=`cat /temp/traffic-dump |grep ↵ "ACCEPT tcp -- bridge0 \* 0.0.0.0/0 $ip ↵
№4(5), апрель 2003
tcp spts:1024:65535 dpt:80"` in=`echo $in|cut -d" " -f2` echo echo echo echo
$in $out 0 web
Если есть проблемы с написанием скриптов для bash, то рекомендую неплохую книгу «Linux и UNIX: программирование в shell» [3]. В целях безопасности, возможно, следует использовать директорию, отличную от /temp (/tmp), для хранения временного файла. Отладка датчиков заключается в том, чтобы при их запуске они выводили на экран 4 строчки, где нам важны первые две – они должны показывать реально вырезанные значения из файла /temp/traffic-dump с показаниями счётчиков на цепочках. Остальные две носят скорее информативный характер – uptime и название того, с чего эти показания снимаются. Видимо, это важно для тех случаев, когда сеть очень большая. Программа mrtg готова к запуску, точнее она сама запустится по crontab и начнёт работать тогда, когда вы создадите рабочий конфигурационный файл. Поэтому разумнее вначале отладить сенсоры, а после править конфигурационный файл. Возможно, вам придётся создать и рабочие поддиректории, но я этого не делал. При первом и втором запуске mrtg в новой конфигурации он будет ругаться на то, что у него нет файлов или файла со значениями. Поэтому лучше его запустить два раза вручную и после ещё один раз, убедившись, что всё ему понравилось. # mrtg /etc/mrtg/mrtg.cfg
Это будет быстрее, чем ждать 10-15 минут и после идти в /var/log/messages, если что-то было не так. Далее можете просматривать html-файлы с полученными красивыми картинками через поднятый на вашем сервере apache. Единственное дополнение состоит в том, что не всегда нужно, чтобы директории с отчётом были доступны всем, поэтому пару слов о том, как к этим директориям ограничить доступ. Для этого находим файл конфигурации apache. У меня это /etc/httpd/conf/httpd.conf и дописываем в нём: <Directory /var/www/html/mrtg/comp1> Order deny,allow Deny from all Allow from x.x.x.3 </Directory> <Directory /var/www/html/mrtg/comp2> Order deny,allow Deny from all Allow from x.x.x.3 x.x.x.4 </Directory> <Directory /var/www/html/mrtg/webdir> Order deny,allow Deny from all Allow from x.x.x.3 </Directory>
Это позволит компьютеру с IP x.x.x.3 просматривать все три статистики, а компьютеру x.x.x.4 только свою. Разумной может быть небольшая правка вышеописанного в статье CGI-скрипта, чтобы он генерировал в отчё-
53
администрирование те для просмотра сразу html-ссылки на страницы просмотра mrtg статистики. Тогда можно будет просто щелчком мыши смотреть графики. Если вас не устраивает привязка к IP-адресу, то вместо привязки можно сделать доступ по паролю средствами apache, для этого: создаём директорию, где будут храниться пароли, если такой у нас ещё нет # mkdir /usr/lib/apache/passwords
и заносим туда пользователей с паролями. Если файла /usr/lib/apache/passwords/passwords нет, то пишем: # htpasswd -ñ /usr/lib/apache/passwords/passwords userlogin1
далее, уже без опции create (-c): # htpasswd /usr/lib/apache/passwords/passwords userlogin2
Когда нас будут спрашивать про пароль при вводе строк, то придумываем и вводим пароль. Поставьте нужные права, ограничивающие чтение директории /usr/lib/ apache/passwords другими пользователями в целях безопасности. Если apache ругается на невозможность доступа к файлу, то вы перестарались. Далее правим /etc/httpd/conf/httpd.conf и дописываем/правим в нём: <Directory /var/www/html/mrtg/comp1> AuthType Basic AuthName "yourcompany" AuthUserFile /usr/lib/apache/passwords/passwords Require user userlogin1 AllowOverride None </Directory> <Directory /var/www/html/mrtg/comp1> AuthType Basic AuthName "yourcompany" AuthUserFile /usr/lib/apache/passwords/passwords Require user userlogin2 AllowOverride None </Directory> <Directory /var/www/html/mrtg/webdir> Order deny,allow Deny from all Allow from x.x.x.3 </Directory>
54
Заходить следует как обычно, при запросе имени вводим userlogin1 или userlogin2, пароль и наслаждаемся графиками. Если же вы хотите придумать что-то более изощрённое или совместить парольную аутентификацию с идентификацией по IP, то можно и так сделать, но я этого делать не буду, а порекомендую хорошую книгу, в которой вы прочитаете много нового о сервере Apache: «Apache для профессионалов» [4]. Небольшое замечание: через мост проходят не IP-протоколы, вне зависимости от правил iptables, такие как Cisco Discovery Protocol (CDP) и Spanning Tree Protocol (STP), возможно, и другие. Думаю, что iptables умеет и их фильтровать, надо просто хитро записать ему правила, но так как особой надобности в этом не было, то я до этого «не дошёл» пока. Если кто-то знает – напишите, буду рад. Выключение же на мосту поддержки STP не влияет на прохождение пакетов STP через него. Mrtg, Apache, perl и всё вышеописанное у меня великолепно уживается с мостом, МЭ и дополняет их, также у меня на сервере вместе с ними живёт система обнаружения атак snort и система бесперебойного питания, но о них, я думаю, что если получится что-то интересное, то я расскажу в следующих статьях. Что же касается параметров, то в эксперименте участвовал и по сей день работает мост на Red Hat Linux v.7.3 (Valhalla). Железо: AMD K7 (Duron) 750/256/80/с двумя 100-мегабитными сетевыми карточками Compex RE100TX/WOL на базе чипсета Realtek RTL-8139. (Остальные несущественные параметры, как двух- или трёхкнопочная мышь или её отсутствие – не заслуживают внимания и упоминания). Литература: 1. Роберт Л. Зиглер. Брандмауэры в Linux. Перевод с англ.: Уч. пос. – М.: Издательский дом «Вильямс», 2000. 2. Павлов А. CGI-программирование: Учебный курс. – СПб.: Питер, 2000. 3. Девид Тейнсли. Linux и UNIX: программирование в shell. Руководство разработчика: Перев. с англ. – К.: Издательская группа BHV, 2001. 4. Питер Уэнрайт. Apache для профессионалов. М.: Издательство «Лори», 2001.
BUGTRAQ Уязвимость в Sendmail
Freebsd 4.4 – (default & self compiled Sendmail 8.11.6)
Обзор уязвимости
Solaris 8.0 x86 – (default & self compiled Sendmail 8.11.6)
does not crash;
Sendmail – один из самых популярных почтовых агентов (Mail Transfer Agent, MTA). Примерно 50%-75% серверов в Интернете используют его для обмена почтой. Это неудивительно, поскольку в ОС Unix и Linux он установлен по умолчанию. В марте 2003 года мировая общественность была уведомлена о новой уязвимости, найденной в Sendmail (5.798.12.7). Ее автором является Марк Давд (Mark Dowd) из ISS (Internet Security Systems) X-Force. Найденная уязвимость ориентирована на функцию обработки заголовка сообщения. При получении письма производится семантическая проверка адреса реципиента, в том числе и «From», «To», «CC». Для этих целей используется функция crackaddr(char* addr), которая описана в файле headers.c. Обрабатываемые данные помещаются в статический буфер, после заполнения которого они проходят несколько проверок безопасности. Одна из этих проверок функционирует некорректно, эта особенность дает возможность злоумышленнику (при помощи специально сформированного поля адреса) переполнить буфер и выполнить произвольный код от имени пользователя, запустившего MTA. Некорректная работа одной из проверок заключается в обработке символов '<' и '>', указанных в адресе реципиента. Дело в том, что при обработке данного поля каждая встреча символа '>', указатель buflim, который ссылается на конец буфера, инкрементируется на 1. Но в тоже время появление '<' никак не обрабатывается, хотя при возникновении такой ситуации указатель buflim должен быть декрементирован. Поскольку каждой закрывающейся скобке должна предшествовать открывающаяся, мы не можем просто указать в адресе N закрывающихся скобок, чтобы увеличить буфер на N. К сожалению, для увеличения значения указателя buflim на 1, нужно использовать комбинацию '<>'. Для вычисления максимального значения X, на которое можно увеличить указатель конца буфера, нужно решить простое уравнение: (2 * x) <= (MAXNAME + 1 - 7) + x x <= (MAXNAME + 1 - 7)
Таким образом мы определяем, насколько можно увеличить значение buflim, чтобы добиться максимального количества байт, которые переполнят буфер. В данном случае оно будет равно 250.
Эксплуатация Из-за статистической декларации буфера на пути к эксплуатации данной уязвимости становятся компиляторы, размещающие статические данные в сегменте данных (data segment). Другими словами, должны быть некие используемые статические данные, размещенные по окончании буфера, которые при его переполнении исполнились бы от имени процесса Sendmail. После экспериментов, проведенных Польской хакерской командой LAST STAGE OF DELIRIUM (LSD) выяснилось, что на большинстве Unix-системах за буфером такие данные не расположены. Следующий список содержит результаты, полученные при исследовании:
№4(5), апрель 2003
does not crash;
Solaris 8.0 sparc – (default & self compiled Sendmail 8.11.6) does not crash;
HP-UX 10.20 – (self compiled Sendmail 8.11.6) does not crash;
IRIX 6.5.14 – (self compiled Sendmail 8.11.6) does not crash; AIX 4.3 – (binary of Sendmail 8.11.3 from bull.de) does not crash;
RedHat 7.0 – (default Sendmail 8.11.0) does not crash; RedHat 7.2 – (default Sendmail 8.11.6) does not crash; RedHat 7.3 (patch) – (patched Sendmail 8.11.6) does not crash;
RedHat 7.0 – (self compiled Sendmail 8.11.6) crashes; RedHat 7.2 – (self compiled Sendmail 8.11.6) crashes; RedHat 7.3 – (self compiled Sendmail 8.11.6) crashes; Slackware 8.0 (patch) – (patched Sendmail 8.11.6 binary) crashes;
Slackware 8.0 – (self compiled Sendmail 8.12.7) does not crash;
RedHat 7.x – (self compiled Sendmail 8.12.7) does not crash. Из предложенной вашему вниманию статистики прежде всего видно, что многие системы являются потенциально чуствительными к данной уязвимости. Это RedHat и Slackware Linux. Как выяснилось, причиной крушения Sendmail в этих системах есть неверное значение указателя MciCache, обьявленного в файле mci.c. LSD провели более детальное исследование и им удалось успешно эксплуатировать уязвимость Buffer Overrun в системе Linux Slackware 8.0. Достичь этого удалось, изменяя значения некоторых указателей и MciCache в частности. Определенно нужно изменить следующие данные: установить значение статического указателя MCI **MciCache в адрес начала структуры mailer_con_info; установить адрес структуры *mci_mailer в адрес MCI; указатель на *mci_host в адрес MCI; указатель на FILE *mci_out в адрес MCI. После внесения изменений становится возможным влияние на исполнение процеса Sendmail: Program received signal SIGSEGV, Segmentation fault. 0x400ee94a in _IO_vfprintf (s=0xaabbccdd, format=0x809b773 ↵ "%s%s", ap=0xbfffd6ac) at vfprintf.c:1024 1024 vfprintf.c: No such file or directory. (gdb) where #0 0x400ee94a in _IO_vfprintf (s=0xaabbccdd, ↵ format=0x809b773 "%s%s", ap=0xbfffd6ac) at vfprintf.c:1024 #1 0x400f7047 in fprintf (stream=0xaabbccdd, ↵ format=0x809b773 "%s%s")at fprintf.c:32 #2 0x8084ff8 in smtpmessage () #3 0x80847ac in smtpquit () #4 0x8069e89 in mci_uncache () #5 0x8069f14 in mci_flush () #6 0x804e0b9 in finis () #7 0x8073042 in dowork () #8 0x807f9bc in smtp () #9 0x804da8e in main () #10 0x400c19cb in __libc_start_main (main=0x804ac00, argc=3, argv=0xbffffbe4, init=0x804a07c <_init>, fini=0x808918c ↵ <_fini>, rtld_fini=0x4000ae60 <_dl_fini>, ↵ stack_end=0xbffffbdc) at ../sysdeps/generic/libc-start.c:92
55
FREEBSD компиляция
администрирование Перекомпиляция ядра и самой операционной системы FreeBSD – часть непрерывного процесса обеспечения безопасности интернет-сервера, и хотя у новичка в мире открытых исходников слова "компиляция ядра операционной системы" обычно вызывают благоговейное преклонение перед произносящим их, этот процесс на самом деле не является слишком сложным и тем более таинственным. В этой статье я опишу обычный порядок перекомпиляции системы, ее ядра, а также основные опции и параметры команды make, используемые в процессе компиляции для систем, основанных на процессорах семейства Intel x86. На вашей машине должны быть установлены инструменты разработки – gcc, make и все соответствующие библиотеки и заголовочные файлы. Исходные тексты операционной системы обычно находятся в каталоге /usr/src. Для их обновления до текущей версии чаще всего используется программа cvsup, устанавливаемая из коллекции пакетов FreeBSD. cvsup является разновидностью CVS [2] (concurrent versions system, одна из широко распространенных систем управления версиями программ, используемых для групповой разработки программного обеспечения. СVS обеспечивает подмножество ее функций, необходимое для синхронизации локальных файлов с файлами, расположенными на master-сервере cvsup. При работе cvsup передает только различия (diffs) между измененными со времени последнего обновления файлами, а также может использовать компрессию потока (с использованием zlib), что позволяет этому методу обновления существенно выигрывать в производительности и нагрузке на канал по сравнению, например, c FTP. Данная программа вызывается с параметром, указывающим местоположение файла, описывающего следующие основные параметры: местонахождение исходных текстов OS на локальном винчестере; имя сервера, на котором расположен репозиторий с исходными текстами, соответствующими текущей версии; части операционной системы (например, игры, библиотеки, ядро или вся система целиком), подлежащие обновлению. Рассмотрим подробно два параметра – default tag и список коллекций для обновления. Параметр default tag указывает, до какой ветки FreeBSD вы хотите производить апгрейд. Возможные варианты:
АЛЕКСАНДР ПРОКОШЕВ №4(5), апрель 2003
. (òî÷êà) – FreeBSD-current. FreeBSD "ñ ïåðåäíåãî êðàÿ". Íå ðåêîìåíäóåòñÿ òåì, êòî òîëüêî îñâàèâàåò ïðîöåññ ïåðåêîìïèëÿöèè. RELENG_5_0 – FreeBSD 5.0 Âåòêà 5.0-RELEASE, èñïîëüçóåòñÿ äëÿ êðèòè÷åñêèõ áàãôèêñîâ è ïàò÷åé ñèñòåìû áåçîïàñíîñòè. RELENG_4 Âåòêà FreeBSD-4.x. Ñåé÷àñ ýòî FreeBSD-STABLE. Îñíîâíàÿ âåòâü ðàçâèòèÿ ÷åòâåðòîé âåðñèè ñèñòåìû. RELENG_4_7 FreeBSD-4.7-RELEASE, èñïîëüçóåòñÿ äëÿ êðèòè÷åñêèõ áàãôèêñîâ è ïàò÷åé ñèñòåìû áåçîïàñíîñòè. RELENG_4_6 FreeBSD 4.6 è 4.6.2, èñïîëüçóåòñÿ äëÿ êðèòè÷åñêèõ áàãôèêñîâ è ïàò÷åé ñèñòåìû áåçîïàñíîñòè. RELENG_4_5
57
администрирование FreeBSD 4.5, èñïîëüçóåòñÿ äëÿ êðèòè÷åñêèõ ïàò÷åé ñèñòåìû áåçîïàñíîñòè. RELENG_4_4 FreeBSD 4.4, èñïîëüçóåòñÿ äëÿ êðèòè÷åñêèõ ïàò÷åé ñèñòåìû áåçîïàñíîñòè. RELENG_4_3 FreeBSD 4.3, èñïîëüçóåòñÿ äëÿ êðèòè÷åñêèõ ïàò÷åé ñèñòåìû áåçîïàñíîñòè. RELENG_3 Âåòêà FreeBSD-3.x. Ñåé÷àñ ýòî 3.x-STABLE. âåòâü ðàçâèòèÿ òðåòüåé âåðñèè ñèñòåìû. RELENG_2_2 Âåòêà FreeBSD-2.2.x. Óñòàðåâøàÿ âåòâü.
áàãôèêñîâ è áàãôèêñîâ è áàãôèêñîâ è Îñíîâíàÿ
Чем отличается RELEASE от STABLE? Очень просто: STABLE – это то, что получается из RELEASE в процессе его (релиза) технического сопровождения, то есть исправления ошибок и латания обнаруженных дыр в безопасности. Отдельным пунктом здесь стоит версия системы, обозначаемая тегом RELENG_4, которая представляет собой "стабильную ветвь разработки". Рано или поздно на основе этой версии будет выпущена версия 4.8-RELEASE (RELENG_4_8_0_RELEASE), от которой, в свою очередь, отойдет 4.8-STABLE (RELENG_4_8). Переходим к списку коллекций. cvsup понимает следующие коллекции, относящиеся к исходным текстам операционной системы: src-all Ïîëíîå äåðåâî èñõîäíèêîâ src-base Áàçîâûå ïðîãðàììû src-bin Ïðîãðàììû â /usr/src/bin – òî, ÷òî ïîñëå óñòàíîâêè íàõîäèòñÿ â /bin src-contrib Contributed software, â òîì ÷èñëå awk, gcc, tcpdump è ìíîãîå äðóãîå, áåç ÷åãî íå îáîéòèñü. src-etc Òî, ÷òî ñ ïîìîùüþ mergemaster'à óñòàíàâëèâàåòñÿ â /etc src-games Èãðû. src-gnu GNU software src-include .h-ôàéëû äëÿ ïîìåùåíèÿ â /usr/include src-kerberos5 Kerberos 5. src-kerberosIV Kerberos 4. src-lib Èñõîäíèêè ñèñòåìíûõ áèáëèîòåê. src-libexec Íåêîòîðûå äåìîíû. Ñêëàäûâàþòñÿ â /usr/libexec src-release Èíñòðóìåíòû äëÿ ïîñòðîåíèÿ äèñòðèáóòèâà. src-sbin Áóäóùåå ñîäåðæèìîå /sbin src-share Áóäóùåå ñîäåðæèìîå /usr/share src-sys Èñõîäíèêè ÿäðà src-tools Èíñòðóìåíòû äëÿ òåñòèðîâàíèÿ è ïîääåðæêè ñèñòåìû. Íå ñîáèðàþòñÿ âî âðåìÿ buildworld. src-usrbin Áóäóùåå ñîäåðæèìîå /usr/bin src-usrsbin Áóäóùåå ñîäåðæèìîå /usr/sbin src-crypto src-eBones src-secure src-sys-crypto Êðèïòîïîäñèñòåìà.
Еще раз подчеркну, что коллекция src-all включает в себя все остальные коллекции, так что если в sup-файле вы указали "src-all", нет надобности указывать еще какиелибо коллекции. С другой стороны, FreeBSD Handbook [1] рекомендует не обновлять userspace программы отдельно от ядра и наоборот, так как это может привести к нера-
58
ботоспособности программ из-за несоответствий структур данных (простой пример – команда ps, часто не работающая с ядром, версия которого не соответствует версии остальной системы). Полностью формат sup-файла описан в документации по cvsup. Далее в этой статье я предполагаю, что параметр default tag установлен в значение "RELENG_4", соответствующий версии системы 4.x-STABLE, и производится обновление системы целиком (используется тег src-all). При этом наш sup-файл имеет примерно следующий вид: --== cut /etc/cvsupfile.sys ==-# Ôàéë îáíîâëåíèÿ ñèñòåìû *default *default *default *default *default *default
host=cvsup5.FreeBSD.org base=/usr prefix=/usr release=cvs tag=RELENG_4 delete use-rel-suffix compress
src-all # src-base # src-bin # src-contrib # src-etc # src-games # src-gnu # src-include # src-kerberos5 # src-kerberosIV # src-lib # src-libexec # src-release # src-sbin # src-share # src-sys # src-tools # src-usrbin # src-usrsbin # src-crypto # src-eBones # src-secure # src-sys-crypto --== end cut ==--
Запускаем cvsup: --== cut here ==-ice.root# cvsup /etc/cvsupfile.sys Connected to cvsup5.FreeBSD.org Updating collection src-all/cvs Edit src/etc/Makefile [âûâîäèìûå ñîîáùåíèÿ îïóùåíû] Edit src/share/misc/pci_vendors Finished successfully ice.root# --== end cut ==--
После успешного завершения работы cvsup в каталоге /usr/src нашего компьютера находятся исходные тексты, соответствующие текущему содержанию CVS-репозитория ветки STABLE четвертого релиза FreeBSD. Теперь переходим к компиляции. Сначала просмотрим файл, настройки которого влияют на конфигурацию и производительность получаемой в результате системы – /etc/make.conf (или /etc/defaults/ make.conf). В нем вы можете задать параметры оптимизации для компилятора, указать, компилировать ли профилировочные версии библиотек, sendmail, поставляемый с системой, perl, а также некоторые другие опции. Интересное замечание насчет параметров оптимизации: FreeBSD Handbook [1] рекомендует выставлять флаг оптимизации "-O", но ничто не мешает вам выставить, к при-
администрирование меру "-O3 -march=i686", хотя, конечно, это скажется на времени компиляции. Еще одно важное замечание: если вы производите апгрейд с версии FreeBSD 4.7-RELEASE или ниже на 4-STABLE, обязательно выставьте параметр "COMPAT3X" файла /etc/make.conf в значение "yes", иначе при запуске программ, скомпилированных для FreeBSD 3.x (одной из таких программ является JDK 1.1.8, содержащийся в ports), вы увидите сообщение динамического редактора связей о ненайденном символе __stderrp в системных библиотеках. Начнем с конфигурации ядра. Традиционно в 4.3BSDbased системах, к которым относится и FreeBSD, конфигурация ядра описывается в текстовом файле, который затем с помощью команды config преобразуется в h-файлы и Makefile, используемые непосредственно инструментами компиляции. Примеры файлов конфигурации находятся в каталоге /usr/src/sys/i386/conf и называются GENERIC и LINT. Для создания своей конфигурации скопируйте файл GENERIC в файл, к примеру: MYCONF: cd /usr/src/sys/i386/conf cp GENERIC MYCONF
и приступайте к его редактированию. Значения опций довольно подробно описаны в файле LINT, и я не буду повторно описывать их здесь. Естественно, вы должны отчетливо представлять себе аппаратную конфигурацию вашей машины. И еще один совет: на первых порах случается всякое, поэтому лучше вносить серьезные изменения в конфигурацию ядра той же версии, под которой в данный момент работает ваш компьютер, то есть до обновления исходников через cvsup. Такой подход имеет два преимущества: исключается полная перекомпиляция системы (то есть make buildworld не выполняется – только make buildkernel, так как установленная система той же версии, что и собираемое ядро), что значительно уменьшает время итерации; больше возможности сохранить работоспособность системы при загрузке со старым ядром в случае неработоспособности вновь собранного из-за того же самого соответствия версии системы версии ядра. После завершения редактирования перейдите в каталог /usr/src и дайте команду сборки системы: cd /usr/src make buildworld. Время выполнения этой команды зависит от заданных ранее опций компиляции и может составить от часа до нескольких часов. Если вы компилируете на многопроцессорной машине, имеет смысл выполнять make с ключом -j<n+2>, где n – количество процессоров:
make buildkernel KERNCONF=MYCONF
Здесь MYCONF – имя того самого файла конфигурации ядра в каталоге /usr/src/sys/i386/conf, который вы недавно редактировали. Обратите внимание, что команда make выполняется в каталоге /usr/src, а имя файла конфигурации передается ей без пути до него. После успешного завершения работы make перейдите в однопользовательский режим: shutdown now
и, вновь войдя в каталог /usr/src cd /usr/src, выполните три заключительные команды: make installkernel KERNCONF=MYCONF make installworld fastboot
При выполнении make installkernel ваше нынешнее ядро будет скопировано в файл /kernel.old, а модули – в каталог /modules.old. Это даст вам шанс все же запустить систему со старым ядром, если новое по какой-либо причине окажется неработоспособным. Совет: если вы компилировали ядро самый первый раз (то есть то, которое перед выполнением make installkernel находится в файле /kernel, заведомо работоспособно), перед make installkernel скопируйте его на всякий случай, допустим, в /kernel.stable, чтобы оно не затерлось последующими выполнениями make installkernel. У вас будет возможность впоследствии загрузить его из командной строки начального загрузчика OS вместо ядра по умолчанию /kernel. Описание работы с командами начального загрузчика выходит далеко за рамки темы данной статьи, поэтому интересующихся мы отсылаем к страницам онлайнового руководства по операционной системе, касающихся команд boot и loader (man 8 boot и man 8 loader). Если все прошло успешно, то после перезагрузки вы будете работать в совершенно свежей операционной системе, только что собранной практически своими руками. С другой стороны, нельзя не напомнить о необходимости делать резервное копирование файловых систем перед началом апгрейда. Ссылки: [1] FreeBSD Handbook http://www.freebsd.org/doc/ en_US.ISO8859-1/books/handbook/index.html [2] Concurrent versions system http://www.cvshome.org
make -j4 buildworld
Внимание! Для сборки системы вам потребуется около 300 Мб свободного места на разделе файловой системы, содержащем каталог /usr/obj. После окончания сборки системы остается только скомпилировать ядро:
№4(5), апрель 2003
59
АБСОЛЮТНО ВСЕ О
ATM СЕРГЕЙ РОПЧАН
администрирование Технология асинхронного режима передачи (Asynchronous Transfer Mode, ATM) разработана как единый универсальный транспорт для нового поколения сетей с интеграцией услуг, которые называются широкополосными сетями ISDN (Broadband-ISDN, BISDN). По планам разработчиков единообразие, обеспечиваемое ATM, будет состоять в том, что одна транспортная технология сможет обеспечить несколько перечисленных ниже возможностей, то есть подразумевалось сделать эту технологию насколько возможно универсальной: Передачу в рамках одной транспортной системы компьютерного и мультимедийного (голос, видео) трафика, чувствительного к задержкам, причем для каждого вида трафика качество обслуживания будет соответствовать его потребностям. Иерархию скоростей передачи данных, от десятков мегабит до нескольких гигабит в секунду с гарантированной пропускной способностью для ответственных приложений. Общие транспортные протоколы для локальных и глобальных сетей. Сохранение имеющейся инфраструктуры физических каналов или физических протоколов: Т1/Е1, ТЗ/ ЕЗ, SDH STM-n, FDDI. Взаимодействие с унаследованными протоколами локальных и глобальных сетей: IP, SNA, Ethernet, ISDN. Главная идея технологии асинхронного режима передачи была высказана достаточно давно – этот термин ввела лаборатория Bell Labs еще в далеком 1968 году. Основной разрабатываемой технологией тогда была технология TDM с синхронными методами коммутации, основанными на порядковом номере байта в объединенном кадре. Главный недостаток технологии TDM, которую также называют технологией синхронной передачи STM (Synchronous Transfer Mode), заключается в невозможности перераспределять пропускную способность объединенного канала между подканалами. В те периоды времени, когда по подканалу не передаются пользова-
№4(5), апрель 2003
тельские данные, объединенный канал все равно передает байты этого подканала, заполненные нулями. Попытки загрузить периоды простоя подканалов приводят к необходимости введения заголовка для данных каждого подканала. В промежуточной технологии STDM (Statistical TDM), которая позволяет заполнять периоды простоя передачей пульсаций трафика других подканалов, действительно вводятся заголовки, содержащие номер подканала. Данные при этом оформляются в пакеты, похожие по структуре на пакеты компьютерных сетей. Наличие адреса у каждого пакета позволяет передавать его асинхронно, так как местоположение его относительно данных других подканалов уже не является его адресом. Асинхронные пакеты одного подканала вставляются в свободные таймслоты другого подканала, но не смешиваются с данными этого подканала, так как имеют собственный адрес. Технология ATM совмещает в себе подходы двух технологий – коммутации пакетов и коммутации каналов. От первой она взяла на вооружение передачу данных в виде адресуемых пакетов, а от второй – использование пакетов небольшого фиксированного размера, в результате чего задержки в сети становятся более предсказуемыми, в связи с чем облегчается анализ и мониторинг. С помощью техники виртуальных каналов, предварительного заказа параметров качества обслуживания канала и приоритетного обслуживания виртуальных каналов с разным качеством обслуживания удается добиться передачи в одной сети разных типов трафика без дискриминации. Технология ATM с самого начала разрабатывалась как технология, способная обслуживать все виды трафика в соответствии с их требованиями. Службы верхних уровней сети BISDN должны быть примерно такими же, что и у сети ISDN – это передача факсов, распространение телевизионного изображения, голосовая почта, электронная почта, различные интерактивные службы, например проведение видеоконференций. Высокие скорости технологии ATM создают гораздо больше возможностей для служб верхнего уровня, которые не
могли быть реализованы сетями ISDN – например, для передачи цветного телевизионного изображения необходима полоса пропускания в районе 30 Мбит/с. Технология ISDN такую скорость поддержать не может, а для ATM она не составляет больших проблем. Разработку стандартов ATM осуществляет группа организаций под названием ATM Forum под эгидой специального комитета IEEE, а также комитеты ITU-T и ANSI. ATM – это очень сложная технология, требующая стандартизации в самых различных аспектах, поэтому, хотя основное ядро стандартов было принято в 1993 году, работа по стандартизации активно продолжается. Оптимизм внушает тот факт, что в ATM Forum принимают участие практически все заинтересованные стороны – производители телекоммуникационного оборудования, производители оборудования локальных сетей, операторы телекоммуникационных сетей и сетевые интеграторы.
Основные концепции технологии ATM Сеть ATM имеет классическую структуру крупной территориальной сети – конечные станции соединяются индивидуальными каналами с коммутаторами нижнего уровня, которые, в свою очередь, соединяются с коммутаторами более высоких уровней. Коммутаторы ATM пользуются 20-байтными адресами конечных узлов для маршрутизации трафика на основе техники виртуальных каналов. Для частных сетей ATM определен протокол маршрутизации PNNI (Private NNI), с помощью которого коммутаторы могут строить таблицы маршрутизации автоматически. В публичных сетях ATM таблицы маршрутизации могут строиться администраторами вручную, как и в сетях Х.25, или могут поддерживаться протоколом PNNI. Коммутация пакетов происходит на основе идентификатора виртуального канала (Virtual Channel Identifier, VCI), который назначается соединению при его установлении и уничтожается при разрыве соединения. Адрес конечного узла ATM, на основе которого прокладывается виртуальный канал, имеет иерархическую структуру, подобную номеру в телефонной сети, и исполь-
61
администрирование зует префиксы, соответствующие кодам стран, городов, сетям поставщиков услуг и т. п., что упрощает маршрутизацию запросов установления соединения, как и при использовании агрегированных IP-адресов в соответствии с техникой CIDR (техника захвата среды). Виртуальные соединения могут быть постоянными (Permanent Virtual Circuit, PVC) и коммутируемыми (Switched Virtual Circuit, SVC), Для ускорения коммутации в больших сетях используется понятие виртуального пути – Virtual Path, который объединяет виртуальные каналы, имеющие в сети ATM общий маршрут между исходным и конечным узлами или общую часть маршрута между двумя коммутаторами сети. Идентификатор виртуального пути (Virtual Path Identifier, VPI) является старшей частью локального адреса и представляет собой общий префикс для некоторого количества различных виртуальных каналов. Таким образом, идея агрегирования адресов в технологии ATM применена на двух уровнях – на уровне адресов конечных узлов (работает на стадии установления виртуального канала) и на уровне номеров виртуальных каналов (работает при передаче данных по имеющемуся виртуальному каналу). Соединения конечной станции ATM с коммутатором нижнего уровня определяются стандартом UNI (User Network Interface). Спецификация UNI определяет структуру пакета, адресацию станций, обмен управляющей информацией, уровни протокола ATM, способы установления виртуального канала и способы управления трафиком. В настоящее время принята версия UNI 4.0, но наиболее распространенной версией, поддерживаемой производителями оборудования, является версия UNI 3.1. Стандарт ATM не вводит свои спецификации на реализацию физического уровня. Здесь он основывается на технологии SDH/SONET, принимая ее иерархию скоростей. В соответствии с этим начальная скорость доступа пользователя сети – это скорость ОС-3 155 Мбит/с. Организация ATM Forum определила для ATM не все иерархии скоростей SDH, а только скорости ОС-3 и ОС-12 (622 Мбит/с). На скорости 155 Мбит/с можно использо-
62
вать не только волоконно-оптический кабель, но и неэкранированную витую пару категории 5. На скорости 622 Мбит/с допустим только волоконно-оптический кабель, причем как SMF, так и MMF. Имеются и другие физические интерфейсы к сетям ATM, отличные от SDH/SONET. К ним относятся интерфейсы Т1/Е1 и ТЗ/ЕЗ, распространенные в глобальных сетях, и интерфейсы локальных сетей – интерфейс с кодировкой 4В/5В со скоростью 100 Мбит/с (FDDI) и интерфейс со скоростью 25 Мбит/с, предложенный компанией IBM и утвержденный ATM Forum. Кроме того, для скорости 155,52 Мбит/с определен так называемый “cell-based” физический уровень, то есть уровень, основанный на ячейках, а не на кадрах SDH/SONET. Этот вариант физического уровня не использует кадры SDH/SONET, а отправляет по каналу связи непосредственно ячейки формата ATM, что сокращает накладные расходы на служебные данные, но несколько усложняет задачу синхронизации приемника с передатчиком на уровне ячеек. Все перечисленные выше характеристики технологии ATM не свидетельствуют о том, что это некая “особенная” технология, а скорее представляют ее как типичную технологию глобальных сетей, основанную на технике виртуальных каналов. Особенности же технологии ATM лежат в области качественного обслуживания разнородного трафика и объясняются стремлением решить задачу совмещения в одних и тех же каналах связи и в одном и том же коммуникационном оборудовании компьютерного и мультимедийного трафика таким образом, чтобы каждый тип трафика получил требуемый уровень обслуживания и не рассматривался как “второстепенный”. Подход, реализованный в технологии ATM, состоит в передаче любого вида трафика – компьютерного, телефонного или видео – пакетами фиксированной и очень маленькой длины в 53 байта. Пакеты ATM называют ячейками – cell. Поле данных ячейки занимает 48 байт, а заголовок – 5 байт. Чтобы пакеты содержали адрес узла назначения и в то же время процент служебной информации не превышал размер поля данных пакета, в
технологии ATM применен стандартный для глобальных вычислительных сетей прием – передача ячеек в соответствии с техникой виртуальных каналов с длиной номера виртуального канала в 24 бита, что вполне достаточно для обслуживания большого количества виртуальных соединений каждым портом коммутатора глобальной (может быть всемирной) сети ATM. Размер ячейки ATM является результатом компромисса между телефонистами и компьютерщиками – первые настаивали на размере поля данных в 32 байта, а вторые – в 64 байта. Чем меньше пакет, тем легче имитировать услуги каналов с постоянной битовой скоростью, которая характерна для телефонных сетей. Ясно, что при отказе от жестко синхронизированных временных слотов для каждого канала идеальной синхронности добиться будет невозможно, однако чем меньше размер пакета, тем легче этого достичь. Для пакета, состоящего из 53 байт, при скорости в 155 Мбит/с время передачи кадра на выходной порт составляет менее 3 мкс. Так что эта задержка не очень существенна для трафика, пакеты которого должны передаваться каждые 125 мкс. Однако на выбор размера ячейки большее влияние оказала не величина ожидания передачи ячейки, а задержка пакетизации. Задержка пакетизации – это время, в течение которого первый замер голоса ждет момента окончательного формирования пакета и отправки его по сети. При размере поля данных в 48 байт одна ячейка ATM обычно переносит 48 замеров голоса, которые делаются с интервалом в 125 мкс. Поэтому первый замер должен ждать примерно 6 мс, прежде чем ячейка будет отправлена по сети. Именно по этой причине телефонисты боролись за уменьшения размера ячейки, так как 6 мс – это задержка, близкая к пределу, за которым начинаются нарушения качества передачи голоса. При выборе размера ячейки в 32 байта задержка пакетизации составила бы 4 мс, что гарантировало бы более качественную передачу голоса. А стремление компьютерных специалистов увеличить поле данных до 64 байт вполне понятно – при этом повышается полезная скорость передачи
администрирование данных. Избыточность служебных данных при использовании 48-байтного поля данных составляет 10 %, а при использовании 32-байтного поля данных она сразу повышается до 16 %. Выбор для передачи данных любого типа небольшой ячейки фиксированного размера еще не решает задачу совмещения разнородного трафика в одной сети, а только создает предпосылки для ее решения. Для полного решения этой задачи технология ATM привлекает и развивает идеи заказа пропускной способности и качества обслуживания, реализованные в технологии frame relay. Но если сеть frame relay изначально была предназначена для передачи только пульсирующего компьютерного трафика (в связи с этим для сетей frame relay так трудно дается стандартизация передачи голоса), то разработчики технологии ATM проанализировали всевозможные образцы трафика, создаваемые различными приложениями, и выделили 4 основных класса трафика, для которых разработали различные механизмы резервирования и поддержания требуемого качества обслуживания. Класс трафика (называемый также классом услуг – service class) качественно характеризует требуемые услуги по передаче данных через сеть ATM. Если приложение указывает сети, что требуется, например, передача голосового трафика, то из этого становится ясно, что особенно важными для пользователя будут такие показатели качества обслуживания, как задержки и вариации задержек ячеек, существенно влияющие на качество переданной информации – голоса или изображения, а потеря отдельной ячейки с несколькими замерами не так уж важна, как, например, воспроизводящее голос устройство может аппроксимировать недостающие замеры и качество пострадает не слишком. Требования к синхронности передаваемых данных очень важны для многих приложений – не только голоса, но и видеоизображения, и наличие этих требований стало первым критерием для деления трафика на классы. Другим важным параметром трафика, существенно влияющим на способ его передачи через сеть, является величина его пульсаций. Разработчики технологии ATM решили выделить
№4(5), апрель 2003
два различных типа трафика в отношении этого параметра – трафик с постоянной битовой скоростью (Constant Bit Rate, CBR) и трафик с переменной битовой скоростью (Variable Bit Rate, VBR). К разным классам были отнесены трафики, порождаемые приложениями, использующими для обмена сообщениями протоколы с установлением соединений и без установления соединений. В первом случае данные передаются самим приложением достаточно надежно, как это обычно делают протоколы с установлением соединения, поэтому от сети ATM высокой надежности передачи не требуется. А во втором случае приложение работает без установления соединения и восстановлением потерянных и искаженных данных не занимается, что предъявляет повышенные требования к надежности передачи ячеек сетью ATM. В результате было определено пять классов трафика, отличающихся следующими качественными характеристиками: наличием или отсутствием пульсации трафика, то есть трафики CBR или VBR; требованием к синхронизации данных между передающей и принимающей сторонами; типом протокола, передающего свои данные через сеть ATM, с установлением соединения или без установления соединения (только для случая передачи компьютерных данных). Очевидно, что только качественных характеристик, задаваемых классом трафика, для описания требуемых услуг оказывается недостаточно. В технологии ATM для каждого класса трафика определен набор количественных параметров, которые приложение должно задать. Например, для трафика класса А необходимо указать постоянную скорость, с которой приложение будет посылать данные в сеть, а для трафика класса В – максимально возможную скорость, среднюю скорость и максимально возможную пульсацию. Для голосового трафика можно не только указать на важность синхронизации между передатчиком и приемником, но и количественно задать вер-
хние границы задержки и вариации задержки ячеек. В технологии ATM поддерживается следующий набор основных количественных параметров: Peak Cell Rate (PCR) – максимальная скорость передачи данных; Sustained Cell Rate (SCR) – средняя скорость передачи данных; Minimum Cell Rate (MCR) – минимальная скорость передачи данных; Maximum Burst Size (MBS) – максимальный размер пульсации; Cell Loss Ratio (CLR) – доля потерянных ячеек; Cell Transfer Delay (CTD) – задержка передачи ячеек; Cell Delay Variation (CDV) – вариация задержки ячеек. Параметры скорости измеряются в ячейках в секунду, максимальный размер пульсации – в ячейках, а временные параметры – в секундах. Максимальный размер пульсации задает количество ячеек, которое приложение может передать с максимальной скоростью PCR, если задана средняя скорость. Доля потерянных ячеек является отношением потерянных ячеек к общему количеству отправленных ячеек по данному виртуальному соединению. Так как виртуальные соединения являются дуплексными, то для каждого направления соединения могут быть заданы разные значения параметров. В технологии ATM принят не совсем традиционный подход к трактовке термина “качество обслуживания” – QoS. Обычно качество обслуживания трафика характеризуется параметрами пропускной способности (здесь это RCR, SCR, MCR, MBS), параметрами задержек пакетов (СТО и CDV), а также параметрами надежности передачи пакетов (CLR). В ATM характеристики пропускной способности называют параметрами трафика и не включают их в число параметров качества обслуживания QoS, хотя по существу они таковыми являются. Параметрами QoS в ATM являются только параметры CTD, CDV и CLR. Сеть старается обеспечить такой уровень услуг, чтобы поддерживались требуемые значения и параметров трафика, и задержек ячеек, и доли потерянных ячеек. Соглашение между приложением и
63
администрирование сетью ATM называется трафик-контрактом. Основным его отличием от соглашений, применяемых в сетях frame relay, является выбор одного из нескольких определенных классов трафика, для которого наряду с параметрами пропускной способности трафика могут указываться параметры задержек ячеек, а также параметр надежности доставки ячеек. В сети frame relay класс трафика один, и он характеризуется только параметрами пропускной способности. Необходимо подчеркнуть, что задание только параметров трафика (вместе с параметрами QoS) часто не полностью характеризует требуемую услугу, поэтому задание класса трафика полезно для уточнения нужного характера обслуживания данного соединения сетью. Если для приложения не критично поддержание параметров пропускной способности и QoS, то оно может отказаться от задания этих параметров, указав признак “Best Effort” в запросе на установление соединения. Такой тип трафика получил название трафика с неопределенной битовой скоростью – Unspecified Bit Rate, UBR. После заключения трафик-контракта, который относится к определенному виртуальному соединению, в сети ATM работает несколько протоколов и служб, обеспечивающих нужное качество обслуживания. Для трафика UBR сеть выделяет ресурсы “по возможности”, то есть те, которые в данный момент свободны от использования виртуальными соединениями, заказавшими определенные параметры качества обслуживания. Технология ATM изначально разрабатывалась для поддержки как постоянных, так и коммутируемых виртуальных каналов (в отличие от технологии frame relay, долгое время не поддерживающей коммутируемые виртуальные каналы). Автоматическое заключение трафик-контракта при установлении коммутируемого виртуального соединения представляет собой весьма непростую задачу, так как коммутаторам ATM необходимо определить, смогут ли они в дальнейшем обеспечить передачу трафика данного виртуального канала наряду с трафиком других виртуальных каналов таким образом, чтобы выполнялись требова-
64
ния качества обслуживания каждого канала. Стек протоколов ATM показан на таблице ниже:
передаваемого трафика) и занимается разбиением (сегментацией) сообщения, принимаемого AAL от протокола верхнего уровня, на ячейки ATM,
Стек протоколов ATM соответствует нижним уровням семиуровневой модели ISO/OSI и включает уровень адаптации ATM, собственно уровень ATM и физический уровень. Прямого соответствия между уровнями протоколов технологии ATM и уровнями модели OSI нет. Уровень адаптации (ATM Adaptation Layer, AAL) представляет собой набор протоколов AAL1-AAL5, которые преобразуют сообщения протоколов верхних уровней сети ATM в ячейки ATM нужного формата. Функции этих уровней достаточно условно соответствуют функциям транспортного уровня модели OSI, например функциям протоколов TCP или UDP. Протоколы AAL при передаче пользовательского трафика работают только в конечных узлах сети, как и транспортные протоколы большинства технологий. Каждый протокол уровня AAL обрабатывает пользовательский трафик определенного класса. На начальных этапах стандартизации каждому классу трафика соответствовал свой протокол AAL, который принимал в конечном узле пакеты от протокола верхнего уровня и заказывал с помощью соответствующего протокола нужные параметры трафика и качества обслуживания для данного виртуального канала. При развитии стандартов ATM такое однозначное соответствие между классами трафика и протоколами уровня AAL исчезло, и сегодня разрешается использовать для одного и того же класса трафика различные протоколы уровня AAL. Уровень адаптации состоит из нескольких подуровней. Нижний подуровень AAL называется подуровнем сегментации и реассемблирования (Segmentation And Reassembly, SAR). Эта часть не зависит от типа протокола AAL (и, соответственно, от класса
снабжением их соответствующим заголовком и передачей уровню ATM для отправки в сеть. Верхний подуровень AAL называется подуровнем конвергенции – Convergence Sublayer, CS. Этот подуровень зависит от класса передаваемого трафика. Протокол подуровня конвергенции решает такие задачи, как, например, обеспечение временной синхронизации между передающим и принимающим узлами (для трафика, требующего такой синхронизации), контролем и возможным восстановлением битовых ошибок в пользовательской информации, контролем целостности передаваемого пакета компьютерного протокола (Х.25, frame relay). Протоколы AAL для выполнения своей работы используют служебную информацию, размещаемую в заголовках уровня AAL. После приема ячеек, пришедших по виртуальному каналу, подуровень SAR протокола AAL собирает посланное по сети исходное сообщение (которое в общем случае было разбито на несколько ячеек ATM) с помощью заголовков AAL, которые для коммутаторов ATM являются прозрачными, так как помещаются в 48битном поле данных ячейки, как и полагается протоколу более высокого уровня. После сборки исходного сообщения протокол AAL проверяет служебные поля заголовка и концевика кадра AAL и на их основании принимает решение о корректности полученной информации. Ни один из протоколов AAL при передаче пользовательских данных конечных узлов не занимается восстановлением потерянных или искаженных данных. Максимум, что делает протокол AAL, – это уведомляет конечный узел о таком событии. Так сделано для ускорения работы коммутато-
администрирование ров сети ATM в расчете на то, что случаи потерь или искажения данных будут редкими. Восстановление потерянных данных (или игнорирование этого события) отводится протоколам верхних уровней, не входящим в стек протоколов технологии ATM. Существует определенный интерфейс между приложением, которому требуется передать трафик через сеть ATM, и уровнем адаптации AAL. С помощью этого интерфейса приложение (протокол компьютерной сети, модуль оцифровывания голоса) заказывает требуемую услугу, определяя тип трафика, его параметры, а также параметры QoS. Технология ATM допускает два варианта определения параметров QoS: первый – непосредственное задание их каждым приложением, второй – назначение их по умолчанию в зависимости от типа трафика. Последний способ упрощает задачу разработчика приложения, так как в этом случае выбор максимальных значений задержки доставки ячеек и вариации задержек перекладывается на плечи администратора сети.
няет коммутацию по номеру виртуального соединения, который в технологии ATM разбит на две части – идентификатор виртуального пути (Virtual Path Identifier, VPI) и идентификатор виртуального канала (Virtual Channel Identifier, VCI). Кроме этой основной задачи протокол ATM выполняет ряд функций по контролю за соблюдением трафик-контракта со стороны пользователя сети, маркировке ячеекнарушителей, отбрасыванию ячеекнарушителей при перегрузке сети, а также управлению потоком ячеек для повышения производительности сети (естественно, при соблюдении условий трафик-контракта для всех виртуальных соединений). Протокол ATM работает с ячейками следующего формата. Поле Управление потоком (Generic Flow Control) используется только при взаимодействии конечного узла и первого коммутатора сети. В настоящее время его точные функции не определены. Поля Идентификатор виртуального пути (VitualPath Identifier, VPI) и Иден-
Самостоятельно обеспечить требуемые параметры трафика и QoS протоколы AAL не могут. Для выполнения соглашений трафик-контракта требуется согласованная работа коммутаторов сети вдоль всего виртуального соединения. Эта работа выполняется протоколом ATM, обеспечивающим передачу ячеек различных виртуальных соединений с заданным уровнем качества обслуживания.
тификатор виртуального канала (Vitual Channel Identifier, VCI) занимают соответственно 1 и 2 байта. Эти поля задают номер виртуального соединения, разделенный на старшую (VPI) и младшую (VCI) части. Поле Идентификатор типа данных (Payload Type Identifier, PTI) состоит из трех бит и задает тип данных, переносимых ячейкой, – пользовательские или управляющие (например, управляющие установлением виртуального соединения). Кроме того, один бит этого поля используется для указания перегрузки в сети – он называется Explicit Congestion Forward Identifier, EFCI – и играет ту же роль, что бит FECN в технологии frame relay, то есть передает информацию о перегрузке по направлению потока данных. Поле Приоритет потери кадра (Cell Loss Priority, CLP) играет в данной технологии ту же роль, что и поле DE в технологии frame relay – в нем комму-
Протокол ATM Протокол ATM занимает в стеке протоколов ATM примерно то же место, что протокол IP в стеке TCP/IP или протокол LAP-F в стеке протоколов технологии frame relay. Протокол ATM занимается передачей ячеек через коммутаторы при установленном и настроенном виртуальном соединении, то есть на основании готовых таблиц коммутации портов. Протокол ATM выпол-
№4(5), апрель 2003
таторы ATM отмечают ячейки, которые нарушают соглашения о параметрах качества обслуживания, чтобы удалить их при перегрузках сети. Таким образом, ячейки с CLP=0 являются для сети высокоприоритетными, а ячейки с CLP=1 – низкоприоритетными. Поле Управление ошибками в заголовке (Header Error Control, НЕС) содержит контрольную сумму, вычисленную для заголовка ячейки. Контрольная сумма вычисляется с помощью техники корректирующих кодов Хэмминга, поэтому она позволяет не только обнаруживать ошибки, но и исправлять все одиночные ошибки, а также некоторые двойные. Поле НЕС обеспечивает не только обнаружение и исправление ошибок в заголовке, но и нахождение границы начала кадра в потоке байтов кадров SDH, которые являются предпочтительным физическим уровнем технологии ATM, или же в потоке бит физического уровня, основанного на ячейках. Указателей, позволяющих в поле данных кадра STS-n (STM-n) технологии SONET/SDH обнаруживать границы ячеек ATM (подобных тем указателям, которые используются для определения, например, границ виртуальных контейнеров подканалов Т1/Е1), не существует. Поэтому коммутатор ATM вычисляет контрольную сумму для последовательности из 5 байт, находящихся в поле данных кадра STM-n, и если вычисленная контрольная сумма говорит о корректности заголовка ячейки ATM, первый байт становится границей ячейки. Если же это не так, то происходит сдвиг на один байт и операция продолжается. Таким образом, технология ATM выделяет асинхронный поток ячеек ATM в синхронных кадрах SDH или потоке бит физического уровня, основанного на ячейках.
Формат ячейки ATM Рассмотрим методы коммутации ячеек ATM на основе пары чисел VPI/VCI. Коммутаторы ATM могут работать в двух режимах – коммутации виртуального пути и коммутации виртуального канала. В первом режиме коммутатор выполняет продвижение ячейки только на основании значения поля VPI, а значение поля VCI он игнорирует. Обычно так работают магистральные
65
администрирование коммутаторы территориальных сетей. Они доставляют ячейки из одной сети пользователя в другую на основании только старшей части номера виртуального канала, что соответствует идее агрегирования адресов. В результате один виртуальный путь соответствует целому набору виртуальных каналов, коммутируемых как единое целое. После доставки ячейки в локальную сеть ATM ее коммутаторы начинают коммутировать ячейки с учетом как VPI, так и VCI, но при этом им хватает для коммутации только младшей части номера виртуального соединения, так что фактически они работают с VCI, оставляя VPI без изменения. Последний режим называется режимом коммутации виртуального канала. Подход здесь аналогичен подходу в сети ISDN – для установления соединения разработан отдельный протокол Q.2931, который весьма условно можно отнести к сетевому уровню. Этот протокол во многом похож на протоколы Q.931 и Q.933 (даже номером), но в него внесены, естественно, изменения, связанные с наличием нескольких классов трафика и дополнительных параметров качества обслуживания. Протокол Q.2931 опирается на достаточно сложный протокол канального уровня SSCOP, который обеспечивает надежную передачу пакетов Q.2931 в своих кадрах. В свою очередь, протокол SSCOP работает поверх протокола AAL5, который необходим для разбиения кадров SSCOP на ячейки ATM и сборки этих ячеек в кадры при доставке кадра SSCOP в коммутатор назначения. Виртуальные соединения, образованные с помощью протокола Q.2931, бывают симплексными (однонаправленными) и дуплексными. Протокол Q.2931 позволяет также устанавливать виртуальные соединения типа “один-к-одному” (point-to-point) и “один-ко-многим” (point-to-multipoint). Первый случай поддерживается во всех технологиях, основанных на виртуальных каналах, а второй характерен для технологии ATM и является аналогом мультивещания, но с одним ведущим вещающим узлом. При установлении соединения “один-ко-многим” ведущим считается узел, который является инициатором этого соедине-
66
ния. Сначала этот узел устанавливает виртуальное соединение всего с одним узлом, а затем добавляет к соединению с помощью специального вызова по одному новому члену. Ведущий узел становится вершиной дерева соединения, а остальные узлы – листьями этого дерева. Сообщения, которые посылает ведущий узел, принимают все листья соединения, но сообщения, которые посылает какой-либо лист (если соединение дуплексное), принимает только ведущий узел. Пакеты протокола Q.2931, предназначенные для установления коммутируемого виртуального канала, имеют те же названия и назначение, что и пакеты протокола Q.933, рассмотренные выше при изучении технологии frame relay, но структура их полей, естественно, другая. Адресом конечного узла в коммутаторах ATM является 20-байтный адрес. Этот адрес может иметь различный формат, описываемый стандартом ISO 7498. При работе в публичных сетях используется адрес стандарта Е.164, при этом 1 байт составляет AFI, 8 байт занимает IDI – основная часть адреса Е.164 (15 цифр телефонного номера), а остальные 11 байт части DSP (Domain Specific Part). При работе в частных сетях ATM обычно применяется формат адреса, соответствующий домену международных организаций, причем в качестве международной организации выступает ATM Forum. В этом случае поле IDI занимает 2 байта, которые содержат код ATM Forum, данный ISO, а структура остальной части DSP соответствует описанной выше за исключением того, что поле HO-DSP занимает не 4, а 10 байт. Адрес ESI присваивается конечному узлу на предприятии-изготовителе в соответствии с правилами IEEE, то есть 3 первых байта содержат код предприятия, а остальные три байта – порядковый номер, за уникальность которого отвечает данное предприятие. Конечный узел при подключении к коммутатору ATM выполняет так называемую процедуру регистрации. При этом конечный узел сообщает коммутатору свой ESI-адрес, а коммутатор сообщает конечному узлу старшую часть адреса, то есть номер сети, в которой работает узел.
Кроме адресной части пакет CALL SETUP протокола Q.2931, с помощью которого конечный узел запрашивает установление виртуального соединения, включает также части, описывающие параметры трафика и требования QoS. При поступлении такого пакета коммутатор должен проанализировать эти параметры и решить, достаточно ли у него свободных ресурсов производительности для обслуживания нового виртуального соединения. Если да, то новое виртуальное соединение принимается и коммутатор передает пакет CALL SETUP дальше в соответствии с адресом назначения и таблицей маршрутизации, а если нет, то запрос отвергается.
Услуги протокола ATM и управление трафиком Для поддержания требуемого качества обслуживания различных виртуальных соединений и рационального использования ресурсов в сети на уровне протокола ATM реализовано несколько служб, предоставляющих услуги различных категорий (service categories) по обслуживанию пользовательского трафика. Эти службы являются внутренними службами сети ATM, они предназначены для поддержания пользовательского трафика различных классов совместно с протоколами AAL. Но в отличие от протоколов AAL, которые работают в конечных узлах сети, данные службы распределены по всем коммутаторам сети. Услуги этих служб разбиты на категории, которые в общем соответствуют классам трафика, поступающим на вход уровня AAL конечного узла. Услуги уровня ATM заказываются конечным узлом через интерфейс UNI с помощью протокола Q.2931 при установлении виртуального соединения. Как и при обращении к уровню AAL, при заказе услуги необходимо указать категорию услуги, а также параметры трафика и параметры QoS. Эти параметры берутся из аналогичных параметров уровня AAL или же определяются по умолчанию в зависимости от категории услуги. Всего на уровне протокола ATM определено пять категорий услуг, которые поддерживаются одноименными службами:
администрирование CBR – услуги для трафика с посто
янной битовой скоростью; rtVBR – услуги для трафика с переменной битовой скоростью, требующего соблюдения средней скорости передачи данных и синхронизации источника и приемника; nrtVBR – услуги для трафика с переменной битовой скоростью, требующего соблюдения средней скорости передачи данных и не требующего синхронизации источника и приемника; ABR – услуги для трафика с переменной битовой скоростью, требующего соблюдения некоторой минимальной скорости передачи данных и не требующего синхронизации источника и приемника; UBR – услуги для трафика, не предъявляющего требований к скорости передачи данных и синхронизации источника и приемника.
Названия большинства категорий услуг совпадают с названием типов пользовательского трафика, для обслуживания которого они разработаны, но необходимо понимать, что сами службы уровня ATM и их услуги – это внутренние механизмы сети ATM, которые экранируются от приложения уровнем AAL. Услуги категории CBR предназначены для поддержания трафика синхронных приложений – голосового, эмуляции цифровых выделенных каналов и т. п. Когда приложение устанавливает соединение категории CBR, оно заказывает пиковую скорость трафика ячеек PCR, являющуюся максимальной скоростью, которую может поддерживать соединение без риска потерять ячейку, а также параметры QoS: величины максимальной задержки ячеек CTD, вариации задержки ячеек CDV и максимальной доли потерянных ячеек CLR. Затем данные передаются по этому соединению с запрошенной скоростью – не с большей и, в большинстве случаев, не меньшей, хотя уменьшение скорости приложением возможно, например, при передаче компрессированного голоса с помощью услуги категории CBR. Любые ячейки, передаваемые станцией с большей скоростью, контролируются первым коммутатором сети и помечаются признаком
№4(5), апрель 2003
CLP-1. При перегрузках сети они могут просто отбрасываться сетью. Ячейки, которые запаздывают и не укладываются в интервал, оговоренный параметром вариации задержки CDV, также считаются мало значащими для приложения и отмечаются признаком низкого приоритета CLP-1. Для соединений CBR нет ограничений на некоторую дискретность заказа скорости PCR, как, например, в каналах Т1/Е1, где скорость должна быть кратна 64 Кбит/с. По сравнению со службой CBR, службы VBR требуют более сложной процедуры заказа соединения между сетью и приложением. В дополнение к пиковой скорости PCR приложение VBR заказывает еще и два других параметра: длительно поддерживаемую скорость – SCR, которая представляет собой среднюю скорость передачи данных, разрешенную приложению, а также максимальный размер пульсации – MBS. Максимальный размер пульсации измеряется в количестве ячеек ATM. Пользователь может превышать скорость вплоть до величины PCR, но только на короткие периоды времени, в течение которых передается объем данных, не превышающий MBS. Этот период времени называется Burst Tolerance, ВТ – терпимость к пульсации. Сеть вычисляет этот период как производный от трех заданных значений PCR, SCR и MBS. Если скорость PCR наблюдается в течение периода времени, большего чем ВТ, то ячейки помечаются как нарушители – устанавливается признак CLP-1. Для услуг категории rtVBR задаются и контролируются те же параметры QoS, что и для услуг категории CBR, а услуги категории nrtVBR ограничиваются поддержанием параметров трафика. Сеть также поддерживает для обеих категорий услуг VBR определенный максимальный уровень доли потерянных ячеек CLR, который либо задается явно при установлении соединения, либо назначается по умолчанию в зависимости от класса трафика. Для контроля параметров трафика и QoS в технологии ATM применяется так называемый обобщенный алгоритм контроля скорости ячеек – Generic Cell Rate Algorithm, который может проверять соблюдение пользо-
вателем и сетью таких параметров, как PCR, CDV, SCR, ВТ, CTD и CDV. Он работает по модифицированному алгоритму “дырявого ведра”, применяемому в технологии frame relay. Для многих приложений, которые могут быть чрезвычайно “взрывными” в отношении интенсивности трафика, невозможно точно предсказать параметры трафика, оговариваемые при установлении соединения. В отличие от CBR и обеих служб VBR, служба UBR не поддерживает ни параметры трафика, ни параметры качества обслуживания. Служба UBR предлагает только доставку “по возможности” без каких-либо гарантий. Разработанная специально для обеспечения возможности превышения полосы пропускания, служба UBR представляет собой частичное решение для тех непредсказуемых “взрывных” приложений, которые не готовы согласиться с фиксацией параметров трафика. Главными недостатками услуг UBR являются отсутствие управления потоком данных и неспособность принимать во внимание другие типы трафика. Несмотря на перегрузку сети, соединения UBR будут продолжать передачу данных. Коммутаторы сети могут буферизовать некоторые ячейки поступающего трафика, но в некоторый момент буферы переполняются, и ячейки теряются. А так как для соединений UBR не оговаривается никаких параметров трафика и QoS, то их ячейки отбрасываются в первую очередь. Служба ABR подобно службе UBR предоставляет возможность превышения полосы пропускания, но благодаря технике управления трафиком при перегрузке сети она дает некоторые гарантии сохранности ячеек. ABR – это первый тип служб уровня ATM, который действительно обеспечивает надежный транспорт для пульсирующего трафика за счет того, что может находить неиспользуемые интервалы в общем трафике сети и заполнять их своими ячейками, если другим категориям служб эти интервалы не нужны. Как и в службах CBR и VBR, при установлении соединения категории ABR оговаривается значение пиковой скорости PCR. Однако соглашение о пределах изменения задержки переда-
67
администрирование чи ячеек или о параметрах пульсации не заключается. Вместо этого «сеть и конечный узел заключают соглашение о требуемой минимальной скорости передачи MCR. Это гарантирует приложению, работающему в конечном узле, небольшую пропускную способность, обычно минимально необходимую для того, чтобы приложение работало. Конечный узел соглашается не передавать данные со скоростью выше пиковой, то есть PCR, а сеть соглашается всегда обеспечивать минимальную скорость передачи ячеек MCR. Если при установлении соединения ABR не задаются значения максимальной и минимальной скорости, то по умолчанию считается, что PCR совпадает со скоростью линии доступа станции к сети, a MCR считается равной нулю. Трафик соединения категории ABR получает гарантированное качество услуг в отношении доли потерянных ячеек и пропускной способности. Что касается задержек передачи ячеек, то хотя сеть и старается свести их к минимуму, но гарантий по этому параметру не дает. Следовательно, служба ABR не предназначена для приложений реального времени, а предназначена для приложений, в которых поток данных не очень чувствителен к задержкам в передаче. При передаче трафика CBR, VBR и UBR явное управление перегрузками в сети отсутствует. Вместо этого используется механизм отбрасывания ячеек-нарушителей, а узлы, пользующиеся услугами CBR и VBR, стараются не нарушать условия контракта под угрозой потери ячеек, поэтому они обычно не пользуются дополнительной пропускной способностью, даже если она в данный момент доступна в сети. Служба ABR позволяет воспользоваться резервами пропускной способности сети, так как сообщает конечному узлу о наличии в данный момент избыточной пропускной способности с помощью механизма обратной связи. Этот же механизм может помочь службе ABR снизить скорость передачи данных конечным узлом в сеть (вплоть до минимального значения MCR), если сеть испытывает перегрузку. Узел, пользующийся услугами ABR, должен периодически посылать в сеть
68
наряду с ячейками данных специальные служебные ячейки управления ресурсами – Resource Management, RM. Ячейки RM, которые узел отправляет вдоль потока данных, называются прямыми ячейками RM – Forward Recource Management (FRM), а ячейки, которые идут в обратном по отношению к потоку данных направлении, называются обратными ячейками RM – Backward Recource Management (BRM). Существует несколько петель обратной связи. Самая простая петля обратной связи – между конечными станциями. При ее наличии коммутатор сети извещает конечную станцию о перегрузке с помощью специального флага в поле прямого управления перегрузками (флаг EFCI) ячейки данных, переносимой протоколом ATM. Затем конечная станция посылает через сеть сообщение, содержащееся в специальной ячейке управления BRM исходной станции, говоря ей о необходимости уменьшить скорость посылки ячеек в сеть. В этом способе конечная станция несет основную ответственность за управление потоком, а коммутаторы играют пассивную роль в петле обратной связи, только уведомляя станциюотправитель о перегрузке. Такой простой способ имеет несколько очевидных недостатков. Конечная станция не узнает из сообщения BRM, на какую величину нужно уменьшить скорость передачи данных в сеть. Поэтому она просто понизит скорость до минимальной величины MCR, хотя, возможно, это и необязательно. Кроме того, при большой протяженности сети коммутаторы должны продолжать буферизовать данные все время, пока уведомление о перегрузке будет путешествовать по сети, а для глобальных сетей это время может быть достаточно большим, и буферы могут переполниться, так что требуемый эффект достигнут не будет. Разработаны и более сложные схемы управления потоком, в которых коммутаторы играют более активную роль, а узел-отправитель узнает более точно о возможной в данный момент скорости отправки данных в сеть. В первой схеме узел-источник посылает в ячейке FRM явное значение скорости передачи данных в сеть, ко-
торую он хотел бы поддерживать в данное время. Каждый коммутатор, через который проходит по виртуальному пути это сообщение, может уменьшить запрашиваемую скорость до некоторой величины, которую он может поддерживать в соответствии с имеющимися у него свободными ресурсами (или оставить запрашиваемую скорость без изменения). Узел назначения, получив ячейку FRM, превращает ее в ячейку BRM и отправляет в обратном направлении, причем он тоже может уменьшить запрашиваемую скорость. Получив ответ в ячейке BRM, узел-источник точно узнает, какая скорость отправки ячеек в сеть для него в данный момент доступна. Во второй схеме каждый коммутатор сети может работать как узел-источник и узел назначения. Как узелисточник он может сам генерировать ячейки FRM и отправлять их по имеющимся виртуальным каналам. Как узел назначения он может отправлять на основе получаемых ячеек FRM ячейки BRM в обратном направлении. Такая схема является более быстродействующей и полезной в протяженных территориальных сетях. Как видно из описания, служба ABR предназначена не только для прямого поддержания требований к обслуживанию конкретного виртуального соединения, но и для более рационального распределения ресурсов сети между ее абонентами, что в конечном итоге также приводит к повышению качества обслуживания всех абонентов сети. Коммутаторы сети ATM используют различные механизмы для поддержания требуемого качества услуг. Кроме описанных в стандартах ITU-T и ATM Forum механизмов заключения соглашения на основе параметров трафика и параметров QpS, а затем отбрасывания ячеек, не удовлетворяющих условиям соглашения, практически все производители оборудования ATM реализуют в своих коммутаторах несколько очередей ячеек, обслуживаемых с различными приоритетами. Стратегия приоритетного обслуживания трафика основана на категориях услуг каждого виртуального соединения. До принятия спецификации ABR в большинстве коммутаторов ATM была реализована простая одноуров-
администрирование невая схема обслуживания, которая давала трафику CBR первый приоритет, трафику VBR второй, а трафику UBR – третий. При такой схеме комбинация CBR и VBR может потенциально заморозить трафик, обслуживаемый другим классом служб. Такая схема не будет правильно работать с трафиком ABR, так как не обеспечит его требования к минимальной скорости передачи ячеек. Для обеспечения этого требования должна быть выделена некоторая гарантированная полоса пропускания. Чтобы поддерживать службу ABR, коммутаторы ATM должны реализовать двухуровневую схему обслуживания, которая бы удовлетворяла требованиям CBR, VBR и ABR. По этой схеме коммутатор предоставляет некоторую часть своей пропускной способности каждому классу служб. Трафик CBR получает часть пропускной способности, необходимую для поддержания пиковой скорости PCR, трафик VBR получает часть пропускной способности, необходимую для поддержания средней скорости SCR, а трафик ABR получает часть пропускной способности, достаточную для обеспечения требования минимальной скорости ячеек MCR. Это гарантирует, что каждое соединение может работать без потерь ячеек и не будет доставлять ячейки ABR за счет трафика CBR или VBR. На втором уровне этого алгоритма трафик CBR и VBR может забрать всю оставшуюся пропускную способность сети, если это необходимо, так как соединения ABR уже получили свою минимальную пропускную способность, которая им гарантировалась.
Передача трафика IP через сети ATM Технология ATM привлекает к себе общее внимание, так как претендует на роль всеобщего и очень гибкого транспорта, на основе которого строятся другие сети. И хотя технология ATM может использоваться непосредственно для транспортировки сообщений протоколов прикладного уровня, пока она чаще переносит пакеты других протоколов канального и сетевого уровней (Ethernet, IP, IPX, frame relay, X.25), сосуществуя с ними, а не полно-
№4(5), апрель 2003
стью заменяя. Поэтому протоколы и спецификации, которые определяют способы взаимодействия технологии ATM с другими технологиями, очень важны для современных сетей. А так как протокол IP является на сегодня основным протоколом построения составных сетей, то стандарты работы IP через сети ATM являются стандартами, определяющими взаимодействие двух наиболее популярных технологий сегодняшнего дня. Протокол Classical IP (RFC 1577) является первым (по времени появления) протоколом, определившим способ работы интерсети IP в том случае, когда одна из промежуточных сетей работает по технологии ATM. Из-за классической концепции подсетей протокол и получил свое название – Classical. Одной из основных задач, решаемых протоколом Classical IP, является традиционная для IP-сетей задача – поиск локального адреса следующего маршрутизатора или конечного узла по его IP-адресу, то есть задача, возлагаемая в локальных сетях на протокол ARP. Поскольку сеть ATM не поддерживает широковещательность, традиционный для локальных сетей способ широковещательных ARP-запросов здесь не работает. Технология ATM, конечно, не единственная технология, в которой возникает такая проблема, – для обозначения таких технологий даже ввели специальный термин – «нешироковещательные сети с множественным доступом» (NonBroadcast networks with Multiple Access, NBMA). К сетям NBMA относятся, в частности, сети Х.25 и frame relay. В общем случае для нешироковещательных сетей стандарты TCP/IP определяют только ручной способ построения ARP-таблиц, однако для технологии ATM делается исключение – для нее разработана процедура автоматического отображения IP-адресов на локальные адреса. Такой особый подход к технологии ATM объясняется следующими причинами. Сети NBMA (в том числе Х.25 и frame relay) используются, как правило, как транзитные глобальные сети, к которым подключается ограниченное число маршрутизаторов, а для небольшого числа маршрутизаторов можно задать ARPтаблицу вручную. Технология ATM от-
личается тем, что она применяется для построения не только глобальных, но и локальных сетей. В последнем случае размерность ARP-таблицы, которая должна содержать записи и о пограничных маршрутизаторах, и о множестве конечных узлов, может быть очень большой. К тому же, для крупной локальной сети характерно постоянное изменение состава узлов, а значит, часто возникает необходимость в корректировке таблиц. Все это делает ручной вариант решения задачи отображения адресов для сетей ATM мало пригодным. В соответствии со спецификацией Classical IP одна сеть ATM может быть представлена в виде нескольких IPподсетей, так называемых логических подсетей (Logical IP Subnet, LIS). Все узлы одной LIS имеют общий адрес сети. Как и в классической IP-сети, весь трафик между подсетями обязательно проходит через маршрутизатор, хотя и существует принципиальная возможность передавать его непосредственно через коммутаторы ATM, на которых построена сеть ATM. Маршрутизатор имеет интерфейсы во всех LIS, на которые разбита сеть ATM. В отличие от классических подсетей маршрутизатор может быть подключен к сети ATM одним физическим интерфейсом, которому присваивается несколько IP-адресов в соответствии с количеством LIS в сети. Решение о введении логических подсетей связано с необходимостью обеспечения традиционного разделения большой сети ATM на независимые части, связность которых контролируется маршрутизаторами, как к этому привыкли сетевые интеграторы и администраторы. Решение имеет и очевидный недостаток – маршрутизатор должен быть достаточно производительным для передачи высокоскоростного трафика ATM между логическими подсетями, в противном случае он станет узким местом сети. В связи с повышенными требованиями по производительности, предъявляемыми сетями ATM к маршрутизаторам, многие ведущие производители разрабатывают или уже разработали модели маршрутизаторов с общей производительностью в несколько десятков миллионов пакетов в секунду. Все конечные узлы конфигуриру-
69
администрирование ются традиционным образом – для них задается их собственный IP-адрес, маска и IP-адрес маршрутизатора по умолчанию. Кроме того, задается еще один дополнительный параметр – адрес ATM (или номер VPI/VCI для случая использования постоянного виртуального канала, то есть PVC) так называемого сервера ATMARP. Введение центрального сервера, который поддерживает общую базу данных для всех узлов сети, – это типичный прием для работы через нешироковещательную сеть. Этот прием используется во многих протоколах, в частности в протоколе LAN Emulation, рассматриваемом далее. Каждый узел использует адрес ATM сервера ATMARP, чтобы выполнить обычный запрос ARP. Этот запрос имеет формат, очень близкий к формату запроса протокола ARP из стека TCP/IP. Длина аппаратного адреса в нем определена в 20 байт, что соответствует длине адреса ATM. В каждой логической подсети имеется свой сервер ATMARP, так как узел может обращаться без посредничества маршрутизатора только к узлам своей подсети. Обычно роль сервера ATMARP выполняет маршрутизатор, имеющий интерфейсы во всех логических подсетях. При поступлении первого запроса ARP от конечного узла сервер сначала направляет ему встречный инверсный запрос ATMARP, чтобы выяснить IP- и ATM-адреса этого узла. Этим способом выполняется регистрация каждого узла в сервере ATMARP, и сервер получает возможность автоматически строить базу данных соответствия IP- и ATM-адресов. Затем сервер пытается выполнить запрос ATMARP-узла путем просмотра своей базы. Если искомый узел уже зарегистрировался в ней и он принадлежит той же логической подсети, что и запрашивающий узел, то сервер отправляет в качестве ответа запрашиваемый адрес. В противном случае дается негативный ответ (такой тип ответа в обычном широковещательном варианте протокола ARP не предусматривается). Конечный узел, получив ответ ARP, узнает ATM-адрес своего соседа по логической подсети и устанавливает с ним коммутируемое виртуальное со-
70
единение. Если же он запрашивал ATM-адрес маршрутизатора по умолчанию, то он устанавливает с ним соединение, чтобы передать IP-пакет в другую сеть. Для передачи IP-пакетов через сеть ATM спецификация Classical IP определяет использование протокола уровня адаптации AAL5, при этом спецификация ничего не говорит ни о параметрах трафика и качества обслуживания, ни о требуемой категории услуг CBR, rtVBR, nrtVBR или UBR.
ATM + LAN Технология ATM разрабатывалась сначала как “вещь в себе”, без учета того факта, что в существующие технологии сделаны большие вложения и поэтому никто не станет сразу отказываться от установленного и работающего оборудования, даже если появляется новое, более совершенное. Это обстоятельство оказалось не столь важным для территориальных сетей, которые в случае необходимости могли предоставить свои оптоволоконные каналы для построения сетей ATM. Учитывая, что стоимость высокоскоростных оптоволоконных каналов, проложенных на большие расстояния, часто превышает стоимость остального сетевого оборудования, переход на новую технологию ATM, связанный с заменой коммутаторов, во многих случаях оказывался экономически оправданным. Для локальных сетей, в которых замена коммутаторов и сетевых адаптеров равнозначна созданию новой сети, переход на технологию ATM мог быть вызван только весьма серьезными причинами. Гораздо привлекательнее полной замены существующей локальной сети новой сетью ATM выглядела возможность “постепенного” внедрения технологии ATM в существующую на предприятии сеть. При таком подходе фрагменты сети, работающие по новой технологии ATM, могли бы мирно сосуществовать с другими частями сети, построенными на основе традиционных технологий, таких как Ethernet или FDDI, улучшая характеристики сети там, где это нужно, и оставляя сети рабочих групп или отделов в прежнем виде. Применение маршрутизаторов IP, реализующих
протокол Classical IP, решает эту проблему, но такое решение не всегда устраивает предприятия, пользующиеся услугами локальных сетей, так как, вопервых, требуется обязательная поддержка протокола IP во всех узлах локальных сетей, а во-вторых, требуется установка некоторого количества маршрутизаторов, что также не всегда приемлемо. Отчетливо ощущалась необходимость способа согласования технологии ATM с технологиями локальных сетей без привлечения сетевого уровня. В ответ на такую потребность ATM Forum разработал спецификацию, называемую LAN emulation, LANE (то есть эмуляция локальных сетей), которая призвана обеспечить совместимость традиционных протоколов и оборудования локальных сетей с технологией ATM. Эта спецификация обеспечивает совместную работу этих технологий на канальном уровне. При таком подходе коммутаторы ATM работают в качестве высокоскоростных коммутаторов магистрали локальной сети, обеспечивая не только скорость, но и гибкость соединений коммутаторов ATM между собой, поддерживающих произвольную топологию связей, а не только древовидные структуры. Спецификация LANE определяет способ преобразования кадров и адресов МАС-уровня традиционных технологий локальных сетей в ячейки и коммутируемые виртуальные соединения SVC технологии ATM, а также способ обратного преобразования. Всю работу по преобразованию протоколов выполняют специальные компоненты, встраиваемые в обычные коммутаторы локальных сетей, поэтому ни коммутаторы ATM, ни рабочие станции локальных сетей не замечают того, что они работают с чуждыми им технологиями. Такая прозрачность была одной из главных целей разработчиков спецификации LANE. Так как эта спецификация определяет только канальный уровень взаимодействия, то с помощью коммутаторов ATM и компонентов эмуляции LAN можно образовать только виртуальные сети, называемые здесь эмулируемыми сетями, а для их соединения нужно использовать обычные маршрутизаторы.
администрирование Использование технологии ATM Технология ATM расширяет свое присутствие в локальных и глобальных сетях не очень быстро, но неуклонно. Число сетей, выполненных по этой технологии, ежегодно увеличивается на 20-30 %. В локальных сетях технология ATM применяется обычно на магистралях, где востребованы такие ее качества, как масштабируемая скорость (выпускаемые сегодня корпоративные коммутаторы ATM поддерживают на своих портах скорости 155 и 622 Мбит/с), качество обслуживания (для этого нужны приложения, которые умеют запрашивать нужный класс обслуживания), петлевидные связи (которые позволяют повысить пропускную способность и обеспечить резервирование каналов связи). Петлевидные связи поддерживаются в силу того, что ATM – это технология с маршрутизацией пакетов, запрашивающих установление соединений, а значит, таблица маршрутизации может эти связи учесть – либо за счет ручного труда администратора, либо за счет протокола маршрутизации PNNI. Основной соперник технологии ATM в локальных сетях – технология Gigabit Ethernet. Она превосходит ATM в скорости передачи данных – 1000 Мбит/с по сравнению с 622 Мбит/с, а также в затратах на единицу скорости. Там, где коммутаторы ATM используются только как высокоскоростные устройства, а возможности поддержки разных типов трафика игнорируются, технологию ATM, очевидно, заменит технология Gigabit Ethernet. Там же, где качество обслуживания действительно важно (видеоконференции, трансляция телевизионных передач и т. п.), технология ATM останется. Для объединения настольных компьютеров технология ATM, вероятно, еще долго не будет использоваться, так как здесь очень серьезную конкуренцию ей составляет технология Fast Ethernet. В глобальных сетях ATM применяется там, где сеть frame relay не справляется с большими объемами трафика, и там, где нужно обеспечить низкий уровень задержек, необходимый для передачи информации реального времени. Сегодня основной потребитель тер-
№4(5), апрель 2003
риториальных коммутаторов ATM – это Internet. Коммутаторы ATM используются как гибкая среда коммутации виртуальных каналов между IP-маршрутизаторами, которые передают свой трафик в ячейках ATM. Сети ATM оказались более выгодной средой соединения IP-маршрутизаторов, чем выделенные каналы SDH, так как виртуальный канал ATM может динамически перераспределять свою пропускную способность между пульсирующим трафиком клиентов IP-сетей. Примером магистральной сети ATM крупного поставщика услуг является сеть компании UUNET – одного из ведущих поставщиков услуг Internet Северной Америки. И напоследок хотелось бы сделать некоторые выводы, касающиеся рассматириваемого нами материала на протяжении цикла “АБСОЛЮТНО ВСЕ О .....”, итак. Хотя технология ATM разрабатывалась для одновременной передачи данных компьютерных и телефонных сетей, передача голоса по каналам CBR для сетей ATM составляет всего 5 % от общего трафика, а передача видеоинформации – 10 %. Телефонные компании пока предпочитают передавать свой трафик непосредственно по каналам SDH, не довольствуясь гарантиями качества обслуживания ATM. Кроме того, технология ATM пока имеет недостаточно стандартов для плавного включения в существующие телефонные сети, хотя работы в этом направлении идут. Что же касается совместимости ATM с технологиями компьютерных сетей, то разработанные в этой области стандарты вполне работоспособны и удовлетворяют пользователей и сетевых интеграторов. К технологиям глобальных сетей с коммутацией пакетов относятся сети Х.25, frame relay, SMDS, ATM и TCP/IP. Все эти сети, кроме сетей TCP/IP, используют маршрутизацию пакетов, основанную на виртуальных каналах между конечными узлами сети. Сети TCP/IP занимают особое положение среди технологий глобальных сетей, так как они выполняют роль технологии объединения сетей любых типов, в том числе и сетей всех остальных глобальных технологий. Таким образом, сети TCP/IP относятся к бо-
лее высокоуровневым технологиям, чем технологии собственно глобальных сетей. Техника виртуальных каналов заключается в разделении операций маршрутизации и коммутации пакетов. Первый пакет таких сетей содержит адрес вызываемого абонента и прокладывает виртуальный путь в сети, настраивая промежуточные коммутаторы. Остальные пакеты проходят по виртуальному каналу в режиме коммутации на основании номера виртуального канала, который является локальным адресом для каждого порта каждого коммутатора. Техника виртуальных каналов имеет преимущества и недостатки по сравнению с техникой маршрутизации каждого пакета, характерной для сетей IP или IPX. Преимуществами являются: ускоренная коммутация пакетов по номеру виртуального канала, а также сокращение адресной части пакета, а значит, и избыточности заголовка. К недостаткам следует отнести невозможность распараллеливания потока данных между двумя абонентами по параллельным путям, а также неэффективность установления виртуального пути для кратковременных потоков данных Сети Х.25 относятся к одной из наиболее старых и отработанных технологий глобальных сетей. Трехуровневый стек протоколов сетей Х.25 хорошо работает на ненадежных зашумленных каналах связи, исправляя ошибки и управляя потоком данных на канальном и пакетном уровнях. Сети Х.25 поддерживают групповое подключение к сети простых алфавитно-цифровых терминалов за счет включения в сеть специальных устройств PAD, каждое из которых представляет собой особый вид терминального сервера. На надежных волоконно-оптических каналах технология Х.25 становится избыточной и неэффективной, так как значительная часть работы ее протоколов ведется “вхолостую”. Сети frame relay работают на основе весьма упрощенной, по сравнению с сетями Х.25, технологией, которая передает кадры только по протоколу канального уровня – протоколу LAP-F. Кадры при передаче через коммутатор не подвергаются преобразованиям, из-
71
администрирование за чего технология и получила свое название. Важной особенностью технологии frame relay является концепция резервирования пропускной способности при прокладке в сети виртуального канала. Сети frame relay создавались специально для передачи пульсирующего компьютерного трафика, поэтому при резервировании пропускной способности указывается средняя скорость трафика CIR и согласованный объем пульсаций Вс. Сеть frame relay гарантирует поддержку заказанных параметров качества обслуживания за счет предварительного расчета возможностей каждого коммутатора, а также отбрасывания кадров, которые нарушают соглашение о трафике, то есть посылаются в сеть слишком интенсивно. Большинство первых сетей frame
72
relay поддерживали только службу постоянных виртуальных каналов, а служба коммутируемых виртуальных каналов стала применяться на практике только недавно. Технология ATM является дальнейшим развитием идей предварительного резервирования пропускной способности виртуального канала, реализованных в технологии frame relay. Технология ATM поддерживает основные типы трафика, существующие у абонентов разного типа: трафик с постоянной битовой скоростью CBR, характерный для телефонных сетей и сетей передачи изображения, трафик с переменной битовой скоростью VBR, характерный для компьютерных сетей, а также для передачи компрессированного голоса и изображения. Для каждого типа трафика пользователь может заказать у сети
значения нескольких параметров качества обслуживания – максимальной битовой скорости PCR, средней битовой скорости SCR, максимальной пульсации MBS, а также контроля временных соотношений между передатчиком и приемником, важных для трафика, чувствительного к задержкам. Технология ATM сама не определяет новые стандарты для физического уровня, а пользуется существующими. Основным стандартом для ATM является физический уровень каналов технологий SONET/SDH и PDH. Ввиду того что ATM поддерживает все основные существующие типы трафика, она выбрана в качестве транспортной основы широкополосных цифровых сетей с интеграцией услуг – сетей B-ISDN, которые должны заменить сети ISDN.
безопасность
СЕРГЕЙ ЯРЕМЧУК Операционная система Unix с самого начала задумывалась простой по устройству и безопасной по содержанию. Простота системы заключается в том, что все, что не видит глаз, является файлами, правда разными по содержанию, но пользователь не видит абсолютно никакой разницы между обычным текстовым файлом и файлом, представляющим собой жесткий диск. Жизнь в систему вдыхают процессы. Пользователи имеют определенные права доступа, на основании которых решается вопрос о том, может ли процесс, имеющий определенные атрибуты (владелец, группа), открыть файл для работы с ним. Но такое упрощение имеет и свои видимые недостатки. Так, важные системные файлы получаются фактически не защищенными. Почему? Как правило, в грамотно настроенной системе такие файлы может изменять и удалять только суперпользователь. Но хорошо, когда это именно наш системный администратор, а если нет? Я считаю, что взломать аккаунт root в принципе возможно, но есть гораздо более
74
эффективный и быстрый способ получить доступ к системным файлам. Так, известно, что большинство демонов (программ, выполняющих запросы пользователей) имеют установленный SUID/SGID-бит. Сущность его заключается в том, чтобы придать процессу, запущенному от имени обычного пользователя, несколько большие права в системе. В качестве примера рассмотрим утилиту passwd, которая позволяет изменить пользователю свой пароль. Все учетные записи и пароли (в зашифрованном виде) хранятся в файлах /etc/passwd и /etc/shadow. Если предоставить право каждому пользователю самолично вносить изменения в эти файлы напрямую, то можете представить, что это будет. Естественно, вам никто и не даст такое право. [sergej@grinder sergej]$ ls -l /etc/passwd /etc/shadow -rw-r--r-- 1 root root 1628 Àâã 13 18:31 /etc/passwd -r-------- 1 root root 1081 Àâã 13 18:31 /etc/shadow
Как видите, все пользователи имеют право только на чтение файла /etc/passwd, а записывать информацию
безопасность может только root (а /etc/shadow, как вы видите, закрыли от всех остальных, чтобы пароли нельзя было подобрать). Теперь смотрим на утилиту passwd: [sergej@grinder sergej]$ ls -l /usr/bin/passwd -r-s--x--x 1 root root 15104 Ìàð 14 03:44 /usr/bin/passwd
Буква «s» означает, что установлен флаг SUID, а владельцем файла является его величество root и теперь, кто бы ни запустил утилиту на выполнение, на время работы программы он временно получает права суперпользователя, т.е. произвести запись в защищенный системный файл. Естественно, утилита должна (и делает это) производить изменение учетной записи только запустившего ее пользователя. Как вы понимаете, требования по безопасности к программам, использующим данный метод, должны быть повышены. Это, наверное, самая большая дыра во всех Unix, потому что найдя ошибку в одной из программ, использующих биты SUID/SGID, можно производить любые действия, не обладая при этом правами суперпользователя. Это свойство использовал нашумевший в 1988 году вирус Морриса. Теперь, получив доступ к такой программе, ничего не мешает переслать файл /etc/passwd себе по электронной почте или убить init, тем самым остановив работу сервера. Но с другой строны, к тому же файлу /etc/passwd при нормальной работе должны обращаться всего две программы: login – при входе пользователя в систему, и уже упоминаемая passwd при смене пароля. Но уж никак не Sendmail. Отсюда получаем, что процессы, запущенные от имени суперпользователя, имеют гораздо больше прав, чем им требуется. С одной стороны, количество SUID/SGID неуклонно уменьшается, но до нуля их количество вряд ли дойдет. Поэтому необходимо иметь способ вручную отрегулировать доступ к некоторым важным системным файлам и каталогам. Еще было бы совсем неплохо расширить имеющуюся модель доступа к файлам – владелец, группа-владелец, остальные и права для каждого – чтение, запись, выполнение. Такая модель, хотя и обладает определенной простотой в реализации, но иногда не обеспечивает гибкости при организации прав доступа в тех случаях, когда есть необходимость задать их персонально для каждого (что отлично реализовано в Windows NT). Итак, задачи поставлены, теперь хотелось бы иметь инструмент для их решения. Таким инструментом является LIDS (Linux Intrusion Detection System), который представляет из себя патч к ядру для осуществления принудительного контроля доступа в ядре, а также инструмент администрирования (lidsadm). Кроме того, LIDS встраивает в ядро механизм предупреждений о каких-либо опасных действиях, а также такую довольно полезную вещь, как детектор сканера портов, дающий сисадмину время на подготовку к отражению атаки. Ведь в большинстве случаев перед проникновением идет «разведка боем». Для установки LIDS необходимо скачать с сайта проекта http://www.lids.org/install.html или с одного из его ftpзеркал утилиту администрирования и патч к ядру. Все
№4(5), апрель 2003
это находится в пакете lids-х.х.х-y.y.y.tar.gz, где х.х.х – номер версии утилиты lids, а y.y.y – номер версии ядра, для которого предназначен патч. Причем поддерживаются и так любимые системными администраторами ядра серии 2.2.х и современные 2.4.х, а также developer ядра серии 2.5.х. Я использовал lids-1.1.2rc4-2.4.19.tar.gz, поэтому с ftp://ftp.kernel.org было взято ядро linux-2.4.19.tar.bz2. Теперь распаковываем два скаченных файла. # bzip2 -cd linux-2.4.19.tar.bz2 | tar -xvf # tar -zxvf lids-1.1.2rc4-2.4.19.tar.gz
Следующим шагом переходим в распакованный каталог с ядром и устанавливаем патч. # cd linux_install_path/linux # patch -p1 < /lids_install_path/lids-1.1.2rc4-2.4.19.patch
В случае если патч установился без проблем, обязательно нужно создать символическую ссылку /usr/src/linux на новый каталог с исходниками ядра. # rm -rf /usr/src/linux # ln -s linux_install_patch/linux /usr/src/linux
Теперь переходим в каталог с исходными текстами, конфигурируем и компилируем ядро. # cd /usr/src/linux # make xconfig (èëè make menuconfig)
В процессе конфигурирования необходимо обязательно установить следующие пункты. В «Code maturity level options» выставьте «Prompt for development and/or incomplete code/drivers».
В «General setup» – «Sysctl support».
И зайдя в новый пункт «Linux Intrusion Detection System» – «Linux Intrusion Detection System support (EXPERIMENTAL)».
75
безопасность
После конфигурирования записываем внесенные изменения и выходим из программы конфигурации. После этого идет обычный процесс компиляции и установки нового ядра. # # # # #
make make make make make
dep clean bzImage modules modules_install
Копируем получившееся новое ядро в каталог /boot: # cp arch/i386/boot/bzImage /boot/lids-kernel
И в параметрах загрузчика (Grub или LILO) прописываем необходимые строки для запуска системы с новым ядром. Но перегружаться еще рано, теперь необходимо установить и сконфигурировать утилиту lidsadm. Если этого не сделать, то система попросту не загрузится. Не удаляйте старое ядро: в случае неудачи будет возможность загрузиться без LIDS для продолжения работы и выяснения причин. Итак, переходим в каталог с распакованной LIDS и даем стандартную команду для конфигурирования и установки. # ./configure && make && make install
После установки можно обнаружить каталог /etc/lids/, в котором хранятся установки и настройки программы. Внутри находятся четыре файла: lids.conf – в данном файле содержится информация о правах доступа (ACL – Access Control Lists) к различным файлам и каталогам. lids.cap – в этом файле прописаны возможности по конфигурированию. Чтобы включить необходимое свойство, необходимо поставить «+» перед ним, отключить – «-». lids.net – в этом файле устанавливаются необходимые значения для посылки предупреждающих сообщений с помощью e-mail (IP-адрес, порт, SMTP-сервер, заголовок). Для включения данной возможности необходимо собрать ядро с параметром «Send security alerts through network». lids.pw – в этом файле сохраняется пароль, предназначенный для изменения параметров lids. Теперь самое время познакомиться с самой утилитой администрирования lidsadm. Первое чувство, кото-
76
рое возникает, когда знакомишься с используемыми опциями и правилами, что это уже где-то видел. И в принципе будете правы на все сто. Все опции и действия, которые можно с их помощью задать, напоминают используемые в программе конфигурирования FIREWALL – ipchains. Даже принцип действия у них в чем-то совпадает, только ipchains работает с пакетами, пришедшими по сети, а LIDS – с процессами, запущенными от имени какого-то пользователя. Для начала необходимо определиться с некоторыми терминами. Субъектом действия утилиты может быть любая программа или файл, объектом может быть файл каталог или специальное устройство. Прежде всего устанавливаем пароль для защиты утилиты, пока работаем с обычным ядром – пароль у нас спрашивать не будут, но как только перегрузимся, все действия по конфигурированию будут предваряться запросом пароля (хотя есть возможность и отключить защиту). Итак, вводим: # lidsadm -P
Теперь у нас запросят пароль дважды и после окончания работы утилиты в зашифрованном виде его можно пронаблюдать в файле lids.pw. Для получения краткой справки по используемым командам и устанавливаемым флагам введите: # lidsadm -h.
Теперь, чтобы добавить новое правило, воспользуемся опцией -A (append). Общий синтаксис команды такой: lidsadm -A [-s subject] -o object [-d] -j
Поле ACTION указывает на действие, которое будет выполняться при запросе отмеченного ресурса. Оно может принимать несколько значений, но самыми употребляемыми будут четыре: READ (объект помечен только для чтения); APPEND (возможно только добавление информации); WRITE (возможна запись, в том числе и удаление); GRANT (предоставляет возможность субъекту отклонять общие правила). Теперь введя команду: # /sbin/lidsadm -A -o /etc/shadow -j DENY
мы запретим всем пользователям доступ к данному файлу. Теперь после перезагрузки с lids-ядром, просмотрев с помощью команды: # ls /etc/shadow
в ответ получим ls: /etc/shadow : No such file or directory. Чтобы пользователь мог зарегистрироваться в системе, откроем доступ только для чтения единственной программе, которая законно должна работать с данным файлом.
безопасность # /sbin/lidsadm -A -s /bin/login -o /etc/shadow -j READ
Теперь пользователи получают возможность входить в систему (с помощью /bin/login), т.е. здесь достаточно прав только для чтения, а другим программам доступ будет заблокирован. Аналогичным образом можно установить требуемые действия сразу на весь каталог. # /sbin/lidsadm -A -o /sbin/ -j READ
Для различных файлов журналов достаточно установить возможность только дозаписи информации в них, в таком случае злоумышленнику будет довольно трудно скрыть свое пребывание редактированием соответствующих логов. Например: # /sbin/lidsadm -A -o /var/log/samba/ -j APPEND # /sbin/lidsadm -A -o /var/log/secure -j APPEND
Просмотреть все установленные правила можно, воспользовавшись опцией -L (list): # lidsadm -L
Статус системы можно просмотреть опцией: # /sbin/lidsadm -V
После того как все необходимые правила будут занесены, необходимо обновить dev/inode лист с помощью команды: # /sbin/lidsadm -U
Естественно, кроме добавления информации о защищаемых файлах, есть возможность удалить файл из списка. Это можно проделать, воспользовавшись опцией -D (delete) с указанием конкретного файла: # /sbin/lidsadm -D /etc/httpd/
или с помощью команды lidsadm -Z очистить сразу весь список. И напоследок, после всех установок, необходимо «запечатать» ядро («seal the kernel») с помощью команды: /sbin/lidsadm -I
а более грамотным решением будет занести в файл /etc/ rc.local соответствующую строку, чтобы не вводить ее при каждом перезапуске системы. После этого ваша система будет защищена с помощью lids. А что делать, если понадобится временно убрать защиту, неужели опять придется перезагружаться со старым ядром? Совсем нет. Необходимо переключиться в режим LIDS free session (LFS). Для его поддержки при конфигурировании ядра необходимо установить параметр «Allow switching LIDS protections». Чтобы открыть сеанс LFS в текущем терминале (и только в нем), необходимо ввести: # /sbin/lidsadm -S -- -LIDS
№4(5), апрель 2003
и ввести пароль по запросу. Чтобы отказаться от режима LFS, вводим: # /sbin/lidsadm -S -- +LIDS
Плюс ко всему желательно заставить перечитать lids конфигурационные файлы: # /sbin/lidsadm -S -- +RELOAD_CONF
Если появилась необходимость отключения от защищенного режима глобально для всей системы, то достаточно для этого ввести: # /sbin/lidsadm -S -- -LIDS_GLOBAL
и теперь это будет обычная система. Как говорилось, lids может защищать процессы от посягательств извне. Установив в файле /etc/lids/lids.cap опцию -29:CAP_INIT_KILL, можно защитить все процессы, чьим родительским является процесс номер 1 в системе init. А вот так можно убрать (спрятать) из списков процессов, выдаваемых с помощью команды ps, сервер Apache. # /sbin/lidsadm -A -s /usr/sbin/httpd -t -o CAP_HIDDEN ↵ -j INHERIT
В случае если lids «прижился» на компьютере и старое ядро за ненадобностью было удалено, есть возможность при загрузке lids-ядра установить режим загрузки без защиты. Для этого надо при выборе ядра в LILO или Grub дополнительно указать параметр: security=0: grub>lids-kernel security=0
После этого система будет загружена в обычном незащищенном режиме. При компиляции ядра с опцией «Port Scanner Detector in kernel» появится возможность дополнительно отслеживать работу сканеров портов, и в случае обнаружения такого сканирования, системный администратор будет оповещен, а в лог-файле появится информация, которая может помочь (а может и не помочь, скрыть IP-адрес труда особого не представляется, но это тема отдельного разговора) в поиске злоумышленника так, что такой возможностью пренебрегать не стоит. Вот такой он LIDS. Единственная сложность в конфигурировании – это определиться с каталогами, которые нужно будет защищать, и выбрать режим работы для них. Здесь универсальный совет дать трудно: все зависит от назначения компьютера и запущенных сервисов. Но не обязательно стараться закрыть все файлы, достаточно поначалу обойтись только наиболее важными, а затем постепенно наращивать защиту. В документации, поставляемой с пакетом LIDS, приведены примеры для некотрых наиболее часто используемых сервисов, так что по аналогии можно будет разобраться. Но одно ясно: используя LIDS, можно существенно поднять уровень защиты компьютера под управлением Linux и значительно усложнить жизнь тем, кто хочет покопаться в чужом компьютере.
77
безопасность
СИСТЕМА КРИПТОГРАФИЧЕСКОЙ ЗАЩИТЫ ИНФОРМАЦИИ
Без использования криптографии сегодня немыслимо решение задач по обеспечению безопасности информации, связанных с конфиденциальностью и целостностью, аутентификацией и невозможностью отказа от авторства. Если до 1990 г. криптография обеспечивала защиту исключительно государственных линий связи, то в наши дни использование криптографических методов получило широкое распространение благодаря развитию компьютерных сетей и электронного обмена данными в различных областях: финансах, банковском деле, торговле и т. д.
ВЛАДИМИР МЕШКОВ
78
безопасность Управление ключами Важнейшую роль в криптографии играет управление ключами. Это основа для обеспечения конфиденциальности обмена информацией, идентификации и целостности данных. Целью управления ключами является нейтрализация таких угроз, как: компрометация конфиденциальности секретных ключей; компрометация аутентичности секретных или открытых ключей. При этом под аутентичностью понимается знание или возможность проверки идентичности корреспондента, для обеспечения конфиденциальной связи с которым используется данный ключ; несанкционированное использование секретных или открытых ключей, например использование ключа, срок действия которого истек. Для снижения риска компрометации конфиденциальности секретных ключей необходимо ограничить круг лиц, у которых есть доступ к ключевой информации. Работать с ключами должен специально подготовленный персонал, имеющий соответствующие полномочия (допуск). Исходя из этого требования, разработаем модель системы криптографической защиты информации (СКЗИ), в которой доступ к ключам имеет только администратор системы. Назначение СКЗИ – криптографическое преобразование информации в соответствии с алгоритмом ГОСТ 28147-89, режим гаммирования. Данная система реализована для операционной системы Linux, версия ядра – 2.4.17, компилятор gcc-2.95.3.
Ðèñ.1. Äðàéâåð íå çàãðóæåí.
Драйвер после загрузки перехватывает системный вызов sys_gost, и все обращения МВ к функции sys_gost будут обслуживаться драйвером. Однако если ключевые данные не введены в БКИ, драйвер также не будет выполнять криптопреобразований, возвращая МВ нулевое значение (рис.2).
Ðèñ.2. Äðàéâåð çàãðóæåí. Êëþ÷åâàÿ èíôîðìàöèÿ íå ââåäåíà.
Только после того, как МКД осуществит запись ключевой информации в БКИ, входные данные, передаваемые драйверу, поступают на вход БКП. Ключевая информация предварительно формируется модулем генерации ключевых данных (рис.3).
Состав СКЗИ и назначение структурных элементов В состав СКЗИ входят следующие элементы: модуль генерации ключевых данных; драйвер криптографического преобразования (далее драйвер). Непосредственно выполняет операции криптографического преобразования информации. Содержит блок криптографического преобразования (БКП) и блок хранения ключевой информации (БКИ); модуль записи ключевых данных (МКД). Осуществляет запись ключевых данных в БКИ драйвера; модуль взаимодействия с драйвером (МВ). Осуществляет информационный обмен с драйвером при выполнении операций криптографического преобразования.
Алгоритм функционирования СКЗИ Структурная схема СКЗИ представлена на рис. 1-3. Информация, подлежащая преобразованию, поступает на вход модуля МВ. МВ, получив блок данных, вызывает системную функцию sys_gost. Данная функция дополнительно вводится в состав ядра ОС Linux. Блок входных данных является параметром вызова sys_gost. Если драйвер не загружен, функция sys_gost никаких преобразований не выполняет и возвращает вызывающему модулю нулевое значение (рис.1).
№4(5), апрель 2003
Ðèñ.3. Äðàéâåð çàãðóæåí. Êëþ÷åâàÿ èíôîðìàöèÿ ââåäåíà.
Сразу отметим, что операции загрузки драйвера и записи в него ключевых данных являются привилегированными. Выполнить их может только администратор системы, имеющий права root. Таким образом выполняется требование по ограничению доступа персонала к ключевой информации.
Реализация СКЗИ Системный вызов sys_gost Как было сказано выше, в состав ядра ОС Linux дополнительно вводится новый системный вызов sys_gost. Механизм системных вызовов был рассмотрен в статье «Перехват системных вызовов в ОС Linux» [1]. Добавим запись о системном вызове sys_gost() в таблицу системных вызовов sys_call_table (файл /usr/src/linux/ arch/i386/kernel/entry.S):
79
безопасность ENTRY(sys_call_table) . . . .long SYMBOL_NAME(sys_gost) /* 226. Íîâûé ñèñòåìíûé âûçîâ! */
Наш системный вызов имеет порядковый номер 226. Добавим его в заголовочный файл /usr/src/linux/include/ asm-i386/unistd.h, в котором содержится перечень всех системных вызовов ядра и макросы для работы с ними: #define __NR_gost
226
/* Íîâûé ñèñòåìíûé âûçîâ! */
В файл /usr/include/bits/syscall.h добавим запись: #define SYS_gost __NR_gost
Теперь осталось написать код, реализующий системный вызов sys_gost(). Вот как он выглядит: asmlinkage int sys_gost(char * block, size_t count, int flag) { return 0; }
Этот код мы добавим в файл /usr/src/linux/fs/open.c. Как мы видим, системный вызов sys_gost принимает три параметра: указатель на буфер с данными char *buf, размер буфера off_t count и флаг int flag. Третий параметр flag служит для информирования о начале/завершении выполнения операции криптопреобразования. Для того чтобы процесс (модуль МВ) мог обратиться к данному системному вызову, в каталоге /usr/include/ создадим заголовочный файл gost.h следующего содержания: #include <sys/types.h> #include <linux/unistd.h> #define E_START #define E_STOP
1 0
static inline _syscall3(int,gost,char *,buf,off_t,count,int,flag)
Алгоритм шифрования ГОСТ 28147-89 Алгоритм ГОСТ 28147-89 был разработан в СССР и является стандартом шифрования Российской Федерации, описывает принципы криптографического преобразования данных для передачи в компьютерных сетях, отдельных компьютерных комплексах или компьютерах, их шифрования и создания цифровых подписей. Алгоритм ГОСТ 28147-89 криптографического преобразования предназначен как для аппаратной реализации, так и для программых реализаций, он удовлетворяет необходимым общемировым стандартам криптостойкости и не определяет ограничений на уровень секретности защищаемой информации. Этот стандарт является обязательным для организаций и компаний РФ, которые используют шифровальную защиту для данных, загружаемых или передаваемых через компьютерные сети, отдельные компьютерные комплексы. Стандарт алгоритма ГОСТ 28147-89 для криптографи-
80
Здесь E_START и E_STOP – флаги, информирующие о начале/завершении операции криптографического преобразования. Макрос _syscall3 сообщает компилятору, что он должен сделать, встретив в исходном тексте программы обращение к системному вызову sys_gost. Этот макрос определен в файле /usr/src/linux/ include/asm-i386/unistd.h: #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3))); \ __syscall_return(type,__res); \ }
Таким образом, системный вызов sys_gost будет выполняться стандартным для всех системных вызовов способом: аргументы вызова загружаются в регистры процессора, а затем вызывается программное прерывание int $0x80. Конструкция __NR_##name трансформируется в порядковый номер системного вызова name, и этот номер загружается в регистр EAX. После внесения всех изменений ядро необходимо перекомпилировать.
Драйвер Задача драйвера – перехватить системный вызов sys_gost, принять ключи и начать выполнение операций криптографического преобразования блоков данных, поступающих от МВ. Драйвер является символьным (байт-ориентированным) устройством. Создадим для него файл устройства следующей командой: mknod /dev/gost c 69 0
Заголовочные файлы и переменные Для работы нам понадобятся следующие header-файлы: ческой защиты данных в компьютерных системах был опубликован в 1990 году и в настоящее время широко используется в программном обеспечении. В отличие от его собрата, алгоритма DES, принятого в качестве федерального стандарта США, ГОСТ 28147-89 позволяет достигать большего уровня секретности данных в силу отсутсвия ограничений на уровень секретности защищаемой информации. Данный алгоритм, подобно DES, работает с блоками размером по 64 бита, но на этом их сходство заканчивается и следуют различия: ГОСТ 28147-89 содержит 32 цикла преобразования, в отличие от 16 циклов DES. Каждый цикл в ГОСТ 28147-89 состоит из более простых операций, чем в DES, что сказывается на скорости работы. В отличие от длины ключа в DES (56 бит), стандарт ГОСТ 28147-89 описывает длину ключа 256 бит. ГОСТ 28147-89 работает на порядок быстрее DES.
безопасность #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/fs.h> #include <sys/syscall.h> #include <asm/uaccess.h> #include "gost_var.h" #define GOST_MAJOR 69
int init_module(void) {
Регистрируем устройство в системе: if (register_chrdev(GOST_MAJOR,"gost",&gost_fops)) return -EIO; – ñòàðøèé íîìåð óñòðîéñòâà
Сохраняем указатель на оригинальный системный вызов:
Переменные: orig_gost = sys_call_table[SYS_gost]; int key_enable = 0; – ôëàã íàëè÷èÿ êëþ÷åâîé èíôîðìàöèè â ÁÊÈ int key_init = 0; – ôëàã èíèöèàëèçàöèè êëþ÷åâîé èíôîðìàöèè struct key_info { char key_d[64]; __u32 X[8]; char sp[8]; } keys;
Производим замену системных вызовов и выходим из функции: sys_call_table[SYS_gost] = own_gost; return 0; }
В соответствии с рис. 2 и 3, структура struct key_info keys является БКИ. В ней будет храниться ключевая информация. Назначение полей структуры struct key_info: char key_d[64] – буфер для хранения долговременного ключа; __u32 X[8] – буфер для хранения сеансового ключа; char sp[8] – буфер для хранения синхропосылки. В файле gost_var.h определены переменные, необходимые для реализации алгоритма ГОСТ 28147-89. Файл имеет следующее содержание:
Структура gost_fops содержит функции, выполняемые драйвером, имеет следующее содержание: struct file_operations gost_fops = { write: write_gost, open: open_gost, release: close_gost, };
Итак, для драйвера определены функции открытия, записи и закрытия.
Функция открытия устройства #include <limits.h> const __u32 C1=0x01010104; const __u32 C2=0x01010101; __u32 SM2, N3, N4;
Функция имеет следующий вид: static int open_gost(struct inode *inode, struct file *file) {
SM1,
Если устройство уже открыто, сообщить об этом: if (MOD_IN_USE) return -EBUSY;
union { struct { __u32 N1; __u32 N2; } lg; char N[8]; } nac;
Значение констант C1 и C2 определено ГОСТ 28147-89. Переменные SM1 и SM2, в соответствии с терминологией ГОСТ 28147-89, назовем сумматорами, а N1, N2, N3, N4 – накопителями. Экспортируем таблицу системных вызовов ядра: extern void *sys_call_table[];
Вводим дополнительно указатель для сохранения оригинального системного вызова: int (*orig_gost)(char *block, size_t count, int flag);
Инициализация драйвера Инициализацию драйвера выполняет функция init_module. Во время инициализации перехватываем системный вызов sys_gost. Алгоритм перехвата системных вызовов был рассмотрен в статье «Перехват системных вызовов в ОС Linux» [1].
№4(5), апрель 2003
Проверяем значение младшего номера устройства (должно быть равно 0) и режим открытия устройства (чтение/запись): if (MINOR(inode->i_rdev) != 0) return -ENODEV; if ((file->f_mode & 1) != 1) return -EBUSY;
Обнуляем структуру для хранения ключевой информации: memset(&keys,0,sizeof(struct key_info));
Сбрасываем флаг наличия ключевой информации в БКИ: key_enable = 0;
Устанавливаем счетчик использования модуля и выходим из функции: MOD_INC_USE_COUNT; return 0; }
Функция записи в устройство В процессе записи драйверу передается структура типа struct key_info, содержащая ключевую информацию.
81
безопасность static ssize_t write_gost(struct file *file, ↵ const char *buf, size_t count, loff_t *ppos) {
Второй аргумент функции содержит блок данных, передаваемых драйверу для обработки. Третий аргумент – размер этого блока. Проверяем размер блока: if (count!=sizeof(struct key_info)) return -EINVAL;
Считываем передаваемый блок данных в адресное пространство драйвера (в БКИ):
Проверяем значение флагов flag и key_enable. Если оба этих флага установлены, приступаем к выполнению операции криптографического преобразования блока данных: if ((flag && key_enable)) {
Все дальнейшие операции выполняются в соответствии с алгоритмом ГОСТ 28147-89, режим гаммирования. Если ключи не инициализированы, выполним их инициализацию: if (key_init == 0) init_key();
copy_from_user((char *)&keys,buf,count);
Поднимаем флаг наличия ключевой информации в БКИ и выходим из функции:
Суммируем значение накопителя N4 и константы C1 по модулю (232-1): __asm__ __volatile__( " addl %3,%%eax \n\t" " jnc 1f \n\t" " incl %%eax \n\t" "1: cmpl %2,%%eax\n\t" " jnz 2f \n\t" " xorl %%eax,%%eax \n\t" "2:" :"=a"(N4) :"0"(N4),"b"(ULONG_MAX),"d"(C1));
key_enable = 1; return count; }
Функция закрытия устройства Данная функция только уменьшает счетчик использования драйвера: static int close_gost(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return 0; }
Суммируем значение накопителя N3 и константы C2 по модулю 232: N3 += C2;
Приравниваем значения накопителей:
Функция выгрузки драйвера nac.lg.N1 = N3; nac.lg.N2 = N4;
Выгружает драйвер команда rmmod. При этом вызывается функция cleanup_module: void cleanup_module() {
Шифруем содержимое накопителей N1 и N2 в режиме простой замены алгоритма ГОСТ 28147-89: symple_replace_crypt();
Восстанавливаем указатель на оригинальный системный вызов в таблице: sys_call_table[SYS_gost]=orig_gost;
Выполняем операцию криптографического преобразования блока данных и возвращаем МВ размер блока данных: for(i=0;i<=7;i++) block[i]^=nac.N[i]; return count;
Обнуляем структуру, содержащую ключевую информацию: } memset(&keys,0,sizeof(struct key_info));
Снимаем регистрацию устройства: unregister_chrdev(GOST_MAJOR,"gost"); return;
Если ключи не введены (флаг key_enable сброшен), или установлен флаг завершения операции криптопреобразования (flag == E_STOP), сбрасываем флаг инициализации ключей и возвращаем нулевое значение модулю МВ:
} key_init = 0; return (0); }
Функция own_gost Функция own_gost, которая заменяет оригинальный системный вызов sys_gost, непосредственно выполняет операции криптографического преобразования блоков данных, переданных драйверу модулем взаимодействия МВ. int own_gost(char *block, size_t count, int flag) { int i;
82
Функция init_key Функция init_key() выполняет инициализацию ключей (в соответствии с алгоритмом ГОСТ 28147-89): void init_key() {
безопасность Поместим в накопители N1 и N2 значение синхропосылки: memset(&nac,0,sizeof(nac)); memcpy(nac.N,keys.sp,8);
Шифруем содержимое накопителей N1 и N2 в режиме простой замены алгоритма ГОСТ 28147-89: symple_replace_crypt();
Функция block В функции block объединены блок подстановки (главный структурный элемент алгоритма) и регистр сдвига. В целях повышения скорости работы данная функция реализована на языке assembler. __u32 block(__u32 SM1, char *k, __u32 N2) { __u32 SM2;
Приравниваем значение накопителей:
__asm__ __volatile__ ( " cld \n\t" " pushl %%edx \n\t" " xorl %%ecx,%%ecx \n\t" " xorl %%edx,%%edx \n\t" " movw $4,%%cx \n\t" "1: pushl %%esi \n\t" " pushw %%cx \n\t" " pushl %%eax \n\t" " pushl %%edx \n\t" " xorl %%edi,%%edi \n\t" " xorw %%cx,%%cx \n\t" " movl %%esi,%%edi \n\t" " addl $8,%%edi \n\t" " xorl %%ebx,%%ebx \n\t" " xorw %%dx,%%dx \n\t" " pushw %%ax \n\t" " shlb $4,%%al \n\t" " shrb $4,%%al \n\t" " movb %%al,%%dl \n\t" " popw %%ax \n\t" " shrb $4,%%al \n\t" " movb %%al,%%dh \n\t" " xorl %%eax,%%eax \n\t" " movb %%dl,%%bl \n\t" " btw $0,%%bx \n\t" " jnc 2f \n\t" " decb %%bl \n\t" " shrb $1,%%bl \n\t" " movw (%%esi,%%ebx),%%ax " shrb $4,%%al \n\t" " jmp 3f \n\t" "2: shrb $1,%%bl \n\t" " movw (%%esi,%%ebx),%%ax " shlb $4,%%al \n\t" " shrb $4,%%al \n\t" "3: movb %%al,%%cl \n\t" " xorl %%ebx,%%ebx \n\t" " movb %%dh,%%bl \n\t" " btw $0,%%bx \n\t" " jnc 4f \n\t" " decb %%bl \n\t" " shrb $1,%%bl \n\t" " movw (%%edi,%%ebx),%%ax " shrb $4,%%al \n\t" " shlb $4,%%al \n\t" " jmp 5f \n\t" "4: shrb $1,%%bl \n\t" " movw (%%edi,%%ebx),%%ax " shlb $4,%%al \n\t" "5: orb %%cl,%%al \n\t" " popl %%edx \n\t" " movb %%al,%%dl \n\t" " popl %%eax \n\t" " popw %%cx \n\t" " rorl $8,%%edx \n\t" " shrl $8,%%eax \n\t" " xorl %%esi,%%esi \n\t" " popl %%esi \n\t" " addl $16,%%esi \n\t" " decw %%cx \n\t" " jz 6f \n\t" " jmp 1b \n\t" "6: movl %%edx,%%eax \n\t" " roll $11,%%eax \n\t" " popl %%edx \n\t" " xorl %%edx,%%eax \n\t" :"=a" (SM2) :"0"(SM1),"S"(k),"d"(N2) :"ebx","ecx","edi"); return SM2;
N3=nac.lg.N1; N4=nac.lg.N2;
Поднимаем флаг инициализации ключей и возвращаемся из функции: key_init = 1; return; }
Функция symple_replace_crypt Операцию шифрования в режиме простой замены ГОСТ 28147-89 выполняет функция symple_replace_crypt(). Функция имеет следующий вид: void symple_replace_crypt() { int i,n;
В соответствии с алгоритмом ГОСТ 28147-89 выполняем 31 цикл преобразования: for(n=1;n<=3;n++) { for(i=0;i<=7;i++) op(i); } for(i=7;i>=1;i--) op(i);
32-й цикл несколько отличается от остальных, распишем его отдельно: SM1=nac.lg.N1+X[0]; SM2=block(SM1,keys.key_d,nac.lg.N2); nac.lg.N2=SM2; return; }
В функции op() реализованы циклы преобразования: void op(int i) {
Суммируем значение накопителя N1 и 4-х байтового вектора X[i] в сумматоре SM1: SM1 = nac.lg.N1+X[i];
Получаем результат из блока подстановки: SM2 = block(SM1,keys.key_d,nac.lg.N2); nac.lg.N2 = nac.lg.N1; nac.lg.N1 = SM2; return; }
№4(5), апрель 2003
\n\t"
\n\t"
\n\t"
\n\t"
}
Здесь приведена «лобовая» реализация блока под-
83
безопасность становки и регистра сдвига. На оптимальность, конечно, не претендует, но работает правильно и достаточно быстро. Весь вышеприведенный код драйвера разместим в файле sys_call_gost.c. Функции расположим в следующем порядке (параметры функций и тип возвращаемого результата не указаны): block; op; symple_replace_crypt; init_key; own_gost; write_gost; open_gost; close_gost; init_module; cleanup_module.
Makefile Для получения загружаемого модуля ядра (драйвера) создадим Makefile следующего содержания:
mount -t ext2 /dev/fd0 /floppy
Теперь рассмотрим код генератора ключей. Заголовочные файлы: #include <stdio.h> #include <fcntl.h>
Точка монтирования файловой системы ключевого носителя: #define MOUNT_DIR "/floppy" int main() { int s,d,sp,rnd; char buf[64];
Для получения случайной последовательности (а точнее, псевдослучайной) воспользуемся файлом /dev/ urandom: rnd=open("/dev/urandom",O_RDONLY);
CC = gcc module = sys_call_gost.o CFLAGS = -O2 -Wall LINUX = /usr/src/linux MODFLAGS = -D__KERNEL__ -DMODULE -I$(LINUX)/include
Формируем ключевые данные. Создаем на ключевом носителе файлы ключей и синхропосылки:
sys_call_gost.o: sys_call_gost.c $(CC) $(CFLAGS) $(MODFLAGS) -c sys_call_gost.c
Модуль генерации ключевых данных
d=open(MOUNT_DIR"/key_d",O_CREAT|O_WRONLY,0600); s=open(MOUNT_DIR"/key_s",O_CREAT|O_WRONLY,0600); sp=open(MOUNT_DIR"/sp",O_CREAT|O_WRONLY,0600);
Записываем в созданные файлы случайную последовательность, считанную из /dev/urandom:
Задача модуля генерации – формирование ключевых данных (долговременного ключа, сеансового ключа и синхропосылки) и запись их на носитель. Размер ключей и синхропосылки фиксирован. Длина сеансового ключа составляет 32 байта, долговременного – 64 байта, длина синхропосылки – 8 байт. В качестве носителя ключевых данных выберем дискету. На этой дискете (далее ключевая дискета) будут размещаться три файла: файл долговременного ключа key_d длиной 64 байта; файл сеансового ключа key_s длиной 32 байта; файл синхропосылки sp длиной 8 байт.
bzero(buf,64); read(rnd,buf,64); if(write(d,buf,64)!=64) { perror("key_d"); exit(-1); } close(d); bzero(buf,64); read(rnd,buf,32); if(write(s,buf,32)!=32) { perror("key_s"); exit(-1); } close(s); bzero(buf,64); read(rnd,buf,8); if(write(sp,buf,8)!=8) { perror("sp"); exit(-1); } close(sp);
Доступ к ключевой дискете должен иметь только администратор системы. Для предотвращения компрометации ключевой информации администратору необходимо обеспечить соответствующие условия ее хранения. Подготовим ключевую дискету к работе: fdformat /dev/fd0u1440 mkfs -V -t ext2 /dev/fd0
Перед записью ключевых данных в БКИ драйвера необходимо смонтировать ключевую дискету. Создадим точку монтирования: mkdir /floppy
и смонтируем туда файловую систему, находящуюся на ключевой дискете:
84
close(rnd); return (0); }
Генератор очень простой и приведен только в качестве примера. Необходимо отметить, что случайная последовательность, из которой формируются ключевые данные, предварительно должна быть подвергнута статистическому анализу для доказательства того, что в ней отсутствуют закономерности, которые могут позволить третьей стороне (противнику) восстановить секретный ключ. Статистический анализ представляет из себя целый комплекс
безопасность специальных тестов (около 14), которые случайная последовательность должна пройти, прежде чем ее признают годной к применению. Для получения действительно случайной последовательности применяются специально спроектированные аппаратные генераторы, построенные на базе полупроводниковых приборов с высоким коэффициентом шума. Но так как мы рассматриваем модель СКЗИ, то жестких требований к качеству ключевой информации предъявлять не будем. Для нашей задачи вполне подойдет и псевдослучайная последовательность. После завершения операции формирования ключевых данных вводим команду:
exit(-1); } s=open(MOUNT_DIR"/key_s",O_RDONLY); if(s < 0) { perror("key_s"); exit(-1); }
Считываем информацию из файлов ключей и синхропосылки в структуру struct key_info: if(read(d,keys.key_d,64)!=64){ perror("key_d"); exit(-1); } if(read(s,(char *)&keys.X,32)!=32){ perror("key_s"); exit(-1); }
umount /dev/fd0
Теперь ключевой носитель готов к применению.
if(read(sp,keys.sp,8)!=8){ perror("sp"); exit(-1); }
Модуль записи ключевых данных Задача модуля записи ключевых данных (МКД) – записать ключи, находящиеся на ключевой дискете, в БКИ драйвера. Рассмотрим программный код МКИ. Заголовочные файлы: #include #include #include #include #include
<stdio.h> <stdlib.h> <fcntl.h> <sys/types.h> <errno.h>
Точка монтирования файловой системы, находящейся на дискете:
Записываем ключевую информацию в БКИ: write(gost,(char *)&keys,sizeof(struct key_info));
Информируем о завершении процедуры записи ключей: printf("\nKeys loaded\n\n");
Закрываем файлы и выходим: close(gost); close(d); close(s); close(sp);
#define MOUNT_DIR "/floppy" int main() {
return (1); }
Дескрипторы ключевых файлов, синхропосылки и файла устройства:
Вышеприведенный код сохраним в файле write_key.c. Получим исполняемый модуль, введя команду:
int s,d,sp,gost; gcc -o write_key write_key.c
Структура для хранения ключевой информации: struct key_info { char key_d[64]; u_long X[8]; char sp[8]; } keys; memset(&keys,0,sizeof(struct key_info));
Открываем все необходимые файлы: gost=open("/dev/gost",O_RDWR); if(gost < 0) { perror("gost"); exit(-1); } sp=open(MOUNT_DIR"/sp",O_RDONLY); if(sp < 0) { perror("sp"); exit(-1); } d=open(MOUNT_DIR"/key_d",O_RDONLY); if(d < 0) { perror("key_d");
№4(5), апрель 2003
Модуль взаимодействия с драйвером Задача модуля взаимодействия с драйвером (МВ) – осуществлять информационный обмен с драйвером при выполнении операций криптографического преобразования. Программный код модуля МВ: #include <stdio.h> #include <fcntl.h> #include <gost.h> int main (int argc, char **argv) { int in,n; char buff[8];
Параметром МВ является имя файла, содержание которого подлежит криптографическому преобразованию. if(argc!=2) { printf("\n\tUsage: gost [input file]\n\n"); exit(0); }
85
безопасность Открываем входной файл: in=open(argv[1],O_RDWR); if(in < 0) { perror("input"); exit(-1); }
Порядок работы с СКЗИ Для подготовки СКЗИ к работе администратор системы должен выполнить следующие действия: загрузить драйвер командой insmod sys_call_gost.o
memset(buff,0,8);
Считываем из входного файла блоки данных длиной 8 байт:
подготовить дискету и сформировать ключевые данные; записать ключи в БКИ:
while((n=read(in,buff,8)) > 0) {
Вызываем системную функцию sys_gost для выполнения операции криптопреобразования блока данных: gost(buff,n,E_START);
Результат преобразования записываем в тот же файл: lseek(in,-n,SEEK_CUR); write(in,buff,n); }
Информируем драйвер о завершении операции криптографического преобразования: gost(0,0,E_STOP);
Закрываем входной файл и выходим из программы: close(in); return 0; }
Вышеприведенный код сохраним в файле gost.c. Исполняемый модуль получим, введя команду: gcc -o gost gost.c
86
смонтировать файловую систему ключевой дискеты командой mount -t ext2 /dev/fd0 /floppy; запустить на выполнение модуль МКД (файл write_key). В случае успешного завершения МКД выдаст сообщение Keys loaded; после записи ключевых данных в БКИ ввести команду umount /dev/fd0; изъять из дисковода ключевой носитель и поместить его в специально выделенное хранилище.
После того как администратор подготовит СКЗИ к работе, пользователь (оператор) может приступить к выполнению операций криптографического преобразования информации. Для этого ему достаточно запустить на выполнение модуль МВ (исполняемый файл gost), указав в командной строке имя преобразуемого файла. Результат преобразования будет записан в тот же файл. Ключи расположены в адресном пространстве ядра ОС, и модуль МВ, работающий в режиме приложения пользователя (третье кольцо защиты), прямого доступа к ключевой информации не имеет. Таким образом, рассмотренная модель СКЗИ позволяет обеспечить достаточно высокий уровень защиты личных данных пользователя и ключевых данных от компрометации. Литература: 1. Мешков В. «Перехват системных вызовов в ОС Linux». – журнал «Системный администратор». – 2003г, №3(4). с.40-44.
ИНТЕРНЕТ-ОПЕРАЦИОННЫЕ
СИСТЕМЫ
web В настоящее время интернет-сайты далеко не всегда и не везде проектируются профессиально, к тому же с учетом дальнейшего развития. В данной статье мы попытаемся предсказать, как же будет развиваться проектирование сайтов, какой ценой это обходится сейчас и будет обходиться в будущем. Для понимания картины будет замечательно, если читатель имеет опыт интернет-программирования и создания сайтов.
Что такое «Интернет-операционная система»?
ИГОРЬ ТЕТЕРИН №4(5), апрель 2003
Интернет-операционная система (ИОС, либо более понятное название WebOS) – программный продукт, предоставляющий некий сервис для программ более высокого уровня, которые, в свою очередь, основываются на этом сервисе. ИОС принципиально ставит перед собой задачу – облегчить труд программиста, а значит, сэкономить, структуризировать, разбить задачи создателя сайта на более мелкие и иметь более четкое и безопасное решение для своего интернет-проекта. Возможно, вы привыкли к обычному пониманию фразы – операционная система. В голове сразу начинают появляться слова Windows, DOS, Linux... На самом деле операционная система – это всего лишь программа, предоставляющая интерфейс для работы остальных программ, суть этого интерфейса в стандартизации, едином синтаксисе написания программ, единых стандартов и т. п. А так как мы рассматриваем ИОС или WebOS, то, соответственно, ограничиваем себя следующими задачами: предоставить некий интерфейс для работы с интернет-сайтами (в случае WebOS) или с некоторым комплексом процессов интернет-сервисов (в случае ИОС). В чем разница? Разница лишь в том, что ИОС должна решать значительно больше задач. Мы хоть и рассматриваем именно ИОС, но нас интересует ограниченное направление. Позже мы коснемся темы микро-ИОС. Вам пока лишь стоит понять, что мы будем рассматривать сайты, имеющие широкий спектр возможностей, а позже касаясь микро-ИОС, коснемся ограниченных возможностей.
Движки сайтов Мы часто можем слышать о движках сайтов. Обычно под этим понимается комплекс программ (скриптов и шаблонов), которые обеспечивают необходимый уровень содержания сайта, и чаще всего удаленного содержания. Так все и привыкли понимать их. Существует достаточно и хороших движков и очень уж специфичных, многие начинающие программисты пишут собственные движки сайтов, основываясь на чьих-то исходниках. Таких вещей очень много, но и при этом достать что-то универсальное – практически невозможно. Каждый из них имеет собственное направление, специфику, ограничения. Что касается коммерческих движков, то тут стоит заметить, что коммерческие движки – есть коммерческие, они либо заставляют нас нарушать закон, либо отказываться от них, либо покупать. Поэтому движки – сейчас настоящая проблема для средних программистов. Теперь посмотрим на движки с другой стороны. Основной задачей для них является управление контентом, реализация хорошего интерфейса клиента и администратора. Остальное отходит на задний план. Именно к этому стремились некоторое время назад. Технические решения представляют собой достаточно сложные программы, где, на мой взгляд, достаточно мусора, но не это главное, главное нам понять, что такое движок.
Сравнение ИОС и движков Давайте попробуем сравнить ИОС и движки. В чем разница? Так как на свете нет бесплатных ИОС, то понимание разницы должно заставить вас понять и то, насколько необходима ИОС вообще. Принципиальная разница в назначении этих двух вещей и уровне программирования/реализации. Давайте вспомним, что же такое ИОС и что такое движок и для начала определим сходства. Они имеют примерно одинаковый уровень программирования, но только примерно, они оба начинают работать по запросу клиента. Можно даже запутаться. Тут тоже может возникнуть подозрение, что в принципе некоторые задачи могут быть одинаковыми. Дело в том, что в идеале обработка запроса сай-
89
web том происходит по следующей упрощенной цепочке: 1. сервер (Apache) 2. Perl 3. ОС 4. движок 3. ОС 2. Perl 1. сервер (Apache) Тут мы схематично можем представить, где находится ИОС. Другими словами, движок строится на вебоперационной системе, которая построена на Perl, Си, Python или, на худой конец, на PHP. Как и любой программе, движку предоставляется выбор: либо использовать функции ОС, либо писать, используя только язык программирования. А ИОС предоставляет этот выбор. Создает некоторую выгоду использования себя.
Схема построения сайтов при помощи ИОС и движков Давайте рассмотрим детальнее, как будет выглядеть обычная обработка запроса. Клиент вводит URL в браузере. Запрос посылается на указанный IP, где управление получает сервер, для примера пусть это будет Apache, который ищет страницу по умолчанию index.html (для примера). В странице оказываются SSI-ссылки на выполнение скрипта, пусть это будут новости. Apache запускает интерпретатор (я все привожу в очень простой форме) и передает параметр (имя скрипта и возможные параметры для скрипта). Следующим шагом интерпретатор запускает скрипт и передает ему параметры. Далее мы рассмотрим 2 варианта: с ИОС и без нее. Без ИОС. Скрипт читает файл с новостями, файл с шаблоном, параметрами, возможно, эти операции разделяются (а, возможно, работа происходит через SQL), в общем итоге составляется код HTML, который передается в stdout. C ИОС управление получает скрипт ОС, который подгружает необходимую минимальную базу модулей, проделывает базовые операции: форматирует входящие параметры, устанавливает обработчик ошибок, устанавливается кешеризатор вывода. Затем управление передается нужно-
90
му скрипту движка, который вызывает функции чтения и указывает, что читать (шаблон5, 20 последних новостей). В общем итоге получается HTML, который отправляется якобы в stdout. Ядро собирает заголовки, отправляет, что получилось у движка, и в случае наличия ошибок, могут быть отправлены данные и об этом. При наличии серьезных ошибок вызывается некое событие. В общем, вот простой пример, как происходит совместная работа, и в чем разница между отсутствием и присутствием ИОС.
Функциональное наполнение ИОС Из рассмотренной схемы мы уже начинаем представлять, что собственно должна делать ИОС. Давайте слегка пройдемся по функциям: Перехват, обработка ввода/вывода, возможность управления этими процессами из движка (кеширование как один из видов обработки). Обработка ошибок, предупреждений, исключений, максимум прозрачности для движка. Функции СУБД. При отсутствии SQL должна быть альтернатива, предоставляющая способ работы с данными, избегая при этом работы с файловой системой. Некоторые функции безопасности. Фильтры, конверторы. Независимая от платформы база пользователей и удобный, гибкий интерфейс к ней. Универсальная система логирования. Система работы, создания и обработки событий и другие не менее значимые функции.
Зависимости Давайте взглянем на примитивную схему ИОС: ИОС представляет собой несколько модулей. Будем исходить из того, что ОС написана на Perl. У ИОС не должно быть как такового ядра. Программист движка будет сам выбирать, что ему нужно. Отсюда каждая часть ИОС должна быть максимально независимой. Это действительно должно быть так, но связей и зависимостей не избежать. Обязательные зависимости должны быть решены жестко, подключением необ-
ходимых модулей, а остальные связи должны общаться через единую систему взаимодействия. Эта система обязательна для всех модулей. Я бы назвал ее системой событий. Именно события придают гибкость и возможность взаимодействия самых разных уровней решения задач. Кратко опишем, как должна работать система событий. События – это отдельный модуль с единственной открытой функцией: создать событие. При его создании передаются параметры, характеризующие его. По параметрам проверяется база событий, при совпадении параметров (при совпадении идентификатора события) выполняется код, принадлежащий данному событию. Независимо от всего событие может быть залогировано. В такой системе событий (все тут описано очень примитивно) весьма удобно изменять движок и ОС. При такой схеме движку предоставляется интерфейс событий, поэтому могут писаться любые события, основанные даже на функциях движка.
Вопрос о способе вызова скриптов и взаимосвязь с ИОС На мой взгляд, на свете существует две модели вызова скриптов, и они обе имеют достаточно оснований быть первыми. Эти две модели можно наблюдать в Perl и PHP. Perl не предоставляет функций включения кода в HTML, хотя это и несложно реализовать. PHP принципиально позволяет делать это. Какой способ лучше? На мой взгляд, возможность встраивания кода в HTML лишняя, хотя и удобная. В чем недостатки такого метода? 1.Лишние проблемы с безопасностью. 2.Размазывание границы между версткой и программированием. Почему я поднял вообще этот вопрос? Потому что это важно для ИОС. Важно это в том плане, что ИОС должна гарантировать безопасность со своей стороны, и предоставлять базовый интерфейс для работы с контентом, а без продуманной системы могут возникнуть какие-либо ограничения. Ограничения – очень нехорошая штука. Я все же не даю конкретных решений, а всего лишь рекомен-
web дую строить свою систему на базе подключения внешних скриптов.
Перспективы ИОС В ближайшем будущем все же должны появиться аналоги WebOS. Все же наложение еще одного уровня несет в себе какие-то затраты на изучение документации, прикручивание этого уровня и затачивания движка под ОС. Успех будет, но не скоро. Не каждый сможет решиться на данный шаг. Ну а как правильнее развиваться аналогам ИОС покажет их бесплатность и открытость. Коммерческие ОСи в любом случае будут ограничивать использование законами.
Некоторые принципы ИОС По ходу были указаны некоторые принципы ИОС, давайте еще раз взглянем на них: бесплатный продукт; открытый код; платформонезависимость; компактность; отсутствие ограничений; принцип выбора, а не навязывания.
Микро-WebOS Вот, наконец, мы и дошли до темы "микро". Микро-WebOS обозначает минимум кода. Наложение дополнительного уровня – достаточно ресурсоемкий ход. Для минимизации затрат, ресурсов и времени работы необходима микро-WebOS. Это значит, что вся функциональность ОС должна быть реализована по минимуму. Насчет минимизации и оптимизации кода есть пара прекрасных вещей, о которых я расскажу в следующей статье.
ret WebOS проект ret WebOS – это микро-операционная система для WEB, основанная на Perl. Бесплатный, открытый проект, сочетающий в себе некоторые принципы ИОС. ret рассчитан на бесплатные хостин-
№4(5), апрель 2003
ги и некрупные проекты, хотя это относится лишь к некоторым частям ОС. Итак, что представляет из себя ret? Несколько компактных модулей, отвечающих за конкретные задачи: cru.pm – модуль, отвечающий за преобразование данных (фильтры, хеши, подсветки и др.); data.pm – собственная микроСУБД; err.pm – модуль, перехватывающий и обрабатывающий ошибки, предупреждения и др.; logs.pm – система ведения логов и обработка событий; rights.pm – система ведения прав (интересно то, что в данной системе нет стандартных пользователей типа root, которым дозволено все); wim.pm – модуль, обрабатывающий входящие данные, в том числе и приходящие файлы. Каждый модуль самостоятелен, кроме модуля rights.pm, который зависит от СУБД. Программист волен подключать только то, что ему будет по душе. Чем интересен данный проект? Во-первых, основным принципом: код ret не должен превышать 50 Кб. СУБД ret предоставляет простые функции (например GetRec, Put), но внутренняя сложность структуры данных зависит только от фантазии программиста. Очень интересная вещь – события. Изначальных событий в код не встроено. Но создана база для того, чтобы можно было очень просто добавлять собственные события. Для примера у вас есть свой скрипт, читающий новости. Его вы вызываете из скрипта, который показывает новости. Последний получает новости в отформатированном виде посредством события обработки текста новостей из первого, который явно вызывает это событие, определенное в logs.pm. В чем заслуга такой системы?
Заслуга в том, что модуль logs просто коллекционирует все события, создавая некий стандарт описания событий. Система прав построена достаточно интересно. Существуют шаблоны и собственно сами пользователи, весь интерес в том, как накладываются шаблоны на права пользователей, и какие преимущества это дает. Вообще весь ret построен так, что нет ничего обязательного, нет никаких ограничений (по крайней мере, к этому стремились). Но есть база для создания тех же ограничений, есть атрибуты, которые можно было бы назвать типами, но атрибуты – это нечто большее. Даже синтаксис описания событий не имеет под собой никаких ограничений, событие может быть описано как угодно. Существуют лишь рекомендации и принципы. С точки зрения ret событие описывается следующим образом: a:b:c, где a – виновник события, b – тип события, c – детализация; но правильно описанным событием будет считаться и событие, описанное, например, так: jhskdjhkajsdh. Конечно, смысла в этих символах нет, но если событие с таким именем описано, то оно произойдет. Поэтому хотелось бы подчеркнуть, что ret предоставляет некую базу, на основе которой можно строить логику движка. К минусам ret можно отнести то, что данный проект не закончен и многое еще предстоит сделать, он рассчитан на бесплатные хостинги, где нет поддержки SQL, поэтому SQL нигде не фигурирует и поддержки для него писать не предвидится, потому как это и не надо, Perl предоставляет все, что необходимо, на достаточно неплохом уровне. В ret нет той мультиплатформенности, которую хотелось бы получить, но это лишь вопрос времени.
91
web
ВЫБОР ВЕБ-СЕРВЕРА:
ПОЧЕМУ APACHE? ДМИТРИЙ ГАЛЫШЕВ 92
web За последние несколько лет в России, как и во всем мире, Интернет все глубже проникает в нашу повседневную жизнь. Фактически история Интернета в России насчитывает чуть более 10 лет, с тех пор, когда ряд университетов и научно-исследовательских институтов начали создание локальных сетей и обзавелись зарубежными каналами связи, и заканчивая текущим моментом, когда по данным РОЦИТ [1] в России насчитывается более пяти миллионов пользователей этой сети. Основа Интернета известна всем – это сервера. Именно на них размещены домашние страницы рядовых пользователей, состоящие из нескольких страничек, тематические ресурсы, состоящие из сотен страниц, часто генерируемых динамически и в большинстве своем поддерживаемые группой людей, а также коммерческие проекты и вполне настоящие, несмотря на свою виртуальность, магазины. Большинству рядовых пользователей свой сервер совершенно не нужен. Посудите сами: даже если не выключать домашний компьютер круглосуточно, установив серверное ПО, то для доступа к нему также необходимо круглосуточное соединение с провайдером. Соединение по телефонной линии слишком медленное, чтобы обслуживать хотя бы десять клиентов одновременно. А выделенная линия стоит дорого. Намного проще разместить свою страничку на сервере провайдера. Другое дело – корпоративные пользователи. Как правило у них уже есть выделенная линия, соединяющая с Интернетом локальную сеть, и выделенный компьютер, выполняющий роль шлюза между локальной и глобальной сетями. На нем-то и можно установить веб-сервер. Или для того, чтобы отдать дань моде, или развернуть крупный проект, приносящий прибыль. Данная статья предназначена в первую очередь для тех, кому предстоит непосредственно администрировать вебсайт и отвечать за его работу. Надеюсь, что администраторам с небольшим опытом в этой области она поможет определиться в нелегком выборе серверного ПО, а также аргументированно отстоять свою точку зрения при принятии решения на уровне руководства организации, нередко слепо принимающего на веру маркетинговые заявления. Итак, вам нужен свой собственный веб-сайт. Какому ПО доверить управление им? По данным сервера Netcraft [2] на ноябрь 2002 года около 90% всех веб-серверов в мире работают под управлением двух типов ПО: Apache от Apache Software Foundation и Internet Information Server корпорации Microsoft [3]. Из них около 60% под управлением Apache (более 20 000 000) и 30% под управлением MS IIS (более 10 000 000). Вспоминается старая поговорка: «2 000 000 леммингов не могут ошибаться». Хотя вряд ли это можно считать критерием выбора. Первый критерий выбора – аппаратное обеспечение сервера. Существует два основных решения – выделенный сервер и размещение на уже существующем сервере, настроив маршрутизацию трафика на брандмауэре. IIS может быть установлен только на ОС MS Windows 2000 Server. Если у вас уже есть сервер под управлением другой операционной системы, то вам придется использовать выделенный сервер и покупать для него OC, даже если загрузка его будет составлять менее 10%, а Apache наверняка может быть установлен на ваш «старый» сервер. Apache
№4(5), апрель 2003
может быть установлен на OC Novell NetWare, практически на все ОС семейства UNIX и даже на MS Windows, поэтому даже если у вас уже есть сервер под управлением Windows 2000, не торопитесь устанавливать туда IIS – это небезопасно. Полный список поддерживаемых ОС вы найдете на сайте Apache [4]. Следующий критерий – производительность. Причем тем критичнее, чем больше одновременных подключений. До недавнего времени Apache, собираемый из исходного кода, оптимизированного под UNIX, ощутимо уступал IIS, интегрированному в ОС. С выходом Apache 2.0 ситуация изменилась. Вместо портирования UNIX-кода разработчики написали полноценное Windows-приложение, которое и рекомендуют для коммерческого использования. Электронный журнал eWEEK [5] сравнивал производительность Apache 2.0 и MS IIS, выполняемых под управлением MS Windows 2000 Advanced Server. По результатам тестов оба сервера показали практически одинаковую производительность. Итак, Apache – высокопроизводительный сервер. Еще один важный критерий – доступность. Разработчики Microsoft утверждают, что они сделали огромный шаг вперед – избавились от необходимости перезагрузки ОС при любом изменении настроек сервера. Теперь настройки можно менять «на лету». Но решены ли все проблемы, приводящие к остановке всего сервера, обычно сопровождающиеся так называемым «синим экраном смерти» – неизвестно. И каждая перезагрузка сервера, чем бы она не была вызвана, означает отказ в обслуживании клиентам на время перезагрузки. К сожалению, нет независимой статистики по доступности серверов под управлением той или иной ОС. Поэтому можно лишь вспомнить, что архитектура UNIX изначально ориентирована на бесперебойную работу. Безопасность. Свободу Интернета, как оказалось, можно использовать и в хулиганских целях. Для выхода в Интернет не нужно ни специального разрешения, ни даже паспорта. В тысячах интернет-кафе и компьютерных клубов достаточно оплатить время, и весь простор доступен вам. Это замечательно, но не все приходят в Интернет с добрыми намерениями. И есть люди, которые для того, чтобы похулиганить, выделиться или даже найти работу, выводят из строя интернет-сервера. Результатом действий злоумышленника могут стать как deface [6], так и порча данных, которая может принести ощутимые убытки, например изменение кода интернет-магазина может привести к различным последствиям: от удаления базы данных до торговли в убыток хозяину сайта. Веб-сервер должен быть надежно защищен от несанкционированного изменения документов, с которыми он работает. К сожалению, пока еще нет абсолютно безопасного веб-сервера. И в Apache, и в IIS злоумышленники находят новые уязвимости и используют их для порчи данных. Здесь стоит немного отвлечься от веб-серверов и вспомнить предмет неутихающих споров и в последнее время даже судебных процессов. Что же все-таки лучше – бесплатное ПО с открытым исходным кодом или коммерческое? Что безопаснее? Скептики утверждают: «Злоумышленнику ничего не стоит найти уязвимость в бесплатном ПО, ведь он может читать исходный код. Когда кода нет, сложно даже узнать, как оно работает.» На са-
93
web мом деле, к счастью, хороших людей больше, чем плохих. И большинство людей предпочитает, найдя уязвимость, сообщить о ней разработчикам, нередко присылая исправленный код, решающий проблему. Поэтому за годы развития найти уязвимости становится сложнее. Второе заблуждение: «Открытые проекты поддерживаются неофициально. Купив ПО, я могу потребовать от разработчика решения проблемы». Не все так печально. Устранить описанную уязвимость в программе с открытым исходным кодом может любой программист. А заплаток от производителя коммерческого ПО можно ждать месяцами, и никто кроме него вам не поможет. Примеры при желании вы можете найти в списке рассылки Bugtraq [7]. Возвращаясь к веб-серверам, отметим, что самыми разрушительными были эпидемии червей Code Red, Code Red II и Nimda, от которых пострадали в основном сервера под управлением IIS, а также то, что атаки все еще продолжаются уже зараженными серверами, и не всегда безуспешно. Более того, успешная атака на сервер под управлением IIS может обернуться не только порчей данных, с которыми он работает, но и порчей данных, с которыми работают другие программы, и даже ОС сервера. Именно поэтому веб-сервер под управлением IIS не должен располагаться на компьютере, который выполняет любую другую критическую работу. Такова цена за интеграцию с ОС. Apache, независимый от ОС, на UNIX-системах может выполняться даже в собственном окружении, или, как говорят, «в песочнице». Максимум успеха атаки на такой сервер – порча данных, размещенных на нем. Кроме того, каждый дополнительный компонент, устанавливаемый вместе с веб-сервером является дополнительной угрозой безопасности. По умолчанию вместе с IIS устанавливается несколько библиотек и расширения редактора html FrontPage (видимо, разработчики считают, что содержание сервера должно создаваться на сервере). Стандартная поставка Apache включает в себя только сам сервер. Все модулидополнения поставляются отдельно. Система управления веб-сервером также тесно связана с безопасностью. «Легкий и удобный в настройке» IIS управляется с помощью приложений, использующих графический интерфейс, а в последней версии и с помощью веб-приложений, устанавливаемых вместе с сервером, и позволяет настроить не все параметры, влияющие на работу сервера. Так как настройки «по умолчанию» ориентированы не на максимальную безопасность, а на максимальное быстродействие и количество предоставляемых сервисов, в то время как добраться до них можно только с помощью редактора реестра Windows, установленный IIS с минимальной настройкой вызывает у опытных администраторов шок. Более того, многие администраторы Windows отключают все возможности управления сервером на основе веб-интерфейса, как потенциальную угрозу безопасности. Настройки Apache хранятся в нескольких текстовых файлах конфигурации. Для администраторов, слабо представляющих, как работает веб-сервер, редактирование этих файлов может быть неразрешимой проблемой, несмотря на то, что они хорошо задокументированы. В то же время при переносе, обновлении или переустановке веб-сервера достаточно скопировать эти файлы на новое место, и сервер сно-
94
ва готов к работе, тогда как IIS придется настраивать заново, либо искать и экспортировать ключи реестра, в которых хранятся его настройки, что является непростой задачей даже для опытного администратора NT, особенно если учесть, что документация по реестру Windows вместе с самой OC не распространяется. Таким образом, можно с уверенностью утверждать, что IIS является решением для пользователей Windows, которые хотят с минимальными затратами времени установить собственный веб-сервер и не заботятся о его дальнейшей поддержке. С необходимостью поддержки проекта на базе IIS затраты на оплату администратора и трафика за постоянное получение патчей от производителя могут ощутимо возрасти. В то же время безопасность и доступность такого решения спорна. Решение же на базе Apache, с одной стороны, требует с самого начала работы серьезной теоретической подготовки администратора, но с другой стороны, возможность работы на большом количестве операционных систем и архитектур открывает широкий выбор для размещения, и в сочетании с возможностью работы в собственном окружении показывает высокую стабильность и безопасность использования, а также легкую переносимость, вне зависимости от сложности сайта. 1. http://www.rocit.ru/ 2. http://www.netcraft.com/ 3. Все торговые марки принадлежат их владельцам. 4. http://httpd.apache.org/ 5. http://www.eweek.com/ 6. deface – переводится с англ. как «портить». Здесь означает подмену заглавной страницы сайта. 7. http://www.securityfocus.com/
подписка
Открыта подписка на 2-е полугодие 2003 года 81655
Единый подписной индекс:
81655 по каталогу агентства «Роспечать»
81655
Рады видеть Вас нашими читателями!
№4(5), апрель 2003
95
СИСТЕМНЫЙ АДМИНИСТРАТОР № 4(5), Апрель, 2003 год РЕДАКЦИЯ Исполнительный директор Владимир Положевец Ответственный секретарь Наталья Хвостова sekretar@samag.ru Технический редактор Владимир Лукин РЕКЛАМНАЯ СЛУЖБА тел.:(095)928-8253 (доб. 112) факс:(095)928-8253 Константин Меделян reklama@samag.ru Верстка и оформление imposer@samag.ru maker_up@samag.ru 103012, г. Москва, Ветошный переулок, дом 13/15 тел.: (095) 928-8253 (доб. 112) факс: (095) 928-8253 Е-mail: info@samag.ru Internet: www.samag.ru РУКОВОДИТЕЛЬ ПРОЕКТА Петр Положевец УЧРЕДИТЕЛИ Владимир Положевец Александр Михалев ИЗДАТЕЛЬ ЗАО «Издательский дом «Учительская газета» Отпечатано типографией ООО «Мастер Печати» Тираж 5000 экз. Журнал зарегистрирован в Министерстве РФ по делам печати, телерадиовещания и средств массовых коммуникаций (свидетельство ПИ № 77-12542 от 24 апреля 2002г.) За содержание статьи ответственность несет автор. За содержание рекламного обьявления ответственность несет рекламодатель. Все права на опубликованные материалы защищены. Редакция оставляет за собой право изменять содержание следующих номеров.
96
ЧИТАЙТЕ В СЛЕДУЮЩЕМ НОМЕРЕ: PHP Я думаю, не будет большим секретом, что с помощью простого HTML-кода можно создать лишь статистическую страничку. Но этого в современном быстроменяющемся мире уже не достаточно, необходимо быстро реагировать на изменения и выдавать эту информацию пользователю. Ко всему есть еще необходимость cобрать информацию, например с помощью тех же анкет, автоматически ее обработать и выдать пользователю. С помощью HTML, увы, такие задачи решить невозможно. Какие только технологии не применяются сейчас для придания интерактивности веб-странице – DHTML, ASP, Perl, Java, ColdFusion. Есть в этом немаленьком списке и PHP. Не рассчитывал создатель данного языка Расмус Лердорф (Rasmus Lerdorf), что его язык приобретет такую большую популярность. Задумывался он первоначально исключительно для использования в своих личных целях. О чем свидетельствует даже расшифровка аббревиатуры PHP – Personal Home Page (персональная домашняя страница).
SELinux Дистрибутивов Linux существует великое множество: есть среди них предназначенные для конечного пользователя, есть совсем маленькие узкоспециализированные, предназначенные для решения конкретных задач, как правило, однодискетные, и нашлось место довольно приличной группе, обозначенной как Security enchanced. Основной задачей проекта было достичь такого уровня защищенности системы, чтобы ее можно было спокойно использовать в военных и правительственных организациях. Но по большому счету это не совсем дистрибутив, каким привыкли его видеть администраторы. SELinux представляет собой дополнительные расширения
к ядру, увеличивающие его защищенность и возможность более гибко и строго работать с правами доступа для конкретных пользователей. Чтобы обеспечить дополнительную гибкость при добавлении новых возможностей с помощью различных add-on был разработан модуль защиты Linux Security Module (LSM), который обеспечивает модульное добавление расширений защиты к стандартному ядру Linux.
Конфигурирование DHCP Для чего нужен протокол DHCP? DHCP (Dynamic Host Configuration Protocol) – это протокол настройки узла, который автоматически назначает IP-адреса компьютерам. Протокол DHCP – это дальнейшее развитие протокола BOOTP. Последний разрешает бездисковым клиентам запускать и автоматически конфигурировать протокол TCP/ IP. Протокол DHCP централизованно назначает IP-адреса в вашей сети и автоматически конфигурирует рабочие станции. Возможно, вы подумали, что в одной сети должен быть только один сервер DHCP, потому что в противном случае между серверами возникнет конфликт, а пострадавшим опять окажется клиент, который зависнет при загрузке. А вот и не так – в одной сети может быть несколько серверов DHCP. И это не только не отразится на производительности сети, но даже повысит надежность сети, если, например, один из серверов выйдет из строя.
Процессы в WinNT Как вы, наверное, знаете, Windows NT – это многозадачная ОС, а это значит, что вы можете создавать программным путём другие процессы и нити внутри процесса. Для создания процесса могут использоваться две основные функции: WinExec и CreateProcess. Первая из них очень проста в применении, имеет только два параметра и может использоваться для создания оконных процессов.