Как устроена и работает система контроля доступа в Squid

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

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Система контроля доступа Squid состоит из двух различных частей: элементов ACL (ACL elements) и списков доступа (access lists). Здесь сокрыта первая сложность, которая связана с переводом на русский язык используемых терминов. Так ACL elements чаще всего переводится как ACL записи или ACL списки, что, в общем-то, достаточно верно отражает их смысл, но вызывает путаницу с термином access lists, вместо которого чаще всего используется термин правила ACL. Чаще всего путаница возникает при самостоятельном переводе англоязычной документации, что резко затрудняет понимание и приводит к различного рода казусам.

Элементы ACL

Под элементами ACL (они же записи или списки) подразумеваются списки значений определенного типа. Список допустимых типов представлен в документации: ACL TYPES AVAILABLE. Как видим, он довольно разнообразен, это и адреса источника или назначения, и доменные имена, параметры URL, время и дата, регулярные значение и т.д., и т.п. Каждый элемент ACL может содержать данные только одного допустимого типа, перечисленные через пробел или отдельной строкой. Также каждый элемент ACL должен иметь уникальное имя. Общий синтаксис следующий:

1acl имя_acl тип_acl список_значений

Например, создадим элемент ACL содержащий IP-адреса какого-либо подразделения:

1acl buh src 192.168.0.100-192.168.0.110 192.168.0.123

Также можно записать это следующим образом:

1acl buh src 192.168.0.100-192.168.0.110
2acl buh src 192.168.0.123

При выборе варианта написания следует исходить из его удобочитаемости, на наш взгляд второй вариант более удобен в восприятии, чем первый.

Одно и тоже значение может входить в списки сразу нескольких элементов ACL. Так один и тот же IP-адрес может входит в списки элементов buh (бухгалтерия), office (сеть офиса) и localnet (локальная сеть):

1acl buh src 192.168.0.100-192.168.0.110 192.168.0.123
2acl office src 192.168.0.100-192.168.0.230
3acl localnet src 192.168.0.0/24

При этом абсолютно не важна последовательность указания элементов ACL в конфиге, в любом случае значение адреса будет входить во все три элемента. Определение принадлежности значения к элементу ACL производится по принципу ИЛИ, т.е. достаточно совпадения с одним из значений списка.

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

Вы можете создать какое угодно количество элементов ACL, как говориться, на все случаи жизни, но при этом следует помнить, что все значения элементов загружаются в память при старте сервиса и каждое значение проверяется по каждому элементу соответствующего типа.

По времени работы различают два типа ACL: быстрые и медленные. К медленным относят элементы, связанные с необходимостью выполнять DNS-запросы, аутентификацию пользователей и т.д., с полным списком медленных и быстрых ACL можно ознакомиться здесь: Fast and Slow ACLs. По понятным причинам медленными элементами ACL злоупотреблять не следует.

Списки доступа

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

Общий синтаксис таков:

1список_доступа действие (allow|deny) элементы_ACL

Вот здесь начинается самое интересное. Каждый список доступа может содержать несколько элементов ACL, которые обрабатываются по принципу И, т.е. чтобы список сработал, значение должно входить во все элементы ACL.

Сами списки обрабатываются последовательно, по принципу ИЛИ, т.е. до первого совпадения.

1http_access allow|deny acl И acl И ...
2 ИЛИ
3http_access allow|deny acl И acl И ...
4 ИЛИ
5...

Если значение не попало ни в один список определенного типа, к нему применяется действие противоположное действию в последнем списке. Эта особенность способна привести к весьма неожиданному результату, поэтому хорошим тоном будет всегда задавать действие по умолчанию, указывая вместо элемента ACL значение all.

Простой пример. Сначала мы разрешили всем подразделениям доступ к интернету через протокол HTTP, но не задали при этом действия по умолчанию:

1acl buh src 192.168.0.101-192.168.0.129
2acl office src 192.168.0.101-192.168.0.199
3acl sklad src 192.168.0.200-192.168.0.209
4
5http_access allow buh
6http_access allow office
7http_access allow sklad

В приведенном примере всё будет работать как надо, все компьютеры, которые не относятся к указанным элементам ACL доступа к сети иметь не будут. А теперь мы решили заблокировать доступ к сети для склада:

1http_access allow buh
2http_access allow office
3http_access deny sklad

После чего любой компьютер сети, кроме входящих в элемент sklad получит доступ, так как для всех не попавших в списки значений действие будет allow. Поэтому всегда задавайте действие по умолчанию:

1http_access allow buh
2http_access allow office
3http_access deny sklad
4http_access deny all

Часто возникает следующий вопрос: а можно ли вместо конструкции

1http_access allow buh
2http_access allow office
3http_access allow sklad

написать

1http_access allow buh office sklad

Вроде бы везде allow, зачем плодить строки? Ответ - нельзя! Потому что списки (правила) обрабатываются как ИЛИ, а элементы как И. А так как один и тот же компьютер, несмотря на то, что сеть бухгалтерии входит в сеть офиса, не может одновременно принадлежать офису и складу, то такое правило работать не будет.

Очень простой пример:

1acl ivanov src 192.168.0.123
2acl petrov src 192.168.0.124

Если мы напишем так, то работать будет:

1http_access allow ivanov
2http_access allow petrov

так как читать эту конструкцию следует как:

1http_access allow ivanov
2ИЛИ
3http_access allow petrov

А вот так не будет:

1http_access allow ivanov petrov

потому что данная запись означает:

1http_access allow ivanov И petrov

чего просто не может быть, так как источник может быть Ивановым ИЛИ Петровым, но никак не Ивановым И Петровым одновременно.

Вообще, избегайте сочетать в одном списке доступа элементы ACL одного типа, это самый верный способ получить нерабочее правило.

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

Поэтому правильно будет:

1acl ivanov src 192.168.0.123
2acl buh src 192.168.0.101-192.168.0.129
3acl office src 192.168.0.101-192.168.0.199
4
5http_access allow ivanov
6http_access allow buh
7http_access allow office

и неправильно:

1http_access allow buh
2http_access allow ivanov
3http_access allow office

Допустим, поступила задача - ограничить доступ к интернету рабочим временем для всей бухгалтерии, кроме Иванова. Хорошо, добавляем:

1acl worktime time MTWHF 09:00-18:00

Затем добавим к разрешающему списку второй элемент ACL и запретим работу во внерабочее время:

1http_access allow buh worktime
2http_access deny buh

В первом случае, когда список с элементом ivanov стоит выше списка с элементом buh - все будет работать как надо, а во втором случае нет. Так как адрес источника 192.168.0.123 входит в списки обоих элементов и условие для элемента buh сработает первым.

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

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

1http_access allow ivanov
2http_access allow buh worktime
3http_access allow office

работать не будет, потому что в рабочее время будет срабатывать правило http_access allow buh worktime, а в нерабочее http_access allow office, так как список значений элемента buh перекрывается списком значений элемента office. Чтобы все работало как задумано потребуется еще один список http_access deny buh:

1http_access allow ivanov
2http_access allow buh worktime
3http_access deny buh
4http_access allow office

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

Также, как и элементы ACL списки доступа могут быть быстрыми и медленными: Fast and Slow ACLs. Например, списки доступа delay_access, отвечающие за ограничение скорости, являются быстрыми, а http_access - медленными. Общее правило: использовать быстрые списки раньше медленных и не использовать быстрые списки с медленными элементами. Также имеет смысл вводить некоторые "бесполезные" проверки, чтобы уменьшить количество обращений к медленным спискам с медленными элементами.

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Помогла статья? Поддержи автора и новые статьи будут выходить чаще:

Поддержи проект!

Или подпишись на наш Телеграм-канал: Подпишись на наш Telegram-канал