Оглавление
Squid + SquidGuard +…
И вот наконец мы добрались до того, ради чего, собственно говоря, всё и затевалось.
Идея системы фильтрации и значительная часть ее реализации позаимствована из статьи Андрея Бешкова «Система фильтрации интернет траффика на основе squidGuard + Apache + Squid + Berkeley DB». К ней я и отсылаю интересующихся обоснованиями выбора именно такой системы. Здесь же рассмотрим только ее практическую реализацию.
Squid
Для начала устанавливаем из портов прокси сервер Squid. У меня использована стабильная версия 2.6 и именно ей посвящено дальнейшее описание. Версию 2.5 (также имеющуюся в портах) не рекомендую, т.к. там несколько более запутанная настройка. С новой 3.0 не экспериментировал, потому не могу гарантировать, что вся система будет работать без изменений в настройках. Итак…
# cd /usr/ports/www/squid26
# make install
По окончании установки редактируем конфигурационный файл:
# ee /usr/local/etc/squid/squid.conf
У меня он выглядит вот так (естественно, здесь отсутствует множество строк комментариев — этот файл, как это обычно и бывает в мире *nix, содержит внутри себя подробную документацию):
# Минимальные рекомендуемые права: 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 acl to_localhost dst 127.0.0.0/8 acl SSL_ports port 443 563 # ssl acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp acl Safe_ports port 443 563 # https acl Safe_ports port 70 # gopher acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # unregistered ports acl Safe_ports port 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl CONNECT method CONNECT # Разрешаем управление только с localhost http_access allow manager localhost http_access deny manager # Запрещаем запросы к неизвестным портам http_access deny !Safe_ports # Запрещаем запрос CONNECT к чему-либо кроме портов SSL http_access deny CONNECT !SSL_ports # Открываем доступ к Squid всем, поскольку управлять # доступом у нас уже будет SquidGuard. Так что двойная # проверка ни к чему http_access allow all # # Дальше идет очень важная строка. Именно тут отличие от # предыдущих версий Squid. «прозрачный» прокси # теперь включается гораздо проще — указанием # параметра transparent # Обрабатываем запросы на порт 3128 localhost http_port 127.0.0.1:3128 transparent # # Что не должно кэшироваться. Просто рекомендованный # разработчиками вариант: hierarchy_stoplist cgi-bin ? acl QUERY urlpath_regex cgi-bin \? cache deny QUERY # Размер оперативной памяти, отводимой под кэш cache_mem 64 MB # Каталог, где будет находиться кэш # Число 4000 - размер кэша в мегабайтах, должен # быть, как минимум, на 20% меньше свободного пространства # в разделе диска cache_dir ufs /usr/local/squid/cache 4000 16 256 # Количество старых лог-файлов, которые нужно хранить # (по умолчанию 10, по-моему, даже 5 — много) logfile_rotate 5 # То, что будет подставляться в качестве пароля при # анонимном доступе к FTP-серверам ftp_user vasja@pupkin.ru # Если пользователь прервал загрузку, когда скачано # не менее 70% файла, завершить его загрузку в кэш quick_abort_pct 70 # Время жизни запросов, завершившихся ошибкой (напр., 404) negative_ttl 1 minutes # локальное имя или e-mail оператора, которому придет # сообщение в случае аварии прокси (в нашем примере, admin) cache_mgr admin # Чтобы видеть сообщения об ошибках по-русски: error_directory /usr/local/etc/squid/errors/Russian-koi8-r # Не включать IP адрес клиента в заголовок запроса: forwarded_for off # Разрешаем управлять кэшем с помощью cachemgr.cgi # В качестве пароля установим слово «secret» cachemgr_passwd secret all # Squid будет запускаться от имени пользователя squid # и группы squid (это нам еще понадобится) cache_effective_user squid cache_effective_group squid # Для поддержки клиентов, нестандартно закрывающих соединение half_closed_clients on
Все остальные параметры (а их гораздо больше, чем тут перечислено) можно оставить так, как они назначены по умолчанию.
Далее мы должны создать каталоги для кэша и лог-файлов, а затем сделать так, чтобы их «владельцем» стал именно тот пользователь, от имени которого будет выполняться Squid (в нашем примере его зовут squid — см. конфигурационный файл выше):
# mkdir /usr/local/squid/cache
# mkdir /usr/local/squid/logs
# chown -R squid:squid /usr/local/squid/cache /usr/local/squid/logs
Впоследствие могут пригодится и некоторые другие ключи для запуска Squid
-d
выводить на устройство stderr отладочную информацию-f <имя_файла>
запуск с другим файлом конфигурации-h
вывод справки-k reconfigure
отправка сигнала HUP (чтобы файл конфигурации был повторно прочитан; обычно используется после его изменений)-k shutdown
«вежливое» выключение-k interrupt
выключение, сразу разрывающее текущие соединения-k kill
принудительное прерывание работы-v
вывод информации о версии и ключах компиляции Squid-X
отладочный режим для разборки конфигурационного файла-F
ускоренное перестроение кэша после сбоя (но на время перестроения запросы не обслуживаются)
Далее необходимо создать в каталоге cache
иерархию каталогов кэша (в соответствии с записью в конфигурационном файле там должно быть 16 каталогов, в каждом из которых — по 16 подкаталогов). Конечно, мы не будем делать это вручную. Воспользуемся самим Squid’ом:
# /usr/local/sbin/squid -z
Готово. Теперь можем запустить прокси-сервер в работу.
# /usr/local/sbin/squid -D
Ключ -D
обозначает, что нам пока не нужно, чтобы Squid при запуске проверял работоспособность DNS-серверов (сейчас важно убедиться в работоспособности самого прокси).
Во время запуска на другой консоли (если мы работаем за компьютером непосредственно, консоли переключаются клавишами Alt+Fn, где n — номер консоли) или в другом терминальном окне (если работаем через SSH) наблюдаем за сообщениями, появляющимися в файле протокола:
# tail -f /var/log/messages
Вообще команда tail
предназначена для вывода нескольких (по умолчанию, десяти) последних строк файла. Но добавление ключа -f <имя_файла>
превращает ее в средство отслеживания добавляющихся в файл строк. Чтобы прервать ее работу в этом случае используют сочетание клавиш Ctrl+C.
Если всё сделано правильно, ошибок там не появится. А когда мы увидим что-то похожее на
Jul 9 11:22:49 sch415 squid[3792]: Squid Parent: child process 3794 started
,
значит, Squid заработал. Можем попробовать позаходить на разные сайты с компьютеров локальной сети, а затем посмотреть файлы протоколов (они у нас, напомню, в /usr/local/squid/logs
).
Apache
Вообще-то, Apache — очень совершенный http-сервер (на таких «живет» большая часть Интернет). Но у нас он будет подменять те сервера, которые мы, по той или иной причине, решили от пользователей закрыть. Как мы уже поступали со многими программами, установим сервер из портов:
# cd /usr/ports/www/apache13
# make install
Заметьте, мы устанавливаем версию 1.3, хотя в портах есть и 2.*. Эти версии существенно отличаются.
Запускаем Apache:
# /usr/local/apache/bin/apachectl start
Создаем каталог, в котором будут лежать файлы-подменки:
# mkdir /usr/local/apache/htdocs/replace
Помещаем туда (любым возможным способом: загрузкой с помощью links, копированием и т.п.) файлы 1x1.gif
(он будет передаваться клиентам вместо баннеров), my.mp3
(маленький огрызок мелодии, который получит каждый желающий загрузить музыку), возможно, еще какие-либо картинки и т.п.
В каталог /usr/local/apache/cgi-bin
помещаем специальный сценарий на perl — block.cgi. Он будет выводить сообщение при попытке посетить запрещенную страницу. Можно использовать либо оригинальный squidGuard.cgi.in из пакета SquidGuard, но лучше взять переведенный Андреем Бешковым. Чтобы скрипт смог работать, ему нужно выставить соответствующие права:
# chown nobody:wheel /usr/local/apache/cgi-bin/block.cgi
# chmod 500 /usr/local/apache/cgi-bin/block.cgi
Berkeley DB
Для работы SquidGuard необходима база данных, где будут храниться запреты. В этом качестве используется Berkeley DB. А она, в свою очередь, использует библиотеку libtool. На момент написания статьи ее актуальная версия — 1.5.26. Установка обычным способом из портов у меня не сработала (да, ошибки встречаются везде), потому пришлось загрузить архив с сайта (нужно воспользоваться ссылкой «Download this directory in tarball»), распаковать его и полностью выполнить процедуру сборки и инсталляции.
# tar zxvf libtool15.tar.gz
# cd libtool15
# make
(после этой команды будет выполнена загрузка исходников, которая может занять достаточное время при медленном канале, а затем компиляция)
# make install
При выполнении дух последних команд смотрим внимательно на появляющиеся сообщения, если что-то происходит не так, наиболее важная информация для понимания причин неприятности будет в последних строчках.
После установки libtool займемся Berkeley DB. Тут процесс будет заметно более сложным. Для начала нам нужно загрузить исходный код и два патча. Внимание! Нужна версия 3.2.9. Я не перепроверял, но по данным Андрея Бешкова только она может быть успешно собрана под FreeBSD. Распаковываем архив исходников, копируем в него оба патча и применяем их по очереди:
# tar zxvf db-3.2.9.tar.gz
# cp patch.3.2.9.1 patch.3.2.9.2 ./db-3.2.9
# cd db-3.2.9
# patch -p0 < patch.3.2.9.1
# patch -p0 < patch.3.2.9.2
А дальше — компилируем и устанавливаем:
# cd build_unix
# ../dist/configure
# make
# make install
SquidGuard
Ну, вот дело дошло и до последнего компонента нашей системы — редиректора SquidGuard. Его мы, как и предыдущие программы, соберем из исходников. Начнем с их загрузки с www.squidguard.org. Затем распакуем, скомпилируем и установим:
# tar zxvf squidGuard-1.3.tar.gz
# cd squidGuard-1.3
# ./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
# make
# make test
# make install
Обратите внимание на «страшную» команду configure
(эти несколько строк именно одна команда). В ней мы указали: 1) куда будет установлен SquidGuard; 2) где находится библиотека BercleyDB; 3) где будет лежать файл конфигурации программы; 4) куда будут записываться файлы протоколов и 5) где будет база данных блокируемых сайтов. Естественно, ошибиться при вводе этой команды крайне нежелательно.
Создаем каталог для протоколов:
# mkdir /usr/local/squidGuard/log
Теперь нам нужен список «нехороших» сайтов. В сети есть несколько источников таких списков. Я воспользовался помощью наших американских коллег. Загружаем список. Распакуем его и перенесем в каталог, заданный при конфигурации:
# tar zxvf blacklists.tgz -C /usr/local/squidGuard
# mv /usr/local/squidGuard/blacklists /usr/local/squidGuard/db
В появившихся подкаталогах будут находиться файлы domains (домены, блокируемые целиком), urls (если нужно блокировать страницу, а не весь домен) и expression (регулярные выражения, определяющие, какие подстроки запрещены в url).
База | Комментарии |
---|---|
ads | реклама |
adult | сайты для взрослых |
aggressive | агрессия |
audio-video | музыка и видео |
forums | форумы |
drugs | наркотики |
gambling | азартные игры |
hacking | хакерство |
local-block | сайты заблокированные местным админом |
local-ok | сайты разрешенные местным админом |
бесплатные почтовые сервера | |
porn | порнография |
proxy | общедоступные прокси сервера |
publicite | опять реклама |
redirector | анонимные прокси сервера |
violence | насилие |
warez | пиратское програмное обеспечение |
К этой базе добавим еще базу баннеров (banners).
Теперь нам необходимо настроить SquidGuard. Создаем файл squidGuard.conf
# ee /usr/local/squidGuard/squidGuard.conf
Выглядеть он может примерно так:
# куда записывать протоколы: logdir /usr/local/squidGuard/log # где находится база данных: dbhome /usr/local/squidGuard/db # # Дальше описываем диапазоны адресов для разных групп пользователей # === ИТ инфраструктура src it-computers { ip 10.0.1.1, 10.0.1.100, 10.0.1.210 } # === Компьютерные классы src nachalka { ip 10.0.1.50-10.0.1.56 } src r33 { ip 10.0.1.211-10.0.1.222 } src books { ip 10.0.1.101-10.0.1.113 } # === Библиотека src library { ip 10.0.1.238 } # === Работники школы src staff { 10.0.1.231-10.0.1.254 } # ============= # При попытке загрузить запрещенные типы файлов подменяем их: rewrite media { s@.*\.mp3$@http://10.0.1.1/replace/my.mp3@r s@.*\.swf$@http://10.0.1.1/replace/noflash.jpg@r s@.*\.flv$@http://10.0.1.1/replace/noflash.jpg@r s@.*\.wmv$@http://10.0.1.1/replace/stop300.gif@r s@.*\.mov$@http://10.0.1.1/replace/stop300.gif@r s@.*\.exe$@http://10.0.1.1/replace/stop300.gif@r log rewr } # Теперь отметим, какие базы и как будут использоваться # Порнографию просто отрубаем с записью в протокол dest porn { domainlist porn/domains urllist porn/urls log porn } # рекламные картинки и баннеры заменяем на 1-пиксельный GIF dest ads { domainlist ads/domains urllist ads/urls log ads redirect http://10.0.1.1/replace/1x1.gif } dest banners { domainlist banners/domains urllist banners/urls # expressionlist banners/expressions log banners redirect http://10.0.1.1/replace/1x1.gif } # Сайты и страницы, не требующие проверки dest local-ok { domainlist local-ok/domains urllist local-ok/urls } # Сайты, добавленные к базе (из Америки видно не всё ;-)) dest local-block { domainlist local-block/domains urllist local-block/urls log local-block redirect http://10.0.1.1/cgi-bin/block.cgi?clientaddr=%a&clientname=%n &clientident=%i&clientgroup=%s&targetgroup=%t&url=%u } # Теперь распределяем, каким группам пользователей что можно acl { # пропускать все, кроме рекламы: it-computers { pass local-ok !banners !ads all } # в компьютерных классах ограничений больше всего: nachalka { pass local-ok !porn !banners !ads !local-block all rewrite media } r33 { pass local-ok !porn !banners !ads !local-block all rewrite media } # а здесь разрешим загружать музыку и т.п. books { pass local-ok !porn !banners !ads !local-block all } library { pass local-ok !porn !banners !ads !local-block all } staff { pass local-ok !porn !banners !ads !local-block all } # с компьютеров, не входящих в группы, доступ к Интернет закрыт: default { pass none redirect http://10.0.1.1/cgi-bin/block.cgi?clientaddr=%a &clientname=%n&clientident=%i&clientgroup=%s&targetgroup=%t&url=%u log default } } # === end of acl
Установим права на служебные файлы и каталоги (сделаем их владельцем пользователя, от имени которого будет работать SquidGuard):
# chown -R nobody /usr/local/squidGuard/log /usr/local/squidGuard/db
# chown nobody /usr/local/squidGuard/squidGuard.conf
Чтобы SquidGuard не строил при каждом запуске базы данных в оперативной памяти, напишем сценарий, который построит их (сохранив на диске) и перезапустит Squid (и с ним SquidGuard):
# ee /usr/local/squidGuard/bin/rebuild_base.sh
#!/bin/sh /usr/local/squidGuard/bin/squidGuard -C all chown -R squid /usr/local/squidGuard/db /usr/bin/killall -HUP squid
Установим необходимые права (этот сценарий должен иметь право запускать только root, а остальным с ним вообще ничего делать нельзя), а затем запустим его:
# chmod 100 /usr/local/squidGuard/bin/rebuild_base.sh
# /usr/local/squidGuard/bin/rebuild_base.sh
Теперь ждем, когда задача будет завершена. Процесс не слишком быстрый. Затем протестируем работу SquidGuard. Воспользуемся написанной опять же Андреем Бешковым маленькой тестовой программкой на Перле. Загружаем архив, распаковываем его и помещаем полученный файл test.pl в каталог /usr/local/squidGuard/bin. Устанавливаем ему разрешение на исполнение, запускаем и вводим тестируемый IP-адрес. В файле result.txt смотрим результат. (Там, где результат — пустая строка, сайт будет доступен, во всех остальных случаях показана строка, на которую произойдет перенаправление Squid’а) Набор сайтов можно поменять, отредактировав сценарий. Если результаты теста нас удовлетворили, подключим SquidGuard к Squid. Для этого в файл /usr/local/etc/squid/squid.conf
добавим следующие строки:
# если не отвечает ни один экземпляр SquidGuard, работать напрямую redirector_bypass on # где находится SquidGuard redirect_program /usr/local/squidGuard/bin/squidGuard # сколько экземпляров SquidGuard запускать redirect_children 10 #
Перезапускаем Squid (а редиректоры он уже [пере]запустит сам):
# killall -HUP squid
Если после этого в конце файла протокола /usr/local/squidGuard/log/squidGuard.log появились строки, подобные:
2008-07-10 14:57:54 [1285] squidGuard 1.2.0 started (1215687474.577)
2008-07-10 14:57:54 [1285] squidGuard ready for requests (1215687474.645)
…значит все запустилось нормально. Теперь сделаем, чтобы наша система запускалась автоматически при загрузке компьютера. Для этого внесем два сценария в «стартовый каталог» FreeBSD rc.d:
# ee /usr/local/etc/rc.d/apache.sh
#!/bin/sh /usr/local/apache/bin/apachectl start
# ee /usr/local/etc/rc.d/squid.sh
#!/bin/sh /usr/local/sbin/squid -D
# chmod 100 /usr/local/etc/rc.d/apache.sh /usr/local/etc/rc.d/squid.sh
Перезагружаем компьютер, убеждаемся, что все нормально работает.
Для полного счастья админа школьной сети недостает только автоматического обновления баз блокируемых сайтов. Что делать?— естественно, писать сценарий. Базу надо скачать, распаковать, перенести в каталог баз данных SquidGuard, после чего запустить уже имеющийся сценарий перегенерации БД:
# ee /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/db rm -R /usr/local/squidGuard/update/blacklists /usr/local/squidGuard/rebuid_base.sh
Устанавливаем права:
# chmod 100 /usr/local/squidGuard/bin/update_blacklist.sh
Создаем временный каталог для распаковки:
# mkdir /usr/local/squidGuard/update
И настраиваем планировщик cron на периодическое выполнение сценария обновления:
# crontab -e -u root
Запускаем редактирование (-e) таблицы периодических заданий пользователя (-u) root. Для просмотра таблицы нужно было бы использовать ключ -l.
Запустится указанный в настройках ОС текстовый редактор (по умолчанию это vi). С его помощью дополним файл примерно такой строкой:
1 15 * * 5 /usr/local/squidGuard/bin/update_blacklist.sh
Она означает, что файл update_blacklist.sh должен запускаться каждую пятницу (5 день недели) в 15 часов 1 минуту. Правильнее было бы назначать обновление на ночное время (например, на 2 часа и сколько-то-там минут), но мы по правилам не можем оставлять компьютеры включенными на ночь.
vi — редактор с непривычным для людей не из мира *nix интерфейсом. Для выхода из него нужно сделать следующее:
— нажимаем Esc — редактор переходит в командный режим
— нажимаем : (двоеточие, оно появится в нижней строке экрана) — редактор переходит в расширенный режим
— набираем wq<Enter> — файл сохраняется и завершается работа с редактором.
Вот, собственно говоря, и всё. Два учебных года — полёт нормальный. Помимо добавления нескольких адресов в список запрета, никаких дополнительных телодвижений. Утром щелкнул выключателем, вечером — shutdown -h now. Бывало, в нарушение правил, машинка (P-II/333MHz/256M) работала по несколько суток не выключаясь.
PS Заметка была написана почти два года назад. С тех пор система умудрилась проработать полтора года практически без участия человека (и почти без выключения). Единственная поломка — выход из строя… одной из сетевых карт.