Squid, https и проблемы CDN

Везде достаточно информации о том как запустить squid с ssl_bump, но в реальности всё иначе.

Моей целью было запустить squid с ssl_bump в прозрачном (intercept) режиме на Centos 7.1. Есть простое решение — добавить репозиторий и просто установить squid-3.5. Это работает, но это было бы слишком просто. Через некоторое время пользователи стали жаловаться на бан в google и недоступность некоторых крупных ресурсов.

Как оказалось, проблема известная и все варианты решения сводятся к прописыванию адреса прокси у пользователя. Всё началось еще в далеком 2009м с уязвимости CVE-2009-0801, а именно — пользователь прозрачно настроенного squid мог обойти правила подделав HTTP заголовок, именно туда (ну а куда же еще?) смотрит squid. В squid-3.2.11 появилась внутренняя функция hostHeaderIpVerify, которая проверяла — действительно ли http.host может быть доступен по указанному ip адресу. Прогресс, тем временем, не стоял на месте и количество ip для домена росло, набрал популярность Round-robin DNS. В таких условиях совсем не удивительно, что на одном хосте что-то резолвится в один IP, на соседнем (с таким же подключением) — иногда в другой, т.к. существует кеш DNS и обновляется он не синхронно. В момент таких «рассинхронизаций» squid не находит соответствия ip-домен в своём кеше (потому что обновил свой кеш немного раньше или позже) и squid прерывает соединение.

В cache.log это выглядит так:

SECURITY ALERT: Host header forgery detected on ... (local IP does not match any domain IP)
SECURITY ALERT: By user agent: ...
SECURITY ALERT: on URL: ...

Выбор был не велик — прописать всем адрес прокси или модифицировать squid. Первый вариант не подходил, т.к. в компании много мобильных пользователей с разными броузерами/устройствами. Пришлось лезть немытыми руками в код. Да, это плохо, очень плохо. В первую очередь потому что ломается вся полезность функции hostHeaderIpVerify со всеми последствиями. За дело.

Сначала добавляем всё тот же репозиторий для установки нужной версии libecap. Устанавливаем всё что потребуется, скачиваем и разворачиваем src.rpm с последней версией squid:

sudo yum install libecap openldap-devel pam-devel openssl-devel krb5-devel db4-devel expat-devel libxml2-devel libcap-devel libtool libtool-ltdl-devel libecap-devel gcc-c++ rpm-build
wget http://www1.ngtech.co.il/repo/centos/7/SRPMS/squid-3.5.12-1.el7.centos.src.rpm
rpm -i squid-3.5.12-1.el7.centos.src.rpm
cd rpmbuild/SOURCES
tar -xf squid-3.5.12.tar.xz

Редактируем код в файле «squid-3.5.12/src/client_side_request.cc».

Ищем функцию hostHeaderIpVerify и вставляем этот кусок сразу за циклом 'for':

debugs(85, DBG_IMPORTANT, "SECURITY ALERT: Workaruond for " << urlCanonical(http->request) << " CONN: " << http->getConn()->clientConnection );
http->request->flags.hostVerified = true;
http->doCallouts();
return;

Меняем поле Release в ~/rpmbuild/SPECS/squid35.spec, чтобы отличать собранные rpm. Запаковываем, собираем.

mv squid-3.5.12.tar.xz{,_old}
tar -cJf squid-3.5.12.tar.xz squid-3.5.12
cd ~/rpmbuild
rpmbuild -bb SPECS/squid35.spec


Собранные rpm в rpmbuild/RPMS готовы к установке.

P.S.: Понимаю, что это очень плохая идея и большой риск по безопасности, но выбора нет. Сотрудникам нужен google и прочие работающие cdn, компании нужен squid.
Tags:
squid, ssl

You can't comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author's username will be hidden by an alias.