Хочу поделиться информацией по поднятию прозрачного HTTP и HTTPS прокси сервера Squid с фильтрацией сайтов и без подмены сертификатов на FreeBSD 13.0 RELEASE. На Хабре уже есть похожая статья по настройке прозрачного прокси сервера Squid с фильтрацией ресурсов и без подмены сертификатов на Linux. Решил актуализировать информацию на свежо установленной ОС FreeBSD 13.0 и поделиться с вами.
При использовании действий «peek-and-splice», сквид выдергивает имя ресурса с помощью SNI и клиент дальше работает с ресурсом. Т.е. не происходит подмена сертификата. Этот режим подходит для нашего прозрачного прокси.
Ставить Squid мы будем из портов, так как необходимо включить некоторые параметры в сборку, также для заворачивания трафика на порт прокси мы будем использовать пакетный фильтр PF.
Для начала скачиваем порты:
portsnap fetch extract
Если порты уже установлены в системе (/usr/ports), то выполняем обновление:
portsnap fetch update
Ставим пакет libressl — форк openssl:
pkg install -y libressl
rehash
После установки выполняем подмену OpenSSL на LibreSSL:
mv /usr/bin/openssl /usr/bin/openssl.old
ln -s /usr/local/bin/openssl /usr/bin/openssl
openssl version
В файле /etc/make.conf определим параметры для сборки нашего сквида:
DEFAULT_VERSIONS+=ssl=libressl
OPTIONS_FILE_SET+=ECAP
OPTIONS_FILE_SET+=GSSAPI_NONE
OPTIONS_FILE_UNSET+=GSSAPI_BASE
OPTIONS_FILE_UNSET+=TP_IPFW
OPTIONS_FILE_SET+=TP_PF
Переходим в директорию порта:
cd /usr/ports/www/squid
Выполняем установку порта:
make install clean BATCH=yes
Создадим сертификат для SSL-bump'инга:
cd /usr/local/etc/squid
/usr/local/bin/openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout squidCA.pem -out squidCA.pem
Инициализируем файл базы SSL:
/usr/local/libexec/squid/security_file_certgen -c -s /var/log/squid/ssl_db -M 4MB
Приводим squid.conf к следующему виду:
#
# Squid configuration:
#
# Set a hostname
visible_hostname proxy.local
# Set nameservers (optional)
dns_nameservers 1.1.1.1
# Local area network
acl localnet src 192.168.0.0/16
# Blocked domains
acl blocked_urls url_regex -i "/usr/local/etc/squid/blocked_urls.acl"
# Squid ports listening
http_port 0.0.0.0:3128
http_port 0.0.0.0:3129 intercept
https_port 0.0.0.0:3130 intercept ssl-bump connection-auth=off cert=/usr/local/etc/squid/squidCA.pem
always_direct allow all
sslproxy_cert_error allow all
acl blocked_https ssl::server_name "/usr/local/etc/squid/blocked_urls.acl"
acl step1 at_step SslBump1
ssl_bump peek step1
ssl_bump terminate blocked_https
ssl_bump splice all
sslcrtd_program /usr/local/libexec/squid/security_file_certgen -s /var/log/squid/ssl_db -M 4MB
# Allowed ports
acl open_ports port 80 # http
acl open_ports port 443 # https
acl ssl_ports port 443
acl CONNECT method CONNECT
#
# Access Permission configuration:
#
# Deny requests to certain unsafe ports
http_access deny !open_ports
# Deny CONNECT to other than secure ssl ports
http_access deny CONNECT !ssl_ports
# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager
# Deny access to localhost
http_access deny to_localhost
# Deny access to domains
http_access deny blocked_urls
# Allow access from local networks
http_access allow localnet
http_access allow localhost
# And finally deny all other access to this proxy
http_access deny all
# Disk cache directory
cache_dir ufs /var/squid/cache 100 16 256
# Leave coredumps in the first cache dir
coredump_dir /var/squid/cache
#
# Add any of your own refresh_pattern entries above these.
#
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
# Errors pages
error_directory /usr/local/etc/squid/errors/ru
error_default_language ru
Далее создадим файл со списком запрещенных сайтов:
vi /usr/local/etc/squid/blocked_urls.acl
.youtube.com
.instagram.com
Проверяем конфиг на наличие ошибок:
squid -k parse
Инициализируем кэш:
squid -z
Пробуем запустить прокси сервер:
/usr/local/etc/rc.d/squid onestart
Проверяем статус запущенной службы:
/usr/local/etc/rc.d/squid onestatus
sockstat -l | grep squid
Подгружаем пакетный фильтр PF как модуль ядра:
kldload pf
kldstat | grep pf.ko
Включаем пакетный фильтр PF:
pfctl -e
Добавляем правила в PF для заворачивания трафика на порт прокси:
vi /etc/pf.conf
rdr pass inet proto tcp from any to any port http -> 127.0.0.1 port 3129
rdr pass inet proto tcp from any to any port https -> 127.0.0.1 port 3130
Проверяем и применяем правила:
pfctl -nvf /etc/pf.conf
pfctl -f /etc/pf.conf
Так как мы используем пакетный фильтр PF для заворачивания трафика на порт сквида, необходимо предоставить пользователю squid доступ на чтение /dev/pf, иначе получите ошибку в логе:
PfInterception PF open failed: (13) Permission denied.
Открываем /etc/devfs.conf и добавляем в конец следующее:
own pf root:squid
perm pf 0640
Перезапускаем devfs:
/etc/rc.d/devfs restart
Не забываем включить пересылку пакетов между интерфейсами:
sysctl net.inet.ip.forwarding=1
Настраиваем автозапуск в файле /etc/rc.conf:
gateway_enable="YES" # параметр sysctl net.inet.ip.forwarding=1
squid_enable="YES" # запускать прокси сервер Squid
pf_enable="YES" # запускать пакетный фильтр PF
pflog_enable="YES" # возможность логирования трафика через интерфейс pflog
Дополнения:
Иногда сквид может прерывать HTTPS соединения на некоторых ресурсах и в логах могут сыпаться ошибки вида:
SECURITY ALERT: Host header forgery detected on ... (local IP does not match any domain) IP)
Как решение можно использовать локальный кэширующий DNS резолвер, который будут использовать клиенты и сам сквид в том числе.
Источники:
https://habr.com/ru/post/267851/
Комментарии (15)
denaturat
02.11.2021 11:28+2А зачем для такой "фильтрации" городить сквид? Проще поднять, если на FreeBSD, локальный unbound, на котором заблэклистить нужные DNS-зоны.
Ровно тот же эффект будет. Плюс ещё и нестандартные порты закроет.
isobby Автор
02.11.2021 12:06-1Фильтровать запросы на уровне DNS не совсем правильное решение. Так как на уровне прокси вы можете определить список групп пользователей, которым необходим доступ к ресурсу и список пользователей, которым доступ запрещен. Из соображений безопасности SNAT по различным портам лучше не использовать и пускать юзеров только через прокси.
denaturat
02.11.2021 13:19+2Тут вы "пользователя" определяете по IP адресу, при прозрачном проксировании. Ну и по DNS точно так же views налепить можно.
Если непрозрачное проксирование - там да, гибче. Но и требует настройки на клиентах, особенно мобильных. И часть кривого софта типа поделий яндекса и whatsapp не хочет брать настройки прокси и лезет напрямую.
isobby Автор
04.11.2021 10:18Чтобы обойти ограничения по DNS, пользователю достаточно включить протокол DoH в браузере.
denaturat
04.11.2021 17:41-1оторвать DoH и DoT, равно как и беготню в интернет мимо прокси вообще, раз уж мы начинаем ограничивать свободу беготни клиентов вовне - ничего сложного, по сути плюс одно-два правило пакетного фильтра
даже, скорее обязательный пункт, фильтрация некоторых сервисов
кстати, если запихнуть мобильные устройства в такой уютный газенваген, то куча сайтов, куда не может загрузится перегруженный жабаскриптом контент баннерных сетей, соцсетей, сервисы сбора данных замаскированные под всё что можно - даже старые устройства перестают тормозить
Dukat
02.11.2021 11:31Куча статей про настройку SSL-bump, а вот как настроить шифрованный канал до прокси? Т.е. мне не надо анализировать трафик клиент-сайт, но хочется добавить дополнительный уровень шифрования для защиты от внешнего анализа трафика клиент-прокси. Это вообще возможно средствами Squid?
danfe
04.11.2021 06:50+1Ставим пакет libressl — форк openssl:
Чем дефолтный не устраивает? Не вижу в порте сквида каких-то особых требований к используемой реализации OpenSSL. От LibreSSL нынче больше геморроя, чем пользы; понятно, что у народа подгорело из-за хартблида в 2014 г., но тот урок был выучен и с тех пор OpenSSL маинтейнится сильно лучше, а эти его форки лишь вносят сумятицу и оттягивают усилия разработчиков.После установки выполняем подмену OpenSSL на LibreSSL:
Никогда так не делайте и не советуйте другим. Вместо того, чтобы грязными руками лезть в базовую систему, внося неучтенную зависимость от внешнего пакета, настройте свой интерпретатор командной строки, чтобы при поиске бинарников обходил каталоги в нужном порядке.mv /usr/bin/openssl /usr/bin/openssl.old ln -s /usr/local/bin/openssl /usr/bin/openssl
volchenkodmitriy
Спасибо за статью. Правильно я понимаю что такой прокси https трафик не вскрывает и не дает возможности его анализировать по содержанию?
isobby Автор
Не совсем. Прокси подключается к HTTPS ресурсу, получает его сертификат, и может «посмотреть» некоторые данные о ресурсе, в частности имя сервера с помощью SNI и применяет действие terminate согласно списку ACL.
volchenkodmitriy
Это я понял из статьи. Но если хочется анализировать сам трафик, например не разрешать скачивать определенные типы файлов, производить антивирусную проверку, кэшировать трафик - это не получится?
isobby Автор
К сожалению, нельзя полностью просмотреть какая именно интернет-страница была открыта, как при MITM-атаке. К плюсам можно отнести: 1) Это не MITM-атака, и не будет проблем с банк-клиентами. 2) Отображение доменных имен в статитстике сайтов запрашиваемых по https.
volchenkodmitriy
Ясно, спасибо!