Перехват и раскрытие HTTPS-запросов на прокси-сервере Squid при помощи SSL-Bump
В корпоративной среде клиентские устройства могут быть настроены на использование прокси, и HTTPS-запросы идут через прокси-сервер, используя метод CONNECT, который преобразует запрос в прозрачный TCP/IP-туннель. Чтобы перехватывать и анализировать такой трафик, Squid должен иметь свой собственный СА сертификат, используемый для подписывания динамически генерируемых сертификатов для серверов, к которым подключаются клиенты. Клиентские устройства при этом должны быть настроены на доверие этому СА-сертификату, чтобы проверка сертификатов, созданных Squid, завершалась с положительным результатом.
Схема работы клиента с сервером в этом случае выглядит так:
1. Клиент обращается к серверу, и его запрос приходит на прокси.
2. Прокси возвращает клиенту сгенерированный сертификат для сервера, подписанный CA-сертификатом самого прокси, которому клиент доверяет.
3. Прокси-сервер устанавливает HTTPS-соединение с сервером, который запросил клиент.
4. Прокси-сервер проверяет сертификат сервера, если с ним что-то не так, то клиенту возвращается ошибка.
5. Прокси получает ответ от сервера, расшифровывает его и повторно шифрует с помощью сгенерированного на шаге 2 сертификата, после чего пересылает ответ клиенту.
6. Клиент получает ответ на запрос к серверу.
Приступим к реализации вышеописанного на прокси сервере Squid версии 4.1. Создаем необходимые каталоги для сертификатов
# mkdir -p /usr/local/etc/squid/ssl # mkdir -p /usr/local/etc/squid/ssl/ssl_db
Готовим базу для генерируемых сертификатов
# /usr/local/libexec/squid/security_file_certgen -c -s /usr/local/etc/squid/ssl/ssl_db -M 16MB
Приводим в порядок права доступа
# chown -R squid:squid /usr/local/etc/squid/ssl # chmod 700 /usr/local/etc/squid/ssl
Создадим СА сертификат и ключ
# cd /usr/local/etc/squid/ssl # openssl req -new -newkey rsa:2048 -sha256 -days 36500 -nodes -x509 -extensions v3_ca -keyout squidCA.pem -out squidCA.pem Generating a 2048 bit RSA private key ....................................+++ ...........................................+++ writing new private key to 'squidCA.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:RU State or Province Name (full name) [Some-State]: Locality Name (eg, city) []:Moscow Organization Name (eg, company) [Internet Widgits Pty Ltd]:Company Ltd Organizational Unit Name (eg, section) []:IT Common Name (e.g. server FQDN or YOUR name) []:proxy.company.ru Email Address []:proxy@company.ru
И подготовим его для импорта в клиентские браузеры
# openssl x509 -in squidCA.pem -outform DER -out squidCA.der
Редактируем squid.conf, директиву http_port приводим к виду
http_port 3128 ssl-bump \ cert=/usr/local/etc/squid/ssl/squidCA.pem \ generate-host-certificates=on \ dynamic_cert_mem_cache_size=16MB
Тут, похоже, порядок опций имеет значение - опция cert должна стоять первой после ssl-bump.
Значение директивы visible_hostname должно совпадать с именем сервера, которое вводилось на стадии генерации сертификата (Common Name)
visible_hostname = proxy.company.ru
Настраиваем хелпер генерации сертификатов для сайтов
sslcrtd_program /usr/local/squid/libexec/security_file_certgen -s /usr/local/etc/squid/ssl/ssl_db -M 16MB sslcrtd_children 50 startup=10 idle=10
Дальше будет немного магии.
В Squid есть такая вещь, как ssl-bump. Её настройки определяют, как Squid будет обращаться с HTTPS-запросами. Если ничего не настраивать, то получив запрос на доступ к https-серверу, прокси будет просто устанавливать с ним соединение, используя метод CONNECT. Но если мы настроили наш входящий порт для клиентских запросов на использование ssl-bump (см. выше, что указано в директиве http_port), то Squid получает ряд дополнительных возможностей. Соединение клиента с сервером разбивается на три этапа или "шага":
SslBump1 - получение открытой информации о соединении (из сертификатов и http-запроса);
SslBump2 - передача Hello info клиента (создание соединения с сервером);
SslBump3 - получение Hello info сервера (создание соединения с клиентом).
И для каждого из этих этапов можно определить, что Squid будет делать c запросами клиентов, а делать можно следующее:
splice - пропустить все последующие действия, т.е. просто поднимаем TCP-туннель, словно и нет никакого ssl-bump
peek — подсмотреть всю доступную информацию без "влезания" в соединение
terminate — закрыть соединение
bump — "влезть" в соединение, сделать https видимым как http
Cоздаем acl с шагами bump.
acl step1 at_step SslBump1
Теперь определимся, как поступать с клиентскими запросами
# Ничего не делаем с запросами к сайтами, перечисленным в списке bypass_bump_sites # (у нас уже должно быть описано acl bypass_bump_sites dstdomain <domain list>) # Это можно делать как по соображениям безопасности, так и в случае возникновения # проблем при использовании ssl-bump с конкретными сайтами ssl_bump splice bypass_bump_sites # С запросами ко всем остальными сайтам - на этапе SslBump1 смотрим # на открытую информацию, на последующих этапах - влезаем в трафик, # "превращаем" https в http, и видим все, что скрывалось бы от нас # в туннеле: ssl_bump peek step1 ssl_bump bump all
Перезапускаем Squid. На клиентах импортируем squidCA.der в хранилище Trusted Root Certificates, и наслаждаемся полной историей соединений в логах прокси, а также корректной работой deny_info с HTTPS-сайтами.