Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #113, МАЙ 2008 г.

Рецепты приготовления кальмара

Сергей «grinder» Яремчук (grinder@ua.fm, tux.in.ua)

Хакер, номер #113, стр. 113-132-1

Squid: настраиваем контроль доступа и оптимизируем кэш

Когда нужно предоставить совместный доступ к Web-сервисам с возможностью кэширования трафика, в первую очередь вспоминают о кэширующем прокси-сервере Squid. Это гибкое решение применяют и в мелких офисах с несколькими пользователями, и в корпоративных сетях со сложной топологией. Разберем, как настроить в Squid самые популярные функции – контроль доступа и работу с кэшем.

Установка Squid

Для новичков - пара слов о самом Squid. Squid, он же «кальмар» (www.squid-cache.org) – приложение, позволяющее организовать прокси/кэширующий сервер для HTTP, FTP и некоторых других популярных протоколов. Поддерживается работа с защищенными TLS/SSL соединениями, кэширование DNS, возможно использование Squid в качестве прозрачного или реверсного прокси. Распространяется по лицензии GNU GPL. Работает во всех популярных вариантах Unix систем – GNU/Linux, *BSD, Mac OS X, SunOS/Solaris. Есть версия для Windows.

В качестве примера буду использовать Ubuntu, но сказанное относится и к остальным дистрибутивам или ОС (со скидкой на особенности установки в каждом конкретном случае). Отметим, что сейчас параллельно развиваются две ветки: 2.x и 3.x. Третья ветка перешла в разряд STABLE в конце прошлого года, и разработчики рекомендуют ее к использованию. В репозитарии Ubuntu 6.06 LTS Dapper Drake находится пакет с версией Squid 2.5, в последнем 7.10 – 2.6.14. Также в репозитариях всех Ubuntu, начиная с Festy Fawn (7.04), есть и пакеты с третьей версией Squid. По описываемым в статье параметрам отличий у них практически нет.

Установка кальмара в Ubuntu довольно проста:

$ sudo apt-get install squid squid-common

Или, для Squid 3:

$ sudo apt-get install squid3 squid3-common

После инсталляции Squid будет запущен с установками по умолчанию. При первом запуске возможна ошибка «FATAL: Could not determine fully qualified hostname. Please set 'visible_hostname'». Это значит, что по дефолту разрешение имени узла, на котором работает Squid, осуществляется при помощи gethostname(). В зависимости от установок DNS он иногда не может однозначно определить имя, которое будет фигурировать в журналах и выводах об ошибках «Generated … by server.com (squid/3.0.STABLE2)», поэтому просит тебя помочь.

Все настройки Squid производятся в единственном файле /etc/squid/squid.conf. В нем до невероятности много параметров и бросаться менять их все и сразу не стоит. Просмотреть список параметров, убрав пустые и закомментированные строки, можно при помощи команды:

$ sudo grep -v "^#" /etc/squid/squid.conf | sed -e '/^$/d'

Формат squid.conf стандартен для Unix. Каждая запись состоит из строк вида: «параметр значение». Строки, начинающиеся со знака решетки, – комментарии. Для удобства настройки все параметры разбиты по секциям. Разбиение чисто условно и свои параметры можно заносить в любое место файла. Возможно подключение внешнего файла с настройками при помощи include. Помни, что установки применяются в порядке очередности.

Для начала запустим Squid, устранив ошибку, указанную выше. Заносим в конфиг строку с именем сервера Squid (необязательно должно совпадать с доменным):

visible_hostname mysquid

И запускаем:

$ sudo /etc/init.d/squid start

В настройках по умолчанию сквид принимает входящие соединения на 3128/tcp. Командой «netstat –ant | grep 3128» проверяем, слушается ли этот порт. Если все OK, настраиваем веб-браузер для работы через прокси-сервер и выходим в Сеть. Но сейчас это возможно только с localhost. Чтобы в интернет могли попасть остальные пользователи локальной сети, нужно установить соответствующие разрешения, используя контроль доступа.

Настраиваем доступ

Изменив параметр http_port, мы можем подвесить Squid только на внутренний сетевой интерфейс:

http_port 192.168.0.1:3128

Чтобы разрешить всем пользователям сетей 192.168.0.0, 172.16.0.0 и компьютера 192.168.1.1 подключаться к Squid, добавляем описание нового списка доступа в секцию «ACCESS CONTROL»:

acl localnet src 192.168.0.0/24 172.16.0.0/12 192.168.1.1

Переменные чувствительны к регистру, но, применив параметр «acl –i», это можно исправить. Чуть дальше покажу, как. Если нужно настроить доступ не для всей сети, а для отдельных ее узлов, проще записать их адреса в файл (по одному в строке), который и указать в качестве последнего параметра. Третья строка – тип списка доступа. В нашем случае используется src (от source). При помощи других параметров можно задать внешний адрес (dst), МАС-адрес (arp), доменное имя (srcdomain, dstdomain), порт (port), протокол (proto), время (time) и многое другое. Фактически, работа по организации доступа сводится к описанию объекта в acl, а затем разрешению или запрету работы объекта при помощи http_access с требуемыми параметрами. Например, чтобы указать рабочее время, применим такую конструкцию:

acl work_hours time M T W T F 9:00-18:00

В описании используются первые буквы английского языка, соответствующие дням недели. В секции «ACCESS CONTROL» уже описаны некоторые ACL, в частности, описываются номера некоторых портов (привожу не все) и ACL, соответствующий всем адресам:

acl SSL_ports port 443 563 873

acl Safe_ports port 80 21 443 563 1025-65535

acl all src 0.0.0.0/0.0.0.0

Следует внимательно просмотреть весь список и закомментировать строки с портами не нужных или не используемых сервисов.

Когда списки составлены, при помощи параметра http_access разрешаем или запрещаем доступ указанному ACL. Общий формат вызова такой:

http_access allow|deny [!]название_ACL

Восклицательный знак инвертирует значение списка, то есть звучит как «все кроме». По умолчанию используется правило:

http_access deny all

Его мы обязательно помещаем в конец списка рулесетов. В этом случае все соединения, которые не разрешены явно, будут блокированы. Майнтэйнеры, собирающие пакеты в дистрибутивах, как правило, добавляют и несколько своих правил.

Чтобы разрешить подключение к Squid с указанных адресов и работу только с нужными портами, пишем:

http_access allow localnet

http_access deny !Safe_ports

http_access deny !SSL_ports

Сохраняем результат и перезапускаем Squid:

$ sudo /etc/init.d/squid restart

Проверяем. Если все нормально, идем дальше. Чтобы не перестраивать клиентские системы, проще использовать iptables:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 \

-j DNAT --to-destination 192.168.0.1:3128

iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 \

-j REDIRECT --to-ports 3128

А вот еще один пример. Нам нужно, чтобы компьютеры с определенными IP могли выходить в инет только в рабочее время. Без проблем:

acl workip src 192.168.1.100 192.168.1.200-192.168.1.210

http_access deny !work_hours workip

Можно разбить это правило на два, сделав более читабельным:

http_access allow work_hours workip

http_access deny workip

Первая строка разрешит доступ при совпадении двух ACL: рабочее время и IP-адрес. Вторая запретит доступ всех записанных в ACL workip при несовпадении с первым правилом (то есть в другой временной промежуток).

Режем баннеры и сайты

Одна из функций, которая делает Squid востребованным, – возможность запрета доступа к определенным ресурсам интернет. Это реализовано на той же сладкой парочке: acl и http_access. Зная адрес ресурса, можно просто закрыть доступ к конкретному адресу или целой подсети:

acl denynet dst 194.55.0.0/16

http_access deny denynet

Но вместо того, чтобы использовать адрес, удобнее при помощи dstdomain указывать домен назначения. Например, запретим доступ к сервисам вроде RapidShare:

acl rapida dstdomain .rapidshare.com .rapidshare.de

http_access deny rapida

Если в сети есть юзеры, которым разрешено все (начальство не любит, когда их куда-то не пускают), то запрещающее правило можно дополнить списком адресов:

http_access deny workip dstdomain

Это самый простой способ, но далеко не самый удобный. Юзвери, не попав на любимый ресурс, быстро бросятся на поиск альтернативы и, естественно, ее найдут. Поэтому адреса в ACL удобнее задавать при помощи регулярных выражений:

acl adult dstdom_regex sex

acl regexdomain dstdom_regex \.com$ \.net$ \.tv$

http_access deny adult regexdomain

Сейчас мы запретили доступ ко всем все доменам, содержащим слово «sex», и всем доменам в зонах .com, .net и .tv.

Аналогичным образом блокируется и определенный контент, но вместо dstdom_regex используется url_regex или urlpath_regex. С их помощью указывается шаблон регулярного выражения для URL. Второй отличается тем, что не нужно заботиться о пути URL (при описании исключается домен). Например, создадим описания расширений видео, флэш и музыкальных файлов и запретим обращение к таким ссылкам. В этом случае urlpath_regex подходит больше, но приведу оба варианта для примера. Чтобы игнорировался регистр символов, используем ключ '-i':

acl videofiles url_regex –i *\.avi$ *\.mpg$ *\.mp4$ *\.swf$

acl soundfiles urlpath_regex -i \.mp3$ \.asf$ \.wma$

http_access deny videofiles soundfiles

Кстати, для хранения URL удобно использовать отдельный файл:

acl blockfiles urlpath_regex -i "/etc/squid/blocks.files.acl"

http_access deny blockfiles

Заносим в него данные о расширениях:

$ sudo nano /etc/squid/blocks.files.acl

\.exe$

\.avi$

\.mpg$

\.mpeg$

\.mp3$

При изменении содержимого этого файла следует перезапускать Squid.

Иногда бывает полезным выводить информационную страничку, чтобы пользователь знал, что он пытается получить доступ к запрещенному URL и его блокируют. Для этого используется параметр deny_info, который находится в секции «ERROR PAGE OPTIONS». В качестве параметров следует передать файл или URL, который будет выведен пользователю, и ACL, к которому относится данный deny_info. Файл должен находиться в подкаталоге /etc/squid/errors в формате HTML. Кроме того, на каталог для сообщений об ошибках показывает переменная error_directory (в Ubuntu по умолчанию /usr/share/squid/errors/English). Добавляем в squid.conf:

deny_info ERR_BLOCKED_FILES blockfiles

И создаем файл /etc/squid/errors/ERR_BLOCKED_FILES, где популярно расписываем причину блокировки.

С помощью регексповых выражений можно блокировать и рекламу. Например, Google AdSense и некоторые другие попадут под правило:

acl adsense url_regex –i *pagead2*

http_access deny adsense

Используя тип proto, можно указать один из протоколов (http или ftp), для которых будет действовать правило, или вообще запретить доступ по выбранному протоколу:

acl ftp proto ftp

http_access deny ftp workip

Теперь с компьютеров с адресами, входящими в workip, нельзя будет обратиться к FTP-ресурсам.

Использование ACL для блокировки баннеров не очень удобно. Выходом будет фильтрация не по конкретному адресу, а по содержимому при помощи squidGuard (его настройку мы рассмотрим в следующем номере журнала).

Настройки кэша

Борьба с баннерами – не единственная возможность сэкономить трафик. Нельзя обойти стороной настройку кэширования. В Ubuntu кэш по умолчанию размещается в каталоге /var/spool/squid. В других дистрибутивах может быть иначе. Чтобы не искать, посмотри значение переменной cache_dir. Формат ее таков:

cache_dir type путь размер L1 L2 [options]

Например:

cache_dir ufs /var/spool/squid 10249 16 256

Поле type определяет тип кэша: ufs (unix file system), aufs и diskd. Обычно используется ufs как наиболее надежный. Максимальный размер, после которого кэш будет очищаться, установлен по умолчанию в 100 Мб. При серьезных нагрузках он быстро заполнится, поэтому есть смысл увеличить его до нескольких гигабайт (мы увеличили до 10 Гб). Удобно, что можно использовать несколько cache_dir, установив кэш на разных дисках, – положительно скажется на производительности. В Squid каждый кэшируемый объект располагается в отдельном файле, а сами файлы не сваливаются в одно место, благодаря механизму работы с двухуровневой иерархией каталогов. Количество каталогов первого и второго уровней и определяют параметры L1 и L2. По умолчанию их значения 16 и 256, соответственно. Дополнительно для каждого cache_dir можно определить параметр read-only (только чтение) и max-size (максимальный размер объекта).

Глобально максимальный размер объекта в кэше определяется переменной maximum_object_size. Значение по умолчанию – 4 Мб, имеет смысл его увеличить:

maximum_object_size 10240 KB

Аналогично есть и параметр minimum_object_size, отвечающий за минимальный размер объекта, по дефолту он отключен (значение 0). Объем ОЗУ, используемый Squid для хранения обрабатываемых объектов, определяется параметром cache_mem (по умолчанию – 8 Мб). При большом размере кэша лучше увеличить это значение, тем более что объемы современных ОЗУ это позволяют. Иначе Squid будет сбрасывать всю информацию на диск, что замедлит его работу.

Но это еще далеко не все. Например, отключенный по умолчанию параметр reload_into_ims разрешает игнорировать nocache или reload и выдавать объект из кэша. Это нарушение стандарта HTTP, но большинство серверов умеют корректно обрабатывать такой запрос, потому включаем:

reload_into_ims on

Вместо глобальной установки можно задать такой параметр для некоторых типов файлов.

Документация на странице reload_into_ims отсылает нас к не менее интересной директиве refresh_pattern, которая управляет параметрами кэширования:

refresh_pattern [-i] regex min percent max [options]

В regex пишем регулярное выражение, которому будет отвечать правило. Проверка производится до первого совпадения. Поэтому последним всегда устанавливается «.» – то есть правило для всех объектов. Параметр min и max указывают на минимальное и максимальное время в минутах, в течение которого объект считается новым. В percent указывается процент от времени последней модификации объекта. В min рекомендуется устанавливать 0, чтобы корректно работать с динамически обновляемыми страницами. В версии Squid 2.x по умолчанию используются инструкции:

refresh_pattern ^ftp: 1440 20% 10080

refresh_pattern ^gopher: 1440 0% 1440

refresh_pattern . 0 20% 4320

В версии 3.0 перед «.» добавлена строка:

refresh_pattern (cgi-bin|\?) 0 0% 0

В поле options через пробел указываются дополнительные параметры. В версии 2.x параметров 7, в 3.х добавилось еще 2. Большинство из них идут в разрез со стандартами HTTP, и их использование может вызвать проблемы при работе с некоторыми серверами. Однако они весьма полезны для оптимизации кэша и понадобятся в дальнейших настройках:

  • override-expire – в нарушение стандарта заставляет игнорировать параметр expire, то есть время актуальности объекта;
  • override-lastmod – игнорировать время последней модификации объекта, переданного сервером;
  • reload-into-ims, ignore-reload – изменяет или игнорирует клиентские запросы nocache или reload и принудительно выдает объект, хранящийся в кэше;
  • ignore-no-cache, ignore-private, ignore-auth – игнорирует заголовки «Pragma: no-cache», «Cache-control: no-cache», «Cache-control: private» и «Cache-control: public», принудительно кэшируя такой объект.

Параметры, появившиеся в третьей версии:

  • ignore-no-store – игнорировать заголовок "Cache-control: no-store";
  • refresh-ims – заставляет проверять наличие новой версии файла при получении от клиента If-Modified-Since.

В самом простом случае вместо правил по умолчанию можно написать одно правило, заставляющее принудительно кэшировать объекты на целый год:

refresh_pattern . 518400 80% 518400 override-expire override-lastmod reload-into-ims ignore-no-cache ignore-private ignore-auth ignore-no-store

Устанавливаем размер кэша побольше и забываем о Squid. Это даст весьма ощутимую экономию трафика. Но такой подход не всегда приемлем, да и кэш быстро заполнится старыми файлами. Поэтому лучше установить свои варианты кэширования для разных типов файлов. Например, часто на сайтах проектов экзешники, архивы и некоторые другие типы файлов имеют постоянный адрес, вроде server.com/current.exe. Укажем для таких файлов время хранения в месяц:

refresh_pattern \.exe$ 43200 100% 43200 override-expire override-lastmod reload-into-ims ignore-no-cache ignore-private ignore-auth ignore-no-store

refresh_pattern \.zip$ 43200 100% 43200 override-expire override-lastmod reload-into-ims ignore-no-cache ignore-private ignore-auth ignore-no-store

И так далее. Таким же образом «вырезаем» рекламу. Так как довольно трудно создать универсальное правило для acl/http_access и всегда можно допустить ошибку, рекламу проще кэшировать, чем блокировать:

refresh_pattern http://ad\. 43200 100% 43200 override-expire override-lastmod reload-into-ims ignore-no-cache ignore-private ignore-auth ignore-no-store

refresh_pattern http://click\. 43200 100% 43200 override-expire override-lastmod reload-into-ims ignore-no-cache ignore-private ignore-auth ignore-no-store

refresh_pattern http://count\. 43200 100% 43200 override-expire override-lastmod reload-into-ims ignore-no-cache ignore-private ignore-auth ignore-no-store

Это самый простой способ. При тщательном изучении логов можно быстро составить коллекцию URL, которые стоит поместить в вечный кэш. Для нарезания баннеров можно дополнительно использовать прокси-сервер bfilter (bfilter.sf.net) или редиректор для squid – adzapper (adzapper.sf.net).

Как видишь, кальмар не так страшен. Если не считаешь удобной ручную настройку, обратись к Webmin, где большинство установок можно произвести в наглядной форме. Базовая настройка занимает минут 10. После определенной доводки пользователи будут радоваться скорости открытия страниц, а руководство – низкому трафику.

INFO

Для Squid существует огромное количество дополнений (анализаторы журналов, отчеты и другие), в репозитариях большинства дистрибутивов есть самые популярные из них. Для поиска в Ubuntu введи «sudo apt-cache search squid».

После установки Squid в каталоге /usr/share/doc/squid ты найдешь документацию и примеры конфигурационных файлов.

Для нарезания баннеров можно дополнительно использовать прокси-сервер bfilter (bfilter.sf.net) или редиректор для squid – adzapper (adzapper.sf.net).

Чтобы заставить Squid 2.6 работать в режиме прозрачного кэширующего прокси-сервера, в конфиге следует удалить все директивы httpd_accel_* и прописать «http_port 127.0.0.1:3128 transparent».

WWW

На странице wiki.squid-cache.org/ConfigExamples доступны примеры настроек Squid.

WARNING

После изменения конфигурационных файлов не забывай перезапускать Squid.

Содержание