![Nginx как прямой прокси-сервер для HTTPS](https://rvso.com/image/1365821/Nginx%20%D0%BA%D0%B0%D0%BA%20%D0%BF%D1%80%D1%8F%D0%BC%D0%BE%D0%B9%20%D0%BF%D1%80%D0%BE%D0%BA%D1%81%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%20%D0%B4%D0%BB%D1%8F%20HTTPS.png)
Хотя мне удалось успешно настроить nginx для проксирования HTTP-трафика (используяэто руководство), все попытки проксирования HTTPS-запросов приводили к коду 400 (Плохой запрос).
Журналы отладки Nginx оказались совершенно бесполезными:
2013/06/05 14:38:33 [info] 74946#0: *589
client sent invalid request while reading client request line, client: 127.0.0.1,
server: google.com, request: "CONNECT google.com:443 HTTP/1.1"
Что это за CONNECT
запросы? Возможно ли вообще делать proxy_pass
HTTPS запросы в nginx?
Обновлять
Нужно добавить, что прокси-сервер является частью моего рабочего процесса/инструментария веб-разработки. Это отличный способ для тестирования/отладки клиентского JavaScript впроизводствосреда (используя перезапись перед прокси).
Также язык конфигурации nginx, возможно, является самостоятельным языком программирования. В нем есть переменные!
решение1
Похоже, nginx не поддерживает режим прямого прокси с SSL. Вам нужно будет использовать что-то вродеКальмарВместо этого. Вот ссылка с более подробными пояснениями от автора nginx:HTTPS и nginx в качестве прямого прокси-сервера.
решение2
Просто для ясности: как я уже писал в комментариях к моему блогу, nginx не обрабатывает вызовы метода CONNECT, которые используются для установления необработанного TCP-соединения с удаленным хостом через HTTP-прокси, что вполне логично, учитывая, что nginx не должен работать как прямой прокси-сервер, он просто отлично работает с обычным HTTP.
Nginx просто буквально не имеет ни малейшего представления, что делать с этими вызовами методов, поэтому сообщения об ошибках в журналах довольно бесполезны. Я всегда ловил себя на том, что использую privoxy для HTTPS:http://www.privoxy.org/- его безумно легко настроить. Но все равно невозможно фильтровать или искажать содержимое HTTPS-реле, поскольку HTTPS-соединения обрабатываются с помощью сырого соединения через метод CONNECT, и сервер понятия не имеет, что он ретранслирует.
решение3
Если вы не против компиляции nginx из исходников, вы можете установитьngx_http_proxy_connect_module. Следующее сработало у меня в Debian 9 "Stretch" на Raspberry Pi (после того, как я добавил URL-адреса deb-src в /etc/apt/sources.list и выполнил apt-get update):
cd /tmp &&
apt-get source nginx &&
git clone https://github.com/chobits/ngx_http_proxy_connect_module &&
cd nginx-* &&
patch -p1 < ../ngx_http_proxy_connect_module/proxy_connect.patch &&
sudo apt-get install libpcre3-dev &&
./configure --add-module=/tmp/ngx_http_proxy_connect_module &&
make && sudo make install
Затем отредактируйте /usr/local/nginx/conf/nginx.conf
и придайте ему следующий вид (я включил пример доменов, которые вы хотите заблокировать, который работает как с SSL-прокси, так и без него):
user www-data;
worker_processes auto;
events { }
http {
server_names_hash_bucket_size 128;
server {
listen 8888;
server_name spam.example.com *.spam.example.com;
server_name spam2.example.com *.spam2.example.com;
access_log off;
return 404;
}
server {
listen 8888;
server_name ~.+;
proxy_connect;
proxy_max_temp_file_size 0;
resolver 8.8.8.8;
location / {
proxy_pass http://$http_host;
proxy_set_header Host $http_host;
}
}
}
Затем запустите /usr/local/nginx/sbin/nginx
. Он будет вполне успешно сосуществовать с nginx
пакетом Debian's stock, если вы также используете производственный веб-сервер на порту 80 и не хотите рисковать испортить его (но обязательно запустите версию /usr/local
отдельно при загрузке); в качестве альтернативы, с большей настройкой вы можете запустить обе службы из nginx, который вы скомпилировали. Но если вы настроите свой скомпилированный nginx для работы на порту, на который ваш брандмауэр пропускает трафик, будьте осторожны, вам придется вручную проверять обновления безопасности nginx, поскольку система пакетов Debian больше не будет делать этого за вас.
решение4
Моей команде потребовалось некоторое время, чтобы понять, как это сделать. Наконец, мы добились этого, встроив фрагмент ниже в nginx.conf:
stream {
map_hash_bucket_size 128;
map $ssl_preread_server_name $sphere {
site-01.example.com site-01;
site-02.example.com site-02;
}
upstream site-01 {
server 192.168.0.1:443;
}
upstream site-02 {
server 192.168.0.2:443;
}
server {
listen 443;
proxy_pass $sphere;
ssl_preread on;
}
}