Перехват и раскрытие HTTPS-запросов на прокси-сервере Squid при помощи SSL-Bump

Материал из OpenWiki
Перейти к: навигация, поиск

В корпоративной среде клиентские устройства могут быть настроены на использование прокси, и 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-сайтами.