Squid отвечает на запрос CONNECT первой подходящей строкой http_access, и эта строка может быть отказом. Именно этот факт объясняет, почему исключение для конечной точки VPN обычно не срабатывает с первой попытки: запрос никогда не доходит до разрешения, которое кто-то добавил в конце. Узкая правка сохраняет существующие защиты портов и учит их одному проверенному источнику, назначению и порту. Всё остальное на прокси ведёт себя точно так же, как раньше.

Как Squid решает судьбу запроса CONNECT

Запрос CONNECT называет хост и порт, а Squid перебирает строки http_access по порядку, пока одна из них не совпадёт. Совпавший отказ немедленно завершает проверку, и клиент получает от прокси 403. Поэтому положение правила важнее его формулировки. Перенос той же строки на шаг выше может полностью изменить результат.

Обычные защиты отклоняют всё за пределами Safe_ports и отклоняют CONNECT за пределами SSL_ports. Эти имена — ACL, определённые в вашей собственной конфигурации, поэтому их содержимое принадлежит вам, а не протоколу. Дистрибутив может разрешать широкий диапазон портов как Safe_ports, отдельно ограничивая CONNECT. Прочитайте фактические значения, прежде чем предполагать, что порт заблокирован по замыслу.

Убедитесь, что запрос отклоняет именно прокси. 403 от Squid совсем не похож на предупреждение TLS от сервера VPN, и объединение двух проблем в одну стоит первого часа. Проверьте строку журнала доступа для запроса: в ней фиксируются и действие, и правило, которое его вызвало.

Постройте одно составное совпадение вместо трёх разрозненных ACL

Постройте исключение из трёх фактов: одобренный диапазон источника, один одобренный адрес назначения и единственный порт, на котором слушает конечная точка. Два разрозненных ACL и одно составное совпадение дают совершенно иную политику, потому что оценивается именно комбинация. Называйте составной ACL по тому, что он разрешает, а не по методу, который он несёт.

Форма ниже использует диапазоны из документации, которые нужно заменить проверенными значениями. Squid не резервирует ни одного из этих имён, так что выбирать их и поддерживать согласованность — ваша задача. Этот рецепт ограничен Squid 6 и 7, чья документированная конфигурация поддерживает группу all-of. Текущая справка помечает эти директивы как недоступные в Squid 8, поэтому относитесь к этому как к рецепту, привязанному к версии, а не как к пути миграции, и сверьте директиву со справкой своей версии перед применением.

acl pvpn_src src 192.0.2.128/25
acl pvpn_dst dst 198.51.100.77/32
acl pvpn_port port 1194
acl pvpn_ok all-of CONNECT pvpn_port pvpn_dst pvpn_src

Группа all-of совпадает только тогда, когда совпадает каждый член, то есть источник, назначение и порт проверяются в одной строке. Сама группа ничего не даёт, и запрос, совпадающий лишь с двумя из трёх фактов, не может её удовлетворить. Это свойство удерживает исключение узким, когда кто-то позже добавляет второй шлюз. Либо новое назначение добавляется намеренно, либо запрос возвращается к исходным защитам.

Согните защиты портов, не убирая их

На своих текущих местах две обычные строки защиты выглядят так. Обычно они стоят после аутентификации и перед строками политики, разрешающими всё.

http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

Добавьте к каждой отрицающее составное совпадение, чтобы совпадающее исключение пережило защиту, которая иначе отклонила бы его. Меняются только строки защиты, и каждая — всего на один дополнительный член.

http_access deny CONNECT !SSL_ports !pvpn_ok
http_access deny !Safe_ports !pvpn_ok

Члены в одной строке доступа объединяются, поэтому строка теперь отклоняет только те запросы, которые не проходят и исходную проверку, и исключение. Запрос к одобренной конечной точке проходит, а любой другой запрос сохраняет прежнее поведение порта. Это уже, чем добавить порт в глобальный список SSL_ports, который разрешил бы этот порт любому назначению. Если порт уже есть в этом списке, данный ACL ничего не сужает, и более старое, широкое разрешение по-прежнему действует для других назначений, поэтому прочитайте живой список, прежде чем утверждать, что исключение открыло порт. Оно также обратимо, потому что две строки возвращаются к прежнему виду. Справка по управлению доступом описывает порядок и обычные защиты, на которых основано это изменение.

Где исключение размещать нельзя

Соблазн — поставить разрешение выше защит и закончить. Такое размещение также пропускает защиты аутентификации и локального назначения, которые обычно стоят ближе к началу работающей конфигурации. Результат — не узкое исключение, а дыра с комментарием над ней. Держите любое новое разрешение на том же проверенном этапе, что и остальная политика клиентов.

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

Подумайте, является ли конечная точка вообще TCP. Исключение CONNECT переносит потоки TCP, а профиль OpenVPN, использующий UDP, через него недоступным и останется. Меняйте профиль на TCP только если сервер так слушает и оператор принимает разницу в поведении.

Проверьте границу парсером и реальным запросом

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

Затем перезагрузите и отправьте один реальный CONNECT через прокси из одобренного источника. Запуск парсера идёт первым, потому что перезагрузка с опечаткой ничему не учит в отношении политики.

squid -k parse
squid -k reconfigure
curl -v -p -x http://proxy.lab.internal:3128 https://vpn.lab.internal:1194/ --max-time 5

Проверьте три случая: одобренный источник и учётная запись, неодобренный источник и другое назначение на том же порту. Третий случай и доказывает узость исключения, потому что задействует порт без совпадения назначения. Читайте журнал доступа для всех трёх, а не полагайтесь на сообщение клиента. Успешный CONNECT устанавливает поток TCP и ничего более, поэтому рукопожатие VPN остаётся отдельной проверкой.

Похожие статьи