...
...
...

«персональным» файрволлам найдется место в «корпоративном» мире

О файрволлах в бумажной и электронной прессе написано очень много, и СР — не исключение. И мне казалось, что мы не скоро вернемся к этой набившей уже оскомину теме, если бы не один вопрос, опубликованный на «Трибуне» редакции «Компьютерной Газеты». Этот вопрос, хоть и имеет в своей основе совершенно частную проблему, натолкнул меня на мысль о том, что многие люди имеют достаточно однобокое представление о файрволлах и о том, какие проблемы можно решать с их помощью.
Но обо всем по-порядку. А начнем мы с того самого «злополучного» вопроса.

постановка задачи


Дано: терминальный сервер с кучей народу. Куча делится на привилегированных пользователей (aka админы) и все остальные. Имеется отдельный шлюз для доступа в Интернет с прокси-сервером. Связь между ними — по локальной сети.
Задача: сделать так, чтобы все могли работать в локальной сети, а также в Интернете через прокси, но только избранные могли ходить в Интернет в обход прокси (то есть напрямую).
Можно ли такое организовать ? Если да, то как ?

Далее автор вопроса дает некоторые уточнения, а также предлагает один из возможных вариантов решения.

Вся сложность в том, что пакетный фильтр+NAT ничего не дадут — адрес у машины один и тот же для всех. То есть, либо к каждому пакету лепится маркер с идентификатором пользователя, по которому фильтр шлюза определяет, что с пакетом делать. Либо это дело строится прямо на терминальном сервере.

матчасть

Как обычно, начнем мы с теории.
/* Поскольку изначально вопрос касался win32-системы (терминальный сервер на базе одной из версий NT/2000/2003), некоторые термины в моем дальнейшем рассказе будут иметь отношение именно к «виндошным» реалиям. С другой стороны, замените winsock на NET4, терминальный сервер на X-сервер — и задачка как будто уже про Linux. */

А вопросец на самом деле очень даже интересный. Я думаю, даже не все оценили, в чем именно тут прикол. А прикол в терминальном сервере: один IP-адрес, один на всех winsock и толпа пользователей с неравными правами на использование всего этого богатства.
Идея с маркировкой пакетов, предложенная автором вопроса, конечно, очень милая, но при отсутствии стандартных (кем-то уже написанных) механизмов для этого нам грозит куча нетривиального программизма.
Но можно пойти и другим путем.

Итак, что нам нужно? Чтобы сетевая подсистема по разному вела себя с различными пользователями: трафик одних, допустим, просто маршрутизировала (на какой-нибудь NAT или в «мир», если IP-адрес реальный), а других пускала только на хост:порт нашего прокси.
И, похоже, единственный шанс у нас — как-то повлиять на единственный и неповторимый (в рамках нашей системы) winsock. Вариантов видится 2 штука:
1. подмена winsock’а;
2. некая "третья сила", работающая "между" winsock’ом и системой и решающая, что отдавать винсоку, а что, может быть, и не стоит ;)
Библиотеки, подменяющие winsock (обычно, сохраняющие его базовый функционал и добавляющие еще что-то) в природе существуют, но обычно они служат для других целей: скажем, трассировки активности winsock. Писать такую библиотеку самим, дабы решить не самую жизненно важную проблему, нам лень, правда? ;)

Итак, обратимся к варианту номер 2. Что есть обозначенная мной «третья сила»? Это что-то, работающее (если речь идет о Windows) на уровне NDIS или TDI (RTFM на эту тему здесь: http://www.nestor.minsk.by/sr/sr0102/sr10210.html). Называться может пакетным драйвером или модулем ядра. Однако с «голым» драйвером/модулем мы каши не сварим: нужен еще некий пользовательский софт для управления ими.

И такие модули/драйверы/софт уже есть в природе, нам не придется писать их с нуля.
Таким образом, мы плавно подошли к теме, которой, собственно и посвящена статья: «локальный» и «шлюзовый» файрволлинг /* устоявшейся терминологии, к сожалению, на этот счет не придумано, так что я опять фантазирую ;) */.
Локальные файрволлы — чаще их называют "персональные", но понятие "локальные" IMHO лучше отражает их суть и не вызывает негативной реакции у корпоративных админов ;) — в отличие от традиционных (шлюзовых) файрволлов, имеют дело не с транзитным трафиком, а с трафиком, имеющим в качестве цели/источника ту же машину, на которой установлены.

Из за этого у них есть весомое преимущество: они могут принимать решения не только на основе стандартных вещей — содержимого заголовков пакетов (IP, TCP etc.), содержимого самих пакетов, их размера и пр. — но и таких параметров, как сервис, инициировавший передачу по сети и запустившего этот процесс пользователя /* это как раз важно в рамках решаемой нами задачи */.
Напротив, шлюзовые файрволлы, как было сказано выше, могут работать только с тем материалом, что есть в проходящих по сети пакетах. А навешивать на пакеты всевозможные маркеры не всегда представляется возможным.

Лирическое отступление: готова поспорить, что задав вопрос «Что такое файрволл?» двум группам респондентов — корпоративным администраторам и домашним пользователям, первые опишут шлюзовый файрволл, а вторые — локальный ;)
Справедливости ради следует отметить, что локальный и шлюзовый файрволлинг могут уживаться в рамках одного продукта. Так, Winroute (продукт под win32, как можно догадатся по названию) и Linux’овый netfilter могут с равным успехом работать и как шлюзовый файрволл, и как локальный, и как то и другое одновременно :)

решение задачи

Собственно, задачу-то мы уже почти решили: мы выяснили, что нашу проблему может решить локальный файрволл с поддержкой фильтрации по пользователям, инициировавшим то или иное соединение. Соответственно, мы настраиваем файрволл таким образом, чтобы трафик непривелегированных пользователей блокировался по всем направлениям и протоколам, кроме разрешенных. В рамках нашей задачи разрешены будут TCP-соедиения на порт корпоративного прокси-сервера, а также любые соединения с хостами локальной сети. Привелегированным же пользователям мы отдельной директивой (в контексте файрволлов такие директивы называются правилами (rules) разрешаем все и вся. Вот приблизительная «блок-схема» нужных правил (на выдуманном алгоритмическом языке, поскольку языки описания правил в конкретных продуктах сильно отличаются друг от друга):

разрешить админу исх. все
разрешить всем исх. на 192.168.0.1 порт 8080 протокол TCP
запретить всем исх. на 192.168.0.1
разрешить всем исх. на 192.168.0.0
запретить всем исх. все


где 192.168.0.1 — адрес корпоративного прокси-сервера, 8080 — его порт.
Мы бы могли, в принципе, ограничиться и тремя правилами —

разрешить админу исх. все
разрешить всем исх. на 192.168.0.0
запретить всем исх. все

но в таком случае остается возможность, что пользователи установят на хосте 192.168.0.1 какую-нибудь пакость вроде альтернативного прокси-сервера, порт-редиректора или что-то плана HTTPort и будут безобразничать в обход заданной политики использования сети. Поскольку в постановке задачи ничего про возможность/отсутствие доступа пользователей на 192.168.0.1 не сказано, я сочла разумным перестраховаться :)

Также замечу, что мы ограничились описанием только правил для исходящего трафика, поскольку правила по входящему не принесут особой пользы (нет запроса — нет и ответа), но изрядно перегрузят таблицу правил, да и ошибиться при таком раскладе больше шансов.
Правила файрволлов (во всех продуктах) «читаются» программой с верху вниз, то есть каждый пакет последовательно сравнивается с описанием, данным в каждом из правил, и как только обнаружится первое совпадение — правило срабатывает, определяя судьбу пакета: он будет или отброшен, или пойдет в работу: в сеть (если он исходящий) или прикладной программе (если входящий). Стало быть, если админу в нашем примере надо будет все же что-то запретить, это правило следует поставить выше чем «разрешить админу все».
Ну, с теорией файрволлов вы уж и сами как-нибудь разберетесь, к тому же это выходит за рамки обсуждаемой в статье темы.

а в реальном мире...

... мы лезем, например, в Google и ищем файрвольный софт, отвечающим нашим требованиям.
Мне вот, прежде чем лезть в Google, вспомнилось, что хорошие, продвинутые сетевые софты под win32 в свое время писали чехи, называемые нынче TINY Software (авторы незабвенного WinRoute).
И действительно, читаем в разделе фич Tiny Personal Firewall:

Full Support for Multiuser Environment. The all new Tiny Software's security technology allows to create the rules for specific applications running under specific accounts and apply them simultaneously on the Windows 2000, Windows 2000 Server, Windows XP Home and Pro and Windows 2003 Server computers. Tiny's Security platform is the only solution with such capabilities on the market and targets all multi-user environments — from Windows XP Professional to Windows 2000 and Windows 2003 Terminal Servers.

Ну, насчет единственных на рынке может и врут, не проверяла ;) Однако фича работает как заявлено, что нам и нужно.
Tiny Personal Firewall «умеет» и другой функционал, характерный для локального файрволла: реализована фильтрация по day&time и приложениям-инициаторам соединений (задается в виде имени исполняемого файла).

Интерфейс, правда, показался мне несколько неудобным: среди обилия возможностей трудно найти простой путь сделать совершенно обыкновенные вещи, задать элементарные файрвольные правила. Но привыкнуть можно, разобраться не сложно (продукт позиционируется на домашний рынок). Если повырубать излишний функционал, продукт вполне можно приспособить для защиты сервера под win32, и в том числе для решения нашей задачки.

Скриншот с настройкой файрволла по «блок-схеме» из предыдущей главы см. на рис. 1.
Также обратите внимание на группы приложений, которым можно инициировать трафик. Сдается мне, что тип трафика IP Protocol Range (любой IP-трафик) доступен только для группы системных приложений, ат редактировать эту группу нельзя. В таком случае придется переписать правила, заменив везде одно правило с IP Protocol Range на два — для UDP/TCP и ICMP. Сути это не меняет, просто почти в два раза больше правил :(

Теперь пару слов о решении аналогичной задачки под Linux (ну куда же мы без Linux, это же модно! ;)
Как я уже говорила, netfilter (подсистема фильтрации пакетов в современных ядрах (от 2.4.х), мы о нем писали как-то в СР — http://www.nestor.minsk.by/sr/sr0102/sr10202.html) наделен функционалом локального файрволлинга. Он, в частности, умеет фильтровать пакеты по инициатору сессии (владельцу, Owner match). Предусмотрены следующие ключи: --uid-owner, --gid-owner, --pid-owner и --sid-owner. Аббревиатуры эти, надо понимать, в разъяснении не нуждаются (в противном случае мне ничего не остается, как отправить вас к документации по основам UNIX-подобных систем). Через Patch-O-Matic (система патчей для netfilter) доступна также date&time-фильтрация.
Вот как будут выглядеть правила файрволла (фрагмент) для netfilter:

iptables -A OUTPUT -m owner --uid-owner 100 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.1 –p tcp –dport 8080 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.1 -j DROP
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT
iptables -A OUTPUT -d 0.0.0.0/0 -j DROP


где 100 (в первой строке) — идентификатор (UID) привелегированного пользователя, 192.168.0.1 — адрес корпоративного прокси-сервера, 8080 — его порт.
Так же, как в примере с Tiny Personal Firewall, мы ограничиваемся только запретами/разрешениями на исходящий трафик: можно заметить, что все правила, решающие нашу задачу, находятся в цепочке OUTPUT.

послесловие


Пока эта статья рождалась на свет, на «Трибуне» разгорелась полемика на тему, весьма характерную для этой виртуальной тусовки: решение под какую ОС (Linux или Windows, экзотика там обсуждается редко;) более изящное, простое и вообще самое-самое.
Вот, скажем, что написал нам некто harryk:

«Красиво... Под Lin — две строчки, под Win — а не поставить ли вам, господа, дополнительный крутонавороченный локальный фаер, а то и еще чего похлеще... Обсудив исходный вопрос с коллегой, пришли к общему выводу — под Win решить этот вопрос с минимальными (лучше всего — с никакими :) затратами довольно затруднительно. Последующее обсуждение это подтвердило...».
Так вот что я вам скажу на это: представленные мной решения под обе платформы абсолютно идентичны по сути своей! Что значит «под Linux — две строчки?» Почему мы забываем про то, что чтобы это все заработало, в системе должны присутствовать файрволльный модуль netfilter (его поддержку надо включить при компиляции ядра) и фронт-энд к нему — программа iptables. Драйверы Tiny Personal Firewall — это также модули ядра, а фронт-эндом к ним выступает GUI программы.

Кто-то может заметить, что Tiny Personal Firewall — это «левый», third party софт, а netfilter — «встроенный» функционал Linux. Но, во-первых, «встроенность» применительно к Linux — это вообще понятие относительное: Linux пишут тысячи людей по всему миру, каждый поставщик этой системы волен компоновать и распространять ее в той комплектации, в которой сочтет нужным. Теоретически, может существовать дистрибутив, не включающий в себя netfilter. Таким образом, комманда разработчиков netfilter — тоже своего рода third party :)

Во-вторых, кто вообще сказал, что прикладной софт — а файрволл разве таковым не является? — обязан поставляться вместе c ОС? Забавная получается идеология: линуксоиды, клянущие Microsoft по поводу монополизма в виде принудительных поставок вместе с ОС прикладного софта (браузер, почтовый клиент) совершенно аналогичную свою деятельность (поставка файрволла вместе с системой) считают неоспоримым достоинством :)
В общем, не будем мы, коллеги, ввязываться в глупые OS holy wars. Хороший сетевик не должен быть ни линуксоидом, ни цискоидом, ни виндусятником, ни зикселятником... Хороший сетевик, при необходимости, заставит работать в сети любое устройство, даже кофеварку.

Да, некоторые вещи изначально лучше приспособлены к работе в сети, некоторые хуже, но, тем не менее, при опеределенной смекалке, под любую аппаратную и программную платформу можно найти оптимальное сетевое решение, решающие ваши прикладные задачи.

Автор благодарит XMan’а за интересный вопрос, варианты решения задачи и замечания по ходу обсуждения этой проблемы на «Трибуне».
Alice D. Saemon.


© Сетевые решения