Локальный прокси-сервер для фильтрации браузерного трафика

Введение

Немного расскажу своими словами о том, как работает модуль ngx_http_proxy_module. Именно он реализует весь функционал, о котором пойдет речь. Допустим, у вас в локальной или виртуальной сети есть какие-то сервисы, не имеющие прямого доступа из интернета. А вы хотите таковой иметь. Можно пробрасывать нужные порты на шлюзе, можно что-то еще придумывать. А можно сделать проще всего — настроить единую точку входа на все свои сервисы в виде nginx сервера и с него проксировать различные запросы к нужным серверам.

Расскажу на конкретных примерах, где я это использую. Для наглядности и простоты буду прям по порядку перечислять эти варианты:

  1. Ранее я рассказывал о настройке чат серверов — matrix и mattermost. В этих статьях я как раз рассказывал о том, как проксировать запросы в чат с помощью nginx. Прошелся по теме вскользь, не останавливаясь подробно. Суть в том, что вы настраиваете на любом виртуальном сервере эти чаты, помещаете их в закрытые периметры сети без лишних доступов и просто проксируете запросы на эти сервера. Они идут через nginx, который у вас смотрит во внешний интернет и принимает все входящие соединения.
  2. Допустим, у вас есть большой сервер с множеством контейнеров, например докера. На нем работает множество различных сервисов. Вы устанавливаете еще один контейнер с чистым nginx, на нем настраиваете проксирование запросов на эти контейнеры. Сами контейнеры мапите только к локальному интерфейсу сервера. Таким образом, они будут полностью закрыты извне, и при этом вы можете гибко управлять доступом.
  3. Еще один популярный пример. Допустим, у вас есть сервер с гипервизором proxmox или любым другим. Вы настраиваете на одной из виртуальных машин шлюз, создаете локальную сеть только из виртуальных машин без доступа в нее извне. Делаете в этой локальной сети для всех виртуальных машин шлюз по-умолчанию в виде вашей виртуальной машины со шлюзом. На виртуальных серверах в локальной сети размещаете различные сервисы и не заморачиваетесь с настройками фаервола на них. Вся их сеть все равно не доступна из интернета. А доступ к сервисам проксируете с помощью nginx, установленным на шлюз или на отдельной виртуальной машине с проброшенными на нее портами.
  4. Мой личный пример. У меня дома есть сервер synology. Я хочу организовать к нему простой доступ по https из браузера по доменному имени. Нет ничего проще. Настраиваю на сервере nginx получение бесплатного сертификата , настраиваю проксирование запросов на мой домашний ip, там на шлюзе делаю проброс внутрь локалки на synology сервер. При этом я могу фаерволом ограничить доступ к серверу только одним ip, на котором работает nginx. В итоге на самом synology вообще ничего не надо делать. Он и знать не знает, что к нему заходят по https, по стандартному порту 443.
  5. Допустим, у вас большой проект, разбитый на составные части, которые живут на разных серверах. К примеру, на отдельном сервере живет форум, по пути /forum от основного домена. Вы просто берете и настраиваете проксирование всех запросов по адресу /forum на отдельный сервер. Точно так же можно без проблем все картинки перенести на другой сервер и проксировать к ним запросы. То есть вы можете создать любой location и переадресовывать запросы к нему на другие сервера.

Надеюсь в общем и целом понятно, о чем идет речь. Вариантов использования много. Я привел самые распространенные, которые пришли в голову и которые использую сам. Из плюсов, которые считаю наиболее полезными именно из своих кейсов, отмечу 2:

  • Вы без проблем можете настроить https доступ к сервисам, при этом совершенно не трогая эти сервисы. Вы получаете и используете сертификаты на nginx сервере, используете https соединение с ним, а сам nginx уже передает информацию на сервера со службами, которые могут работать по обычному http и знать не знают о https.
  • Вы очень легко можете менять адреса, куда проксируете запросы. Допустим у вас есть сайт, его запросы проксируются на отдельный сервер. Вы подготовили обновление или переезд сайта. Отладили все на новом сервере. Теперь вам достаточно на сервере nginx изменить адрес старого сервера на новый, куда будут перенаправляться запросы. И все. Если что-то пойдет не так, можете оперативно вернуть все обратно.

С теорией закончил. Перейдем теперь к примерам настройки. В своих примерах я буду использовать следующие обозначения:

blog.zeroxzed.ru доменное имя тестового сайта
nginx_srv имя внешнего сервера с установленным nginx
blog_srv локальный сервер с сайтом, куда проксируем соединения
94.142.141.246 внешний ip nginx_srv
192.168.13.31 ip адрес blog_srv
77.37.224.139 ip адрес клиента, с которого я буду заходить на сайт

Connection termination

The proxy must handle end-of-file conditions as transparently as
possible. If it reads end-of-file from one socket, it should pass the
condition along to the other socket (using shutdown) after
writing any remaining buffered data. However, the proxy should
continue to forward data in the other direction. The proxy should
terminate a connection pair and close the file descriptors under the
following two circumstances:

  1. The proxy has read an end-of-file (or experienced a read error
    other than EAGAIN) in both directions and has
    written all remaining buffered data.
  2. The proxy experiences a write error (other than EAGAIN)
    in either direction.

Часто задаваемые вопросы по теме статьи (FAQ)

При использовании https нужно ли в режиме proxy_pass настраивать https и на бэкенде?

В общем случае не обязательно. Но есть некоторый софт, который не может корректно работать в таком режиме. Он не понимает, как корректно обрабатывать такую ситуацию. Может создавать ссылки вида http://site.ru:443, которые будут являться ошибочными. В таком случае необходимо настроить обмен между nginx и бэк сервером тоже https соединение.

Как наиболее простым спосбом передавать сертификат let’s encrypt с nginx на backend? Ведь обновдление и генерация сертификата происходят только на nginx.

Я в таких случаях использую 2 способа, в зависимости от ситуации. Самый простой — на сервере с nginx настроить nfs сервер, а на бэкенде подмонтировать по nfs к себе директорию /etc/letsencrypt и спокойно использовать сертификаты, как-будто они лежат локально. Второй вариант — использовать простой bash скрипт для копирования сертификатов к себе на сервер по scp. В обоих случаях надо не забыть на бэкенде перезапускать службы, которые использую сертификат, после его обновления.

При обращении с бэкенда по адресу сайта, запрос уходит на nginx proxy, так как в dns прописан его ip адрес. Из-за этого иногда не работают встроенные скрипты или проверки некоторых движков, так как они ожидают, что запрос вернется с того же сервера, с которого он был сделан. Но на практике он уходит на proxy и приходит оттуда.

В такой ситуации может помочь правка файла /etc/hosts на самом бэкенде. Сделайте там статическую запись с именем сайта и локальным ip адресом. Тогда запросы с самого сервера будут приходить на него же локально, а не на nginx proxy.

Что лучше использовать для проксирования http запросов nginx или haproxy?

Однозначного ответа на этот вопрос не может быть. В чем-то это схожий софт, но есть и существенные отличия. В общем случае, описанном в статье, принципиальной разницы нет. У haproxy в бесплатной версии есть функционал, который присутсвует только в nginx plus. Так что нужно смотреть по конкретным задачам и решать, какой продукт подойдет лучше.

Добавляет ли nginx в режиме proxy_pass дополнительные сетевые задержки?

Конечно да. Но на практике они очень малы, если nginx и целевой сервер находятся в общей локальной сети. С учетом задержек при передачи пакетов по сети интернет, этими локальными задержками можно пренебречь. Они будут ничтожно малы. Если же вы проксируете запросы через интернет, то нужно внимательно смотреть величину задержек между nginx и бэкендом. Желательно их делать минимальными, располагая сервера поближе друг к другу.

1: Настройка Nginx

Установка Nginx

Обновите индекс пакетов и установите Nginx:

После этого можно проверить версию Nginx и убедиться, что установка прошла успешно.

Получение сертификата

Теперь нужно получить SSL-сертификат. В этом разделе вы узнаете, как создать самоподписанный сертификат.

Примечание: Чтобы создать доверенный сертификат, читайте статью Создание сертификата Let’s Encrypt для Nginx в Ubuntu 14.04.

Перейдите в соответствующий каталог и сгенерируйте сертификат.

Вам будет предложено ввести информацию о сертификате. Вы можете заполнить эту форму на свое усмотрение; просто помните, что эта информация будет видна в свойствах сертификата. Если вы хотите получить сертификат, вам необходимо создать запрос на подпись (CSR). 2048 бит – это минимум, необходимый для подписания сертификата.

Настройка Nginx

Откройте стандартный конфигурационный файл Nginx:

Отредактируйте файл следующим образом:

В этой конфигурации параметры cert.crt и cert.key указывают местоположение, в котором будет храниться SSL-сертификат. Вам нужно обновить строки server_name и proxy_redirect и указать свой домен. Есть еще одна полезная функция Nginx: запросы читаются Nginx и переписываются на стороне ответа, чтобы обеспечить обратное проксирование.

Первый раздел говорит, что сервер Nginx может прослушивать любые запросы, поступающие на порт 80 (порт по умолчанию HTTP), и перенаправлять их на HTTPS.

Следующий раздел содержит параметры SSL. В нем находятся хорошие значения по умолчанию.

В последнем разделе настраивается проксирование. Этот раздел принимает любые входящие запросы и передает их на экземпляр Jenkins, который слушает порт 8080 в локальном сетевом интерфейсе.

Если у вас нет доменного имени, которое разрешается на ваш сервер Jenkins, то выражение proxy_redirect не будет работать правильно и нуждается в модификации. Также, если вы неправильно настроите proxy_pass (например, добавив слеш в конец), вы увидите такое сообщение:

Если вы видите такую ошибку, перепроверьте параметры proxy_pass и proxy_redirect.

Правильный сертификат

Под этим подразумевается выполнение двух условий:

  1. Сертификат должен быть выпущен доверенным центром.
  2. Сертификат должен быть выдан для домена, к которому идет подключение.

Доверенный центр

Есть список центров сертификации, внесенные в общий реестр доверенных узлов, которые могут выпускать ключи безопасности. Данным центрам по умолчанию доверяют все основные операционные системы.

Для получения сертификата от правильного центра, необходимо за него заплатить или получить бесплатно от Let’s Encrypt. Купить сертификат можно у большинства хостеров или регистраторов доменных имен. Для получения бесплатного сертификата можно воспользоваться инструкцией Получение бесплатного SSL сертификата Let’s Encrypt.

И наоборот, сертификат может быть выпущен не доверенным центром или локально на компьютере (самоподписанный). В таком случае мы получим ошибку при проверке подлинности.

Сертификат для домена

Заказывая сертификат, мы обязательно указываем, для какого доменного имени его будем использовать. Это обязательное требование. Например, если мы хотим настроить SSL-подключение к узлу security.dmosk.ru, то необходимо указывать именно это имя при заказе ключа безопасности. В противном случае, браузер будет выдавать нам ошибку, что сертификат выдан для другого узла.

Также мы можем заказать сертификат типа wildcard — он применим к домену и все его поддоменам. Например, в нашем случае мы можем заказать ключ для *.dmosk.ru — он будет применять для любого доменного имени 3-го уровня с корнем dmosk.ru.

Использование всей цепочки сертификатов

Применяя сертификат в NGINX, необходимо загрузить не только сертификат для домена, но и для всех центров сертификации — как основного, так и промежуточных. В противном случае, мы получим ошибку This server’s certificate chain is incomplete. Grade capped to B:

В случае покупки сертификата, нам отправляют все ключи в отдельных файлах. Цепочка сертификатов, как правило, идет в файле chain. Мы должны скопировать последовательность в данном файле и добавить ее к содержимому в файле с сертификатом домена — получиться файл, содержащий как последовательность для домена, так и всех центров. Назвать его можно fullchain.pem.

В случае получение бесплатного сертификата от Let’s Encrypt, мы получаем 4 файла, один из которых называется fullchain.pem — именно он и содержит все необходимые последовательности.

И так, при настройке виртуального домена в NGINX, необходимо указать путь до файла, содержащего в себе все ключи, например:

server {
        listen 443;
        server_name security.dmosk.ru;
        ssl on;
        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/cert.key;
        …
}

* в данном примере мы настраиваем NGINX для домена security.dmosk.ru; обратите внимание, что мы указали путь до файла fullchain.pem, в котором должны находиться последовательности, как для домена, так и центров сертификации. Не забываем перезапустить nginx:

Не забываем перезапустить nginx:

systemctl restart nginx

The assignment

The proxy server you will build for this lab will be invoked at the command
line as follows:

% 

For example, to redirect all connections to port 3000 on your local
machine to yahoo’s web server, run:

% 

The proxy server will accept connections from multiple clients and
forward them using multiple connections to the server. No client or
server should be able to hang the proxy server by refusing to read or
write data on its connection. For instance, if one client suddenly
stops reading from the socket to the proxy, other clients should not
notice interruptions of service through the proxy. You will need
asynchronous behavior, described in Using TCP Through
Sockets.

The proxy must also handle hung clients and servers. In particular,
if one end keeps transmitting data but the the other stops reading,
the proxy must not buffer an unlimited amount of data. If the proxy
has buffered data in one direction and is unable to write any of it
for 10 seconds, it should abort both connection pairs.

«Прозрачный» Squid с фильтрацией HTTPS ресурсов без подмены сертификатов +23

  • 28.09.15 10:32


nagibat0r

#267851

Хабрахабр

19250

Системное администрирование, Настройка Linux

Не секрет, что в больших конторах тема фильтрации Интернета довольно актуальная. С этой задачей справляется немало программных и аппаратных решений. Но в настоящее время все те сайты, которые мы резали ранее, работают по протоколу HTTPS, т.е. порт 443. Как известно, данный протокол проследить, прослушать и т. п., невозможно. А любой кеширующий фильтрующий прокси-сервер, редиректор и т. п. фильтрует только HTTP, т.е. порт 80. Как же резать Вконтакте, Одноклассники, iphide.info и многие другие подобные сайты? Как блокировать доступ к личной почте в организации, если использование оной запрещено порядками в организации? Да, можно фильтровать по IP адресам, но они частенько меняются, да и на многих ресурсах несколько IP адресов. Блокировать их на уровне файрвола как-то совсем не православное решение, и не совсем удобное.
И вот, совсем недавно, мне один товарищ рассказал, что он поднимает у себя в конторе кеширующий прокси с фильтрацией HTTPS, меня это заинтересовало. А поднимал он Squid 3.5.8. Как выяснилось, в нем переработана организация перехвата шифрованных HTTPS-сеансов (ssl_bump), вместо режимов перехвата («modes») введены в обиход действия («actions»), которые в том числе можно использовать в ACL. Режим «server-first», при котором вначале осуществляется соединение с целевым сервером, а потом создаётся защищённое соединение между клиентом и прокси, теперь доступен как действие «bump». Режим «none», при котором создаётся TCP-туннель без дешифровки трафика, теперь доступен как действие «splice».
Для обеспечения обратной совместимости добавлено действие «peek-and-splice», при котором решение о типе создаваемого вначале соединения (клиент-прокси или прокси-сервер) принимается на основе SSL hello-сообщений. Добавлены действия «peek» и «stare» для получения клиентского или серверного сертификата с сохранением возможности дальнейшего применения режимов «splice» и «bump» для соединений. Добавлено действие «terminate» для закрытия соединений к клиенту или серверу. Вот как раз SSL BUMP, PEEK-and-SPLICE и Terminate нам и нужны. Вообще, схема работы на самом деле довольно простая. Squid подключается к HTTPS ресурсу, получает его сертификат, и может «посмотреть» некоторые данные о ресурсе, в частности имя сервера, которое нам как раз и нужно для блокировки! Все мануалы, которые есть в Интернете, то и дело описывают Man in the middle (MITM) атаку с подменой сертификатов, при которой в принципе не работают некоторые сайты и банк-клиенты, да и юзеры явно видят, что за ними следят. Мы же с товарищем совместными усилиями добились сбособа фильтрации и отслеживания HTTPS без подмены сертификатов, без MITM и прочего, и все это в прозрачном режиме без настройки браузеров!
Впоследствии я столкнулся с некоторыми сложностями, в частности Squid начинал сегфолтиться на большой нагрузке. Но проблема была решена. Дело в том, что в Openssl имеются кое какие баги, которые исправлены в библиотеке Libressl. Поэтому необходимо сначала интегрировать в систему Libressl, потом уже после внесения патча в файл bio.cc в исходниках Squid приступать к компиляции последнего. Поехали! Оговорюсь, что у меня используется дистрибутив Debian Jessie x86, и Squid я в итоге собрал версии 3.5.9 (последняя на данный момент версия), и статья рассчитана на более-менее опытного пользователя Linux, так как некоторые моменты опускаются, а говорится лишь самое главное, так как мне лень все разжевывать. Итак, если вам интересно, идем под кат.
Для начала, подготовимся к сборке пакетов:

последний

bugs.squid-cache.org/attachment.cgi?id=3216

pem

UPD: в версии Кальмара, которую компилировал я изначально, т.е. 3.5.9, найден досадный баг (или фича), из-за которого спустя время перестают открываться некоторые HTTPS сайты. Решение: компилировать версию 3.5.8.UPD2: создал очередной багрепорт по проблеме в 3.5.9, тему буду обновлять, если что-то прояснится.UPD3: вышла версия 3.5.10 с исправленными багами, по крайней мере, патч на файл bio.cc там уже применен. Не тестировал пока-чтоUPD4: подредактировал статью немного.UPD5: прямая ссылка для скачивания архива со всеми нужными пакетами (SQUID 3.5.8)прямая ссылка на скачивание архива со всеми нужными пакетами (SQUID 3.5.10 — последняя на данный момент стабильная версия, в которой исправлено множество багов и сделано множество оптимизаций, судя по чейнжлогу, в т.ч. исправлен баг, из-за которого пришлось в статье применять патч к bio.cc

ВНИМАНИЕ! НЕ ТЕСТИРОВАЛАСЬ на боевом сервере!)

3proxy tiny free proxy server

Hot news: 3proxy 0.8.13 released August, 1 2019.

0.8.13 resolves bugs in admin service and configuration parser
0.8.12 fixes name resolution in SOCKSv5 UDP mappings and eliminate compilation problems on some platforms.
0.8.11 fixes a number of stability bugs and iproves ftppr IPv6 support.
0.8.10 fixes bugs in redirectinon exceptions for HTTP proxy and bandlimiters for old connections on configuration reload.
0.8.9 fixes tcppm failure with parent proxy.
0.8.8 fixes name resolution bug, plugin handling in light version, parent SOCKSv5 over IPv6.
0.8.7 fixes random / system dependant bugs in daemon, extip, ftppr, authcache, SOCKSv5 BIND/UDPASSOC, improves stability under older Win platforms for lite version and adds some new functionality.
0.8.6 fixes random 00012 commands on some configurations
0.8.5 fixes crash on ‘log’ commands in some configurations
0.8.4 fixes random errors on IPv6 connect and adds extip and stacksize support
0.8.3 fixes FreeBSD connect() problems
0.8.2 fixes bug with transparent flag not reset in keep-alive connection
leading to potential DoS from authenticated user; FreeBSD interface binding
problems, random 00013 errors on some Linux glibc versions.
0.8.1 fixes bug with destination networks on ACLs

0.8 intoduces IPv6 support, connect back, DNS proxy via TCP with parent proxy support,
non-blocking name resolution via default system methods on *nix, reduced memory usage and
multiple race conditions fixes.

It’s recommended to move to 0.8.10 or 0.7.1.4 due to security/stability reasons.

Download: http://3proxy.ru/download/

You can use every proxy as a standalone program (socks, proxy, tcppm,
udppm, pop3p) or use combined program (3proxy). Combined proxy
additionally supports features like access control, bandwidth limiting,
limiting daily/weekly/monthly traffic amount,
proxy chaining, log rotation, syslog and ODBC logging, etc.

It’s created to be small, simple and yet very functional.

It may be compiled with Visual C or gcc. Native Win32/Win64 versions included
in archive and supports installation as a service. Currently
3proxy is tested to work under Windows since 98 (Windows before Vista reqires lite version) and up to latest version both i386 and x64,
FreeBSD/i386/x64, NetBSD/i386/x64, OpenBSD/i386/x64, Linux/i386/x64/PPC/Alpha/arm, Mac OS X, Solaris/i386/x64.

See Release Notes and Changes on download page for a full list of features
list.

3proxy is absolutely free (FreeWare) and open source. It can be used
under terms of GNU/GPL. Starting from 0.6 version BSD-style license is used and
any compatible license (Apache license, GPL, LGPL) may be used instead.

Contributors:

  • 3APA3A, 3APA3A at 3proxy.ru, code developer
  • Vladimir Dubrovin, vlad at securityvulns.ru, code developer

Настройка правильной работы SSL

Дальше рассмотрим как выполняется настройка https прокси Nginx. Как я уже сказал, для правильной работы SSL нам понадобится модуль Apache mod_rpaf. Он устанавливает заголовки и переменные таким образом, чтобы прокси мог без проблем использовать https. Его можно установить из официальных репозиториев:

Затем создайте конфигурационный файл для этого модуля:

Строка RPAFProxyIPs задает IP адрес вашего прокси. После завершения настройки активируйте модуль:

Осталось перезапустить Apache:

Дальше нам нужно создать наши сертификаты с помощью OpenSSL:

А файл виртуальных хостов с поддержкой SSL теперь будет выглядеть во так:

ssl on;
ssl_certificate /etc/nginx/ssl/test.io-cert.pem;
ssl_certificate_key /etc/nginx/ssl/test.io-key.pem;

location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Сохраните файл конфигурации и перезапустите Nginx:

Теперь вы можете открыть наш домен в браузере по HTTS и убедится что прокси отлично работает

Обратите внимание, что если вы используете самоподписанный сертификат, то вам придется добавить его в исключения браузера:

Поддержка защищенного протокола включена и SERVER_PORT имеет значение 443, все работает прозрачно, как бы проксирование nginx не осуществляется, а мы направляем запросы непосредственно к Apache.

NGINX Stream (L4 Solution)

Since the upper-layer traffic is transparently transmitted, the critical question that arises here, is whether NGINX should serve as an «L4 proxy» to implement completely transparent transmission of protocols above TCP/UDP. The answer is yes. NGINX 1.9.0 or later supports . This module is not built by default. Add the option under the command to enable this module.

Common Problems

Using NGINX stream as a proxy of the HTTPS traffic at the TCP layer, leads to the same problem mentioned at the beginning of this article: the proxy server does not obtain the target domain name that the client wants to access. This happens because the information obtained at the TCP layer is limited to the IP address and port, without obtaining the domain name. To obtain the target domain name, the proxy must be able to extract the domain name from the upper-layer packets. Therefore, NGINX stream is not an L4 proxy in a strict sense, and it must seek help from the upper layer to extract the domain name.

ngx_stream_ssl_preread_module

In order to obtain the target domain name of HTTPS traffic without decrypting HTTPS traffic, the only method is to use the SNI field contained in the first ClientHello packet during the TLS/SSL handshake. Starting from the version 1.11.5, NGINX supports . This module helps to obtain SNI and ALPN from the ClientHello packet. For a L4 forward proxy, the ability to extract SNI from the ClientHello packet is crucial, otherwise the NGINX stream solution will not be implemented. This, however, also brings a restriction that all clients must include the SNI field in the ClientHello packets during the TLS/SSL handshake. Otherwise, the NGINX stream proxy wouldn’t know the target domain name that the client needs to access.

Environment Building

1) Environment Installation

For the newly installed environment, refer to the common installation steps (content in Chinese), and directly add the , , and options under the «configure» command. Consider the example below for better understanding.

Add the preceding three stream-related modules for already installed and compiled environments as shown below.

2) Configure nginx.conf File

Unlike HTTP, configure NGINX stream in the stream block. Though, the command parameters are similar to those of the HTTP block. The following snippet shows the main configuration.

Application Scenarios

As L4 forward proxy, NGINX basically transparently transmits traffic to the upper layer, and does not require HTTP CONNECT to establish a tunnel. Therefore, the L4 solution is suitable for the transparent proxy mode. For example, when the target domain name is directed to the proxy server by means of DNS resolution, it require simulating the transparent proxy mode by binding to the client.

The following snippet shows the commands on the client:

Common Problems

Now, let’s take a quick look at the key problems concerning the L4 solution.

1) Access attempt failure due to the manual proxy settings on the client.

The L4 forward proxy transparently transmits the upper-layer HTTPS traffic and does not require HTTP CONNECT to establish a tunnel. Thus, it is unnecessary to set the HTTP(S) proxy on the client. Critical question is whether manually setting the HTTP(S) proxy on the client, ensures a successful access attempt. Use the «-x» parameter of cURL to set the forward proxy server and test the access to this server. The following snippet shows the result.

The result indicates that the client tries to establish an HTTP CONNECT tunnel before NGINX. However, as NGINX transparently transmits the traffic, the CONNECT request is directly forwarded to the target server. The target server does not accept the CONNECT method. Therefore, «Proxy CONNECT aborted» reflects in the above snippet, resulting in an access failure.

2) Access attempt failure as the client does not include SNI in the ClientHello packet.

As mentioned earlier, when NGINX stream is used as a forward proxy, it is crucial to use to extract the SNI field from ClientHello. If the client does not include SNI in the ClientHello packet, the proxy server wouldn’t know the target domain name, resulting in an access failure.

In transparent proxy mode (simulated by manually binding hosts), use OpenSSL for simulation on the client.

OpenSSL does not include SNI by default. As the snippet shows, the preceding request terminates in the TLS/SSL handshake phase after ClientHello is sent. This occurs because the proxy server does not know the target domain name where ClientHello should be forwarded.

Using OpenSSL with the «servername» parameter to specify SNI, results in successful access.

DNS

Итак, осталось рассмотреть DNS. Если мы решили использовать дефолтную сеть, с DNS проблем возникнуть не должно. Но если мы взяли кастомную сеть, то здесь есть одна особенность. Дело в том, что докер при создании контейнера в кастомной сети всегда добавляет свой встроенный DNS сервер. Помните, тот, который ? А он не в силах разрешить ipv6-only домены. Скорее всего, это баг. А еще прикол в том, что его нельзя отключить! Единственный способ избавиться от него — руками выкорчевать строчку из resolv.conf перед запуском приложения:

(здесь намеренно не использовалась опция inplace — попробуйте сделать то же самое с и вы поймёте, почему)

После этого наш контейнер снова может успешно резолвить доменные имена, т.к. конфигурация скопирована с хост-машины.

Далее нужно разобраться, как правильно слушать сокеты в приложении, если хотите открыть порт для подключений снаружи и что делать, если приложение написано криво и не поддерживает ipv6.

Общая настройка NGINX

Настройка NGINX состоит из нескольких блоков. Если Вы используете последние версии NGINX, то для получения актуальной информации мы рекомендуем Вам использовать официальные справочные данные, так как в зависимости от версий настройки могут отличаться.

Модули, из которых состоит NGINX, можно настроить при помощи директив, которые, в свою очередь, подразделяются на простые и блочные. Блочная директива отличается от простой тем, что в ней содержатся дополнительные инструкции. Контекст – это блочная директива, внутри которой можно задавать другие директивы. Что касается блоков, то для настройки NGINX необходимо остановиться на следующих разновидностях: блок server отвечает за конфигурацию для виртуального сервера, в блоке http (в котором находится блок server) прописываются директивы HTTP-сервера, а блоки location определяют конфигурацию в зависимости от URI-запроса.

Теперь перейдем к самому процессу настройки NGINX.

Для начала необходимо настроить файл nginx.conf:

$ sudo nano /etc/nginx/nginx.conf

В этом файле Вы можете посмотреть все основные параметры. Рассмотрим, что обозначает каждая из директив:

  • User – пользователь и группа, права которых будут использоваться для запуска рабочего процесса;
  • worker_processes – число рабочих процессов (воркеров). Рекомендуется поставить значение “auto”, т.к. число будет равно числу процессорных ядер;
  • error_log – конфигурирует запись в лог;
  • pid — определяет, в каком файле будет храниться номер основного процесса;

блок events:

  • worker_connections – определяет максимальное количество соединений, которые одновременно может открыть рабочий процесс;
  • use — метод, который будет использоваться для обработки соединений;
  • multi_accept — определяет, какое количество соединений будет принимать рабочий процесс за один раз (on – все новые соединения; off – только одно новое соединение);

блок http:

  • include – включение файла или файлов, которые подходят под заданную маску;
  • default_type — тип данных по умолчанию;
  • server_tokens – позволяет включить (on) или отключить (off) вывод версии NGINX в заголовках ответа или ошибках;
  • sendfile – позволяет включить (on) или отключить (off) метод отправки данных sendfile();
  • sendfile_max_chunk — определяет объем данных, который может передаваться за один вызов sendfile. Если установить на ноль, то одно быстрое соединение может полностью захватить рабочий процесс;
  • tcp_nopush – при включении позволяет передавать заголовок ответа и начало файла одним пакетом, а также передавать файл целым пакетом;
  • reset_timedout_connection — позволяет включить (on) или отключить (off) сброс соединений по таймауту;
  • client_header_timeout – определяет время, за которое клиент должен успеть передать полностью заголовок;
  • client_body_timeout – определяет таймаут при чтении тела запроса клиента;
  • send_timeout – задается время, по истечении которого соединение закрывается, если клиент ничего не принимает;
  • client_header_buffer_size – определяет буфер для чтения заголовка запроса клиента (по умолчанию равняется 1K);
  • client_body_buffer_size – определяет буфер для чтения тела запроса клиента;
  • client_max_body_size – определяет максимально допустимый размер тела запроса клиента;
  • access_log — позволяет включить (on) или отключить (off) лог доступа;
  • include – подключение дополнительных конфигураций.
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *