Вопрос или проблема
В течение нескольких дней я пытаюсь понять, как заставить работать прозрачный HTTPs-прокси с Squid. То, что я пытаюсь сделать, — это прокси, который принимает интернет-трафик с портов 80 и 443, перенаправляет его через Squid в Privoxy, затем через Tor, и возвращает данные обратно. По сути, я хочу “автоматически” перенаправлять некоторый трафик через Tor без необходимости для пользователя добавлять прокси в свое соединение.
Я знаю, как настроить части с Privoxy и Tor, но у меня возникают трудности с конфигурацией Squid и IP tables.
Вот моя настройка
Скачайте последнюю версию
curl -O http://www.squid-cache.org/Versions/v3/3.5/squid-3.5.22.tar.gz && tar zxvf squid-3.5.22.tar.gz && cd squid-3.5.22
Установите все необходимые пакеты
apt install devscripts build-essential openssl libssl-dev fakeroot libcppunit-dev libsasl2-dev cdbs ccze libfile-readbackwards-perl libcap2 libcap-dev libcap2-dev libnetfilter-conntrack-dev htop ccze sysv-rc-conf -y
Настройте сборку, выполните make и установите
./configure \
CHOST="x86_64-pc-linux-gnu" \
CFLAGS="-march=core2 -O2 -pipe" \
CXXFLAGS="${CFLAGS}" \
--build=x86_64-linux-gnu \
--prefix=/usr \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--libdir=/usr/lib \
--sharedstatedir=/usr/com \
--includedir=/usr/include \
--localstatedir=/var \
--libexecdir=/usr/lib/squid \
--srcdir=. \
--datadir=/usr/share/squid \
--sysconfdir=/etc/squid \
--infodir=/usr/share/info \
--mandir=/usr/share/man \
--x-includes=/usr/include \
--x-libraries=/usr/lib \
--with-default-user=proxy \
--with-logdir=/var/log/squid \
--with-pidfile=/var/run/squid.pid \
--enable-err-languages=English \
--enable-default-err-language=English \
--enable-storeio=ufs,aufs,diskd \
--enable-linux-netfilter \
--enable-removal-policies=lru,heap \
--enable-gnuregex \
--enable-follow-x-forwarded-for \
--enable-x-accelerator-vary \
--enable-zph-qos \
--enable-delay-pools \
--enable-snmp \
--enable-underscores \
--with-openssl \
--enable-ssl-crtd \
--enable-http-violations \
--enable-async-io=24 \
--enable-storeid-rewrite-helpers \
--with-large-files \
--with-libcap \
--with-netfilter-conntrack \
--with-included-ltdl \
--with-maxfd=65536 \
--with-filedescriptors=65536 \
--with-pthreads \
--without-gnutls \
--without-mit-krb5 \
--without-heimdal-krb5 \
--without-gnugss \
--disable-icap-client \
--disable-wccp \
--disable-wccpv2 \
--disable-dependency-tracking \
--disable-auth --disable-epoll \
--disable-ident-lookups \
--disable-icmp
Разрешите ip4 forward
echo -e "net.ipv4.ip_forward = 1\nnet.ipv4.conf.default.rp_filter = 0\nnet.ipv4.conf.all.rp_filter = 0\nnet.ipv4.conf.eth0.rp_filter = 0\n" >> /etc/sysctl.conf
Создайте сертификаты
mkdir /etc/squid/ssl_certs && cd /etc/squid/ssl_certs
openssl genrsa -out squid.key 2048
openssl req -new -key squid.key -out squid.csr -nodes
openssl x509 -req -days 3652 -in squid.csr -signkey squid.key -out squid.crt
cat squid.crt squid.key > squid.pem
Создайте кэш сертификатов
mkdir /var/lib/squid && chown -R proxy:proxy /var/lib/squid/
/usr/lib/squid/ssl_crtd -c -s /var/lib/squid/ssl_db
Измените владение и права на папках
mkdir -p /var/spool/squid
chown -R proxy:proxy /etc/squid/squid.conf | chown -R proxy:proxy /usr/lib/squid | chown -R proxy:proxy /var/lib/squid/ssl_db/ | chown -R proxy:proxy /var/spool/squid | chown -R proxy:proxy /var/log/squid | chmod 777 /var/spool/squid | chmod 777 /var/log/squid | chmod 755 /var/lib/squid/ssl_db/certs | chown proxy:proxy /var/log/squid/
Измените конфигурацию (ниже) и инициализируйте кэш
squid -f /etc/squid/squid.conf -z
Перенаправьте порты 80 и 443
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3128
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 3129
Моя фактическая конфигурация Squid
acl localnet src all
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # незарегистрированные порты
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
never_direct allow all
always_direct allow all
# Разрешить доступ cachemgr только с локального хоста
http_access allow localhost manager
http_access deny manager
http_access allow localnet
http_access allow localhost
debug_options ALL,2
visible_hostname squid
# остановить squid, чтобы не тратило вечность на перезапуск.
shutdown_lifetime 3
# для клиентов с настроенным прокси.
http_port 3127
# для клиентов, перенаправленных сюда через iptables ... REDIRECT.
http_port 3128 tproxy
# для клиентов https, перенаправленных сюда через iptables ... REDIRECT
https_port 3129 tproxy ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/etc/squid/ssl_certs/squid.pem
sslcrtd_program /usr/lib/squid/ssl_crtd -s /var/lib/squid/ssl_db -M 4MB sslcrtd_children 8 startup=1 idle=1
# acl step1 at_step SslBump1
# ssl_bump peek step1
# ssl_bump bump all
ssl_bump server-first all
sslproxy_cert_error allow all
sslproxy_flags DONT_VERIFY_PEER
via off
forwarded_for off
request_header_access From deny all
request_header_access Server deny all
request_header_access WWW-Authenticate deny all
request_header_access Link deny all
request_header_access Cache-Control deny all
request_header_access Proxy-Connection deny all
request_header_access X-Cache deny all
request_header_access X-Cache-Lookup deny all
request_header_access Via deny all
request_header_access X-Forwarded-For deny all
request_header_access Pragma deny all
request_header_access Keep-Alive deny all
cache_dir ufs /var/spool/squid 1024 16 256
coredump_dir /var/cache/squid
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
Вы можете заметить, насколько я мягок с настройками Squid. Это только для тестирования.
Так что на данный момент ни перехват, ни tproxy не работают. Если я использую accel для некриптографического трафика, это работает, но ничего больше. Если я использую его как он есть, то результат — это будет висеть в течение периода времени ожидания клиента и затем истечет время ожидания.
Вот пример. Я изменил в /etc/hosts
IP для httpbin.org и перенаправил его через сервер Squid.
❯ curl -vk https://httpbin.org/ip
* Пытаюсь *******...
* Подключено к httpbin.org (*******) порт 443 (#0)
* TLS 1.2 подключение с использованием TLS_RSA_WITH_AES_256_GCM_SHA384
* Сертификат сервера: ******
* Сертификат сервера: Universe
> GET /ip HTTP/1.1
> Host: httpbin.org
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 503 Service Unavailable
< Server: squid/3.5.22
< Mime-Version: 1.0
< Date: Mon, 05 Dec 2016 05:43:50 GMT
< Content-Type: text/html;charset=utf-8
< Content-Length: 3498
< X-Squid-Error: ERR_CONNECT_FAIL 110
< Vary: Accept-Language
< Content-Language: en
< X-Cache: MISS from pipik
< Connection: close
На стороне Squid
2016/12/05 05:42:50.362 kid1| 5,2| TcpAcceptor.cc(220) doAccept: Новое подключение на FD 28
2016/12/05 05:42:50.362 kid1| 5,2| TcpAcceptor.cc(295) acceptNext: подключение на local=[::]:3129 remote=[::] FD 28 flags=25
2016/12/05 05:42:50.363 kid1| 33,2| client_side.cc(3911) httpsSslBumpAccessCheckDone: требуется sslBump для local=*******:3129 remote=############# FD 11 flags=17 method 3
2016/12/05 05:42:50.363 kid1| 11,2| client_side.cc(2347) parseHttpRequest: HTTP Клиент local=*******:3129 remote=############# FD 11 flags=17
2016/12/05 05:42:50.363 kid1| 11,2| client_side.cc(2348) parseHttpRequest: HTTP Клиент ЗАПРОС:
---------
CONNECT *******:3129 HTTP/1.1
Host: *******:3129
----------
2016/12/05 05:42:50.363 kid1| 85,2| client_side_request.cc(744) clientAccessCheckDone: Запрос CONNECT *******:3129 РАЗРЕШЕН; последняя проверенная ACL: localnet
2016/12/05 05:42:50.363 kid1| 85,2| client_side_request.cc(720) clientAccessCheck2: Нет адаптированной http-доступа. по умолчанию: РАЗРЕШЕНО
2016/12/05 05:42:50.363 kid1| 85,2| client_side_request.cc(744) clientAccessCheckDone: Запрос CONNECT *******:3129 РАЗРЕШЕН; последняя проверенная ACL: localnet
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.378 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.379 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.379 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.379 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.379 kid1| 83,2| client_side.cc(4284) clientPeekAndSpliceSSL: SSL_accept завершился ошибкой.
2016/12/05 05:42:50.379 kid1| 17,2| FwdState.cc(133) FwdState: Перенаправление клиентского запроса local=*******:3129 remote=############# FD 11 flags=17, url=*******:3129
2016/12/05 05:42:50.379 kid1| 44,2| peer_select.cc(280) peerSelectDnsPaths: Найдены источники для '*******:3129'
2016/12/05 05:42:50.379 kid1| 44,2| peer_select.cc(281) peerSelectDnsPaths: always_direct = РАЗРЕШЕНО
2016/12/05 05:42:50.379 kid1| 44,2| peer_select.cc(282) peerSelectDnsPaths: never_direct = DUNNO
2016/12/05 05:42:50.379 kid1| 44,2| peer_select.cc(288) peerSelectDnsPaths: ORIGINAL_DST = local=############# remote=*******:3129 flags=25
2016/12/05 05:42:50.379 kid1| 44,2| peer_select.cc(295) peerSelectDnsPaths: timedout = 0
2016/12/05 05:43:50.645 kid1| 4,2| errorpage.cc(1261) BuildContent: Нет существующего языкового файла error page для ERR_CONNECT_FAIL. Используется файл ошибки по умолчанию.
2016/12/05 05:43:50.645 kid1| 20,2| store.cc(980) checkCachable: StoreEntry::checkCachable: НЕТ: не кэшируемо
2016/12/05 05:43:50.645 kid1| 20,2| store.cc(980) checkCachable: StoreEntry::checkCachable: НЕТ: не кэшируемо
2016/12/05 05:43:50.845 kid1| 83,2| client_side.cc(3811) clientNegotiateSSL: clientNegotiateSSL: Новая сессия 0x29dda60 на FD 11 (#############:59117)
2016/12/05 05:43:50.943 kid1| 11,2| client_side.cc(2347) parseHttpRequest: HTTP Клиент local=*******:3129 remote=############# FD 11 flags=17
2016/12/05 05:43:50.944 kid1| 11,2| client_side.cc(2348) parseHttpRequest: HTTP Клиент ЗАПРОС:
---------
GET /ip HTTP/1.1
Host: httpbin.org
User-Agent: curl/7.49.1
Accept: */*
----------
2016/12/05 05:43:50.944 kid1| 33,2| QosConfig.cc(145) doTosLocalMiss: QOS: Сохранение TOS при пропуске, TOS=0
2016/12/05 05:43:50.944 kid1| 33,2| client_side_reply.cc(1534) buildReplyHeader: clientBuildReplyHeader: Поддержание соединения Keep-Alive не запрошено администратором или клиентом
2016/12/05 05:43:50.944 kid1| 88,2| client_side_reply.cc(2051) processReplyAccessResult: Ответ на GET https://httpbin.org/ip РАЗРЕШЕН, потому что совпадает (лог доступа демон:/var/log/squid/access.log строка)
2016/12/05 05:43:50.944 kid1| 11,2| client_side.cc(1393) sendStartOfMessage: HTTP Клиент local=*******:3129 remote=############# FD 11 flags=17
2016/12/05 05:43:50.944 kid1| 11,2| client_side.cc(1394) sendStartOfMessage: HTTP Клиент ОТВЕТ:
---------
HTTP/1.1 503 Service Unavailable
Server: squid/3.5.22
Mime-Version: 1.0
Date: Mon, 05 Dec 2016 05:43:50 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 3498
X-Squid-Error: ERR_CONNECT_FAIL 110
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from squid
Connection: close
----------
2016/12/05 05:43:50.944 kid1| 33,2| client_side.cc(817) swanSong: local=*******:3129 remote=############# flags=17
2016/12/05 05:43:50.944 kid1| 20,2| store.cc(980) checkCachable: StoreEntry::checkCachable: НЕТ: не кэшируемо
2016/12/05 05:43:50.944 kid1| 20,2| store.cc(980) checkCachable: StoreEntry::checkCachable: НЕТ: не кэшируемо
Я пробовал так много разных конфигураций, что уже запутался в том, что работает, а что нет. Вероятно, я неправильно понимаю связь между iptables и squid, но независимо от того, что я читаю, я всегда оказываюсь здесь.
Я ценю любые предложения.
Все, что вам нужно, это установить .crt сертификат на ваших клиентах, если вы используете самоподписанный сертификат. Я использую пример из этого вопроса, чтобы скомпилировать squid 5 в прозрачном режиме с самоподписанным сертификатом в прозрачном tls-режиме, и это работает хорошо. Только Google использует другой сертификат, в Linux все хорошо, в Windows все хорошо, в Android пятьдесят на пятьдесят, но вы можете использовать браузер во всех из них.
Ответ или решение
Настройка прозрачного HTTPS-прокси с использованием Squid 3.5 может быть сложной задачей, особенно когда речь идет о маршрутизации трафика через Privoxy и Tor для поддержки анонимности пользователей. Рассмотрим более подробно теорию, пример и применение этого процесса.
Теория
Задача состоит в том, чтобы настраивать Squid как прозрачный прокси-сервер для перенаправления трафика с портов 80 (HTTP) и 443 (HTTPS) через дополнительные звенья — Privoxy и Tor, без необходимости изменения конфигурации клиента. Основная сложность заключается в правильной настройке Squid как прозрачного (intercept) прокси и корректной обработки SSL-трафика, что требует SSL-бампинга для расшифровки и повторного зашифрования трафика.
Squid как прозрачный прокси используется для перехвата и обработки пользовательских запросов на уровне HTTP и HTTPS без необходимости конфигурировать вручную клиенты, кроме установки необходимых SSL сертификатов. В то же время, связка с Privoxy и Tor обеспечивает дополнительный уровень переработки трафика и анонимности соответственно.
Пример
Ваш текущий подход выглядит достаточно проработанным, но некоторые моменты нуждаются в уточнении и исправлении.
- Конфигурация Squid:
Вы уже настроили множество опций для Squid, включая поддержку SSL с опцией ssl-bump
. Это позволяет Squid расшифровывать HTTPS-трафик для его обработки. Однако, необходимо четко определить этапы SSL (SslBump), чтобы избежать проблем с SSL_accept failed
.
- Iptables:
Вы убедились, что правила iptables перенаправляют трафик с порта 80 на 3128, а с порта 443 на 3129. Это основополагающий шаг для организации прозрачного проксирования, но обратите внимание, что такие перенаправления ставок должны учитывать интерфейсы, на которых они задействованы (например, -i eth0
для конкретного интерфейса).
Применение
-
Убедитесь в корректности SSL настройки:
Для успешного SSL-бампинга, убедитесь, что у вас есть следующие этапы в конфигурации Squid:
acl step1 at_step SslBump1 ssl_bump peek step1 ssl_bump bump all
Это позволит корректно отслеживать и влиять на SSL-трафик.
-
Установите сертификаты:
Каждый клиент должен доверять вашим сертификатам для успешной работы SSL-бампинга. Без этого любые попытки расшифровать зашифрованный трафик будут встречены ошибками, что и происходит. Импортируйте сертификат, который вы использовали при настройке Squid (в данном случае
squid.pem
), на всех конечных устройствах клиентов. -
Обработка ошибок SSL:
Ошибки
SSL_accept failed
часто вызваны некорректной настройкой SSL контекста или проблемами с доверием к сертификатам. Убедитесь, что ваш сертификат должным образом установлен и привязан, и что конфигурации не конфликтуют с уже установленным трафиком. -
Решение проблем:
Если проблемы продолжаются, увеличьте уровень логирования с помощью опции:
debug_options ALL,9
После этого логируйте любые неудачные попытки подключения для дальнейшего анализа.
Если же данные шаги не имеют эффекта, может потребоваться глубже исследовать совместимость со специфическими клиентами или сетевыми устройствами, которые могут вмешиваться в HTTPS трафик. Однако, рассматривая ваш базовый подход, эти шаги должны помочь стабилизировать настройки и успешно организовать прозрачное проксирование через Squid.
Этот процесс требует внимательности в настройке каждого элемента, и важно убедиться, что все части цепочки – от Iptables до Tor – синхронизированы и верно настроены.