Как стать автором
Обновить

«Прозрачный» Squid с фильтрацией HTTPS ресурсов без подмены сертификатов (х86, х64 — универсальная инструкция)

Время на прочтение7 мин
Количество просмотров87K
Всего голосов 15: ↑14 и ↓1+13
Комментарии75

Комментарии 75

Положу в копилку допила «детского файрвола». Сейчас всякая всплывающая зараза имеет https сертификаты.
Да, это верно. Тем более, что получить сертификат бесплатно сейчас не особо и сложно
У меня только 1 вопрос зачем шифровать 90% трафика интернета? Видео, картинки, да хоть те-же скрипты? Добавил заголовок например X-AES-Hash: 444444455666666
И отправляй данные, заодно и прокси по маршруту эти терабайты закешируют
Даное решение позволяет фильтровать определенные страницы на wikipedia.org?
Например разрешить доступ на Wikipedia, но запретить доступ на uk.wikipedia.org/wiki/HTTPS?
Клиентский браузер не ругается на сертификат?
Прочтите предыдущую статью, все будет ясно.
Так как для блокировки используется данные из sni_info (конкретно server_name), то заблокировать отдельные страницы не получится. Браузеры на сертификат не ругаются, так как это не является MITM-атакой! Сертификат не трогается и не подменяется.
Squid подключается к HTTPS ресурсу, получает его сертификат, и может «посмотреть» некоторые данные о ресурсе, в частности имя сервера, которое нам как раз и нужно для блокировки!

Значит он здесь может посмотреть адрес сервера и полный URL к запрашиваемой странице? Или только адрес сервера(домен)?
Ясно, большое спасибо. Меня именно это и интересовало.
Не за что! Я думаю, вскоре найдется способ блокировки отдельных страниц. Это уже сделано, в принципе. Только режим работы Кальмара должен быть НЕ прозрачным. Меня же интересовала тема именно прозрачного проксирования HTTPS
Наверное вопрос глупый, но: имя сервера он берет просто потому, что подключается к этому самому серверу или из данных сертификата?
Имя сервера он получает из сертификата. Процесс очень несложный. Кальмар представляется клиентом, «открывает» ресурс, получает сертификат и смотрит sni_info, откуда берет server_name. Как показано в предыдущей статье
acl blocked ssl::server_name  "/etc/squid/blocked_https.txt"

создается специальная директива, где мы прописываем пусть к файлу с заблокированными доменами (.google.ru .avito.ru, к примеру). Если данные server_name из sni_info совпадают с доменами из списка, то происходит блокировка, т.е. терминирование соединения
ssl_bump terminate blocked 

А если не совпадает, тогда Кальмар ничего не делает, и передает клиенту соединение без подмены сертификата, т.е. без MITM-атаки
Видимо для сайтов, которые за Cloudflare такая система корректно работать не будет…
У них как правило пачка доменов в сертификатах.
В случае, если example.com находится в одном сертификате с freepron.cum, кальмар сработает на freepron, если последний в локальном бане, так?
Получается, что да. Если заблокировать, к примеру, mail.ru, то перестает работать Аська, так как у них же она и располагается. Хотя надо проверить
Спасибо!
кальмар сработает на freepron, если последний в локальном бане

и freepron утащит с собой example.com так как они в одном сертификате?
это надо протестировать, я с этим не сталкивался…
А если дополнительно использовать SNI?
так вся эта система на SNI и завязана!
Но вы писали:
Имя сервера он получает из сертификата. Процесс очень несложный. Кальмар представляется клиентом, «открывает» ресурс, получает сертификат и смотрит sni_info, откуда берет server_name.
В варианте с SNI никаких connection probe делать не нужно. И сертификат парсить тоже. Вы просто извлекаете из перехватываемых пакетов имя хоста, которое передается в открытом виде (без шифрования).

У меня сейчас нет под рукой Wireshark'а, но можете проверить сами.

UPD: Не до конца дочитал тот кусок, который сам же и процитировал.
получает сертификат и смотрит sni_info, откуда берет server_name
Я не знаком со сквидом, но почему нельзя было посмотреть содержимое sni_info сразу, без запроса сертификата? И не будет проблем, о которых писал nikitasius.
Я знаю, как устроены пакеты. И каким же образом Вы хотите в Squid'e это провернуть? Боюсь, что это выходит за рамки данной статьи. К тому же, я считаю, что легче использовать SNI в самом Кальмаре. Результат тот же самый! SNI — это некая информация, которая доступна во время процесса handshake, т.е. рукопожатия. А handshake предусматривает получение клиентом сертификата. Зачем перехватывать какие-то пакеты, если Кальмар итак уже получил SNI_INFO
Я исхожу из того, что мы пытаемся сейчас решить следующую проблему:
В случае, если example.com находится в одном сертификате с freepron.cum, кальмар сработает на freepron, если последний в локальном бане, так?
В случае, если вы перехватите запрос пользователя, то вы сможете узнать, какой ресурс был запрошен на самом деле: freepron.com или example.com.

В случае, если вы сделаете запрос сами, вы лишь узнаете, что это либо freepron.com, либо example.com.

Либо я вас не правильно понял.
Вопрос товарища nikitasius еще нужно проверить, так как я не сталкивался с такими сертификатами. Но Ваше утверждение требует глобального вмешивания в трафик пользователя, что является потенциальной дырой в безопасности. К тому же, я еще раз повторюсь, не представляю, как это все сделать в связке с Кальмаром. Если есть реальная идея, с удовольствием посмотрю
Как я уже сказал, у меня сейчас нет возможности поснифить свой трафик. Вот первая попавшаяся картинка из Google. Суть в том, что имя запрашиваемого хоста можно получить в открытом виде.

Насколько я понял по сайту Squid, последний так и делает.

UPD: Торопился и не туда ответил. Это ответ на комментарий nagibat0r выше.
можно, оно и не шифруется, но Squid итак смотрит именно эту информацию. Поэтому смысла парсить трафик не вижу.
Похоже, мы говорим с вами об одном и том же, просто на разных уровнях абстракции. Вы мне про конфиг Squid, а я вам про сам алгоритм, который, как оказалось, Squid и использует. На этом предлагаю дискуссию прекратить. За статью вам в любом случае +.

P.S. Смотрю, вы тоже не туда ответили. Если вы отвечали на тот комментарий с синим заголовком, который появился при автообновлении, то это похоже на баг habrahabr. Опять UPD: Нет, просто мы с вами создали слишком длинную ветку :-)
А я и хотел донести, что Кальмар и использует этот алгоритм) Дискуссия длинная получилась, да=)
Прочитал документацию, вопрос отпал. Squid не делает своих запросов, а лишь частично передает запросы клиента до тех пор, пока не сможет получить имя хоста.

Таким образом, проблем с двумя доменами при такой конфигурации быть не должно.
вот я и склоняюсь к этому, просто не до конца понял документацию по этому вопросу. Завтра протестирую
А почему Вы используете старую версию libressl, когда доступна уже 2.3.2?
Буквально вчера я с последней libressl собирал squid 3.5.12 нс debian 8.2 x64 — проблем со сборкой через dpkg-buildpackage не возникло. Правда добиться работы в прозрачном режиме не удалось с первого напрыга, а т.к. был первый час ночи то я пошёл спать. На днях ещё повоюю с версией 3.5.12
Вопрос в другом, если Вы контактировали с разработчиками squid то как они обьясняют нестабильность работы версий после 3.5.12?
Потому что именно эта версия протестирована и работает стабильно. А насчет остальных не уверен.
По поводу нестабильности новых версий Squid. Разработчики именно этот вопрос уже три раза оставляли незакрытым. Оставлял багтреки, но разработчики просто переставали отвечать там.
Любопытная вещь с squid 3.5.12, собрал его с опциями (--enable-ssl --enable-ssl-crtd --with-openssl), но при squid -k parse выводит

2015/12/09 22:48:56| Took 0.00 seconds ( 0.00 entries/sec).
FATAL: Unknown SSL option 'NO_SSLv3'
Squid Cache (Version 3.5.12): Terminated abnormally.

и то же самое на NO_SSLv2

куда девались эти опции? по документации http://www.squid-cache.org/Versions/v3/3.5/cfgman/http_port.html они должны быть.

на SINGLE_DH_USE ругани нет

посмотрел diff между 3.5.10 и 3.5.12, там ничего криминального нет по вырезанию этих опций, в общем загадка.

что более интересно, без NO_SSLv2 и NO_SSLv3 все прекрасно работает и ограничение по https тоже, старые баги с https://mail.ru и некоторыми другими сайтами которые наблюдались на squid 3.5.10 исчезли, остается вопрос производительности и не начнет ли валиться squid 3.5.12 когда к нему полезут 50-100 человек, собственно это я выясню завтра в течении дня запустив фильтрацию на выборочной группе пользователей из офиса.
режим работы прокси — прозрачный?
Да, прозрачный.

В общем 3.5.12 не готов пока для прозрачного проксирования https, возникают какие-то глюки. То странички по https открываются очень долго, и как правило в результате не открываются вообще, причем выборочно на разных разделах одного и того же сайта по https.
то же самое, что и во всех версиях, начиная с 3.5.9. Печально=(
Вообще, пообщавшись по почте с некоторыми разработчиками, удалось кое-что выяснить. Они «что-то сломали там», еще когда сделали 3.5.9. И никто не обращал внимания. Теперь, чтобы исправить, необходимо много переписывать, дабы не потерять текущий функционал, а добавилось его немало. В частности меня интересует, что с версии 3.5.9 в логи при прозрачном проксировании попадают не просто ip адреса HTPS ресурсов, а имена доменов.
Как-то не красиво выглядит использование checkinstall'a и сгенеренные им недопакеты ( особенно, если планируется их передавать куда-то дальше локалхоста), проще такой самосбор выносить в /opt, мне думается.

А вообще, стоит пользоваться специально предназначенными для таких вещей инструментами, например, набором devscripts, в частности uupdate. Делается это как-то так:
apt-get build-dep squid3
apt-get source squid3
wget http://www.squid-cache.org/Versions/v3/3.5/squid-3.5.8.tar.gz
cd squid*
uupdate --upstream-version 3.5.8 ../squid-3.5.8.tar.gz
debuild -i -us -uc -b
dpkg -i ../*3.5.8*deb


И это будут нормальные пакеты с деревом зависимостей. Там же можно наложить дополнительные патчи и указать директивы сборки.
Ну да, в прошлой статье именно так я и делал. Так что ничего нового) А я написал в статье, что этот способ не работает по причине отсутствия «дебианезированных» исходников 3.5.7
Кхм-кхм. Собственно для отсутствия «дебианезированных» исходников более новой версии, и существует uupdate, «дебианизирующий» новую версию на основе старой дистрибутивной.
Кхм кхм, а как Вы, собственно, хотите сделать uupdate с версии 3.5.10 до 3.5.8 (не опечатка)?

Вы, вероятно, не совсем поняли. В репозитории. как я и написал, отсутствуют нужные исходники. А есть 3.5.10, которая нам не подходит. Подходит только 3.5.8, и никакая другая!
точнее подходит именно для способа из первой статьи версия исходников из репозитория только 3.5.7 (для обновления до 3.5.8). Если взять версию постарше, например 3.5.4, то обновление произойдет некорректно, и компиляция не пройдет. Проверено
> uupdate с версии 3.5.10 до 3.5.8 (не опечатка)?
$apt-cache policy squid3
squid3:
  Установлен: (отсутствует)
  Кандидат:   3.4.8-6+deb8u1
  Таблица версий:
     3.4.8-6+deb8u1 0
        500 http://security.debian.org/ jessie/updates/main amd64 Packages
     3.4.8-6 0
        500 http://mirror.yandex.ru/debian/ jessie/main amd64 Packages


На самом деле, нужно будет грохнуть версия-зависимые патчи и, по-хорошему, поправить rules с учетом пожеланий к сборке.
я провел над этим делом три дня, но так и не заставил собраться нормальные пакеты этим способом, плюс были проблемы именно в архитектуре х64. Поэтому checkinstall стал более простым способом. К тому же, позволяет rpm генерировать. Недостатки, которые в статье описаны, связаны с правилами сборки. Надо просто покурить их, пока нет возможности, болею
Тогда выздоравливайте. Я checkinstall недолюбливаю из-за его неприятной особенности: он не собирает пакет с последующей установкой, а отслеживая происходящие изменения на файловой системе, уже генерит пакет. И действие dpkg -i здесь уже излишне.

Соответственно, если checkinstall споткнется и вывалится с ошибкой, то помойку придется вычищать руками или надеяться на работспособность make uninstall. И наша операционная система начинает превращаться в слаку.

Потому куда правильнее делать
./configure --prefix=/opt/`basename $(pwd)`


Перенос содиржимого opt'a на другую машину куда менее болезнен, чем порожденных чекинсталлом недопакетов.

Ну это я так, побухтеть. На одной из прошлых работ вдоволь накушался вкривь и вкось собранного непонятно как и чем непотребства.
почитал, усвоил кое что, спасибо. На самом деле, с чекинсталлом я ранее дело имел редко, потому что я по тем же причинам его недолюбливаю=) просто пришлось из-за того, что я писал выше. Самое идеальное — найти репозиторий, хоть где, где есть «дебианизированные» исходники squid 3.5.7, но я не нашел. Был бы несказанно рад, если кто-то все таки его найдет
Существуют ли какие-то аналогичные решения магистрального масштаба?
Ну и конечно интересно как от этой блокировки защититься? А то что-то оружие блокировки стало последнее время побеждать.
1) что Вы имеете в виду под словами «магистральный масштаб»?
2) защита от блокировки — использовать другой прокси, к примеру, выставив вручную настройки в браузере. Но я, например, в своей конторе запретил использование сторонних прокси и DNS, и порты у нас открыты только определенные. Система работает уже несколько месяцев, пока не было случаев обхода
запретил использование сторонних прокси и DNS

не подскажете, каким образом?
В очередной раз спасибо за статью!
Но хотелось бы узнать, как грамотно настроить данный прозрачный Squid, если не делать его шлюзом по умолчанию. Так как в качестве шлюза стоит роутер.
Не за что. Если Вы хотите иметь прозрачный прокси, то он должен быть обязательно шлюзом для Ваших ПК, иначе Вас прокси пускать не будет. Статически — пожалуйста, хоть в другую подсеть его убирайте.
Смотря что за шлюз, если это cisco — используйте WCCP. Если это не циско — заворачивать роут-мапами. Если это Linux роутер — используйте DNAT, но при его использовании наверное придется отказаться от tproxy так как нужно разделять трафик уже прошедший через squid и еще не прошедший. Хотя при наличии 2-х интерфейсов в squid — и этот вопрос решаемый.
Стоит у нас Zyxel Zywall.
Там уже есть http_redirect но там только 1 порт можно указать (312#)
Думал Route сделать. НО пока времени не хватает.
Ребята, читаем!
UPD 14.12.15: спешу поделиться с коллегами отличной новостью! Я нашел способ заставить работать новые версии Squid'а без особых танцев с бубном! Необходимо, чтобы у клиентов и в настройках Squid'а были одинаковые DNS! В моем случае, на шлюзе с Кальмаром крутится Bind. Назначил клиентам именно его, и Кальмару директивой:
dns_nameservers 127.0.0.1
. После чего все успешно заработало. Проверено на Squid 4.0.3, собрана БЕЗ Libressl!


Прошу протестировать
И что за ключ "--enable-ssl" в ./configure --help его нет.
вообще ключ включает в Кальмаре поддержку SSL
Покажите мне его пожалуйста в официальной документации. В файле configure, в исходниках, такого ключа нет.
Отвечаю на свой же вопрос. В версии Squid 3.5 удалена "--enable-ssl" поэтому используем только "--with-openssl".
пруф
Вот пакеты: Squid, Libressl, Libecap для CentOS 7.2.
Cобирал вот отсюда
Libressl
Squid
Squid собран с патчем bio.cc. Libressl я не ставил, у меня работает и без него, и не применял ключ --enable-ssl, так как в этой статье про него ничего нет.

squid-3.5.8-4.el7.centos.x86_64.rpm
squid-debuginfo-3.5.8-4.el7.centos.x86_64.rpm
squid-helpers-3.5.8-4.el7.centos.x86_64.rpm
libecap-1.0.0-3.el7.centos.x86_64.rpm
libecap-devel-1.0.0-3.el7.centos.x86_64.rpm

Если будут проблемы с openssl вот пакеты libressl
libressl-2.3.0-1.el7.awel.libre.x86_64.rpm
libressl-libs-2.3.0-1.el7.awel.libre.x86_64.rpm
огромное спасибо! Перенесу Ваш коммент в статью!!!
Автор, вы меня заинтриговали. Достойная работа! Я уже все интернеты перерыл в поисках нормального решения без костылей в виде прописывания прокси и подмены сертификатов. Надеюсь вскоре нечто подобное будет доступно в PFSense, ибо думаю не осилю Вашу инструкцию…
Спасибо, что читаете. Инструкция легкая, если используете Debian 8 / Archlinux =) Насчет остальных дистрибутивов не скажу, не пробовал. В PFSense в ближайшее время не будет такое доступно ;-)
Вопрос такой — в случае ubuntu 14.04 схема сильно изменится, как думаете?
в принципе я по вашей инструкции все сделал, но в репах только 3.3.8, так что "возможны нюансы"
В общем-то у меня сквид собрался и даже запустился, все гуд.
Но при попытке проксировать https я получаю ошибку сертификата, т.е. сквида таки пытается подменить сертификат на свой. как с этим быть — нипанятна...
логи, логи, логи) при таком конфиге Кальмар просто не может подменять сертификат.
https://kias.rfbr.ru/
не пашет
не актуально, сорри
Народ, кто тестировал х64, отпишитесь, все ли работает? Есть пара сообщений о глюках (Debian x64 Jessie), мол по истечении времени нагрузка на ЦП 100% и сегфолт…

Работает, только тестил не долго еще Бубунта 16.04.
Собирал по вашему мануалу (3.5.8 пока только), пришлось поправить в bio.cc и support.cc везде где ругался на SSLv3… на SSLv23… (LIbreSSL стоит 2.4.1 из реп)
Почему то не видит в options= параметры NO_SSLv3, NO_SSLv2, пришлось убрать.

Debian 8.3 x64
Никто не сталкивался по этому ману при сборке libecap вываливается в
dh_makeshlibs: failing due to earlier errors
/usr/share/cdbs/1/rules/debhelper.mk:262: recipe for target 'binary-fixup/libecap3' failed
make: *** [binary-fixup/libecap3] Error 255
dpkg-buildpackage: error: debian/rules binary gave error exit status 2

Cам и отвечу :)
Почему то с репозитория то что тянулось выдавало указанную ошибку.
А вот взял отсюда
wget http://jakondo.ru/wp-content/uploads/file-manager/squid_3.5.19/libecap_1.0.1-3.dsc
wget http://jakondo.ru/wp-content/uploads/file-manager/squid_3.5.19/libecap_1.0.1.orig.tar.gz
wget http://jakondo.ru/wp-content/uploads/file-manager/squid_3.5.19/libecap_1.0.1-3.debian.tar.xz

и собралось без ошибок…
Вопрос: Нужно фильтровать http и https доступ пользователей от обратного. Т.е. для каждого пользователя доступ в интернет заблокирован кроме разрешенных сайтов.
В указанном для данного мана конфиге я изменил
ssl_bump terminate blocked
ssl_bump splice all

на:
ssl_bump splice blocked
ssl_bump terminate all

После этого я получил что по https доступны только файлы указанные в blocked_https.txt, но при этом у меня абсолютно не фильтруется http-доступ.
После того как я закоментировал http_access allow localnet и перед ним добавил

acl test src 192.168.1.5/32
acl sites_test url_regex -i "/etc/squid/blocked_https.txt"
http_access allow sites_test test
http_access deny test


После этого у меня началась фильтрация http-траффика, но вылезло что теперь при переходе на https-сайты браузеры стали ругать на сертификат.
Подскажите где я не углядел чего для нужных мне задач?
Точнее даже что то сломалось и после принятия ругания на сертификат мне к https-сайтам нету доступа — выкидывает Access Denied сквида и урл не в виде доме, а ip-адресса.
Например заходя на work.ua который указан в файле — получаю ошибку доступа к url https://89.184.80.164/*
У меня точно то же самое. Уже где-то год как плюнул на это дело. По ходу, никто не знает.
Ну я в конце концов бубном я это победил.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации