Питание прокси

В тот или иной момент вы, скорее всего, слышали термин «обратный прокси» или «прокси-сервер», который встречается то тут, то там, но что это такое? В контексте компьютерных сетей Консорциум World Wide Web (или W3C) определяет их следующим образом:

Агент, который ретранслирует сообщение между агентом запрашивающей стороны и агентом поставщика, который представляется веб-службе запрашивающей стороной.

Прокси обычно делятся на две отдельные категории при рассмотрении типичных реализаций:

  • Переслать прокси
  • Обратный прокси

Прямые прокси чрезвычайно распространены в бизнес-сетях любого размера и особенно полезны в крупномасштабных корпоративных средах. Вы, скорее всего, использовали его каждый раз, когда вы были за компьютером на работе, пытаясь получить доступ к веб-сайту или другому сетевому ресурсу. Вы когда-нибудь пытались перейти на сайт, который ваша компания заблокировала? Это прямой прокси-сервер, фильтрующий веб-запросы перед отправкой в ​​​​сеть!

Хотя я уверен, что многие из нас имели недовольство, увидев такие надоедливые оповещения о прокси, эти конфигурации нас здесь не интересуют! Мы хотим воспользоваться мощным обратным прокси:

Обратный прокси-сервер — это сервер, который находится перед веб-серверами и перенаправляет запросы клиентов (например, веб-браузера) на эти веб-серверы. Обычно обратные прокси-серверы используются для повышения безопасности, производительности и надежности¹.

Наш сценарий

У вас есть общедоступный веб-сайт, и вы хотите создать несколько различных внутренних API-интерфейсов, чтобы эффективно и безопасно использовать различные службы уведомлений, не открывая несколько открытых портов. Как нам это сделать? Правильно… обратный прокси!

Как и многие вещи в мире программирования, есть несколько способов выполнить задачу. Способ, которым мы собираемся структурировать этот проект (который, как правило, я предпочитаю), будет следующим:

  • Воспользуйтесь преимуществом скорости Go и богатыми платформами сообщества, чтобы создать API для нашей службы уведомлений.
  • Используйте гибкость и дополнительную безопасность контейнеризации с помощью Docker и Docker Compose.
  • Используйте встроенные прокси-функции Nginx для обработки маршрутизации всех наших сервисов.

Общая структура нашего проекта выглядит следующим образом:

.
├── api
├── backend
│   └── main
│       └── assets
│           ├── css
│           ├── fonts
│           ├── img
│           └── js
├── devices
└── nginx
└── sites-enabled

Что касается каталогов ресурсов, папка активов довольно проста. Его родительский каталог, backend/main, содержит базовый шаблон веб-сайта, используемый для имитации общедоступного сайта, используемого в реальном развертывании.

Возможно, вы заметили два интересных каталога в приведенной выше структуре. Папки api и devices содержат пример кода для имитации серверных API, которые должны быть доступны для получения уведомлений. Один предназначен для отправки новых контактных форм, а другой — для предупреждений датчиков устройства для имитации срабатывания локального устройства IoT.

Поскольку Go обеспечивает отличную скорость и параллелизм, простой синтаксис и многочисленные библиотеки сообщества, он легко становится популярным для программирования API. Давайте посмотрим на наш пример кода для недавно отправленных контактных форм веб-сайта:

Программа относительно проста, но давайте пробежимся по основным пунктам кода:

  • Мы начинаем с запуска функции init для добавления/создания файла журнала для отслеживания всех запросов в течение жизни контейнера (подробнее об этом позже)
  • Мы импортируем мощную библиотеку Gorilla Mux, а также Logrus, чтобы предоставить простые интерфейсы для создания пользовательских маршрутов и записей в журнале.
  • Создайте две функции конечной точки для сопоставления запросов маршрута, каждая из которых вызывает функцию выполнения, которая запускает скрипт Python, специфичный для маршрута… в результате чего вам (или, возможно, клиенту) отправляется оповещение по электронной почте.
  • Наконец, мы создаем основной маршрутизатор и объявляем наши пользовательские маршруты в теле функции main, а также запускаем наш сервер API на определенном порту.

Каталог devices использует ту же структуру кода для создания своего API. Основное отличие заключается в скрипте Python, используемом для службы уведомлений, и создании специальных структур Sensor для каждого датчика устройства.

Следующий важный раздел проекта включает в себя создание контейнеров, которые будут запускать серверы API. Чтобы обеспечить дополнительную модульность и безопасность нашему веб-серверу, мы будем использовать Docker для запуска двух разных API в их собственных изолированных средах. Если вы новичок во всей концепции контейнеризации, обязательно ознакомьтесь с обширной документацией, доступной на веб-сайте Docker, чтобы ускорить работу и настроить использование контейнеров на вашем компьютере.

Для Docker доступна отличная программа оркестровки под названием Docker Compose. Это позволяет нам написать простой файл YAML, указывающий, какие образы докеров и ресурсы мы планируем использовать, и он идеально соответствует нашим потребностям в этом проекте!

Вот как наш веб-сервер будет раскручивать нужные нам контейнеры:

Подробное описание каждого шага, который проходит Docker Compose, выходит за рамки этой статьи; однако, если вы посмотрите на каталоги devices и api, вы увидите Dockerfile в каждом из них. Они содержат инструкции по созданию образа для каждой службы… и это то, что compose использует в качестве плана. Через минуту мы рассмотрим процесс высокого уровня!

Заключительные части

Все, что нам осталось сделать, это убедиться, что на нашем сервере правильно установлен/настроен Nginx для размещения нашего сайта и соответствующей маршрутизации входящих запросов.

Если вы еще не установили и не настроили Nginx на своем сервере, рекомендую ознакомиться с одним из нескольких пошаговых руководств, доступных на Digital Ocean. Они не только проведут вас через этапы установки и базовой настройки, но также включают шаги по настройке бесплатных сертификатов LetsEncrypt, чтобы ваша страница могла использовать SSL/TLS.

После того, как каталоги вашего веб-сервера настроены (если они еще не были настроены), вам нужно сделать только одно большое изменение. Если вы следовали любому из пошаговых руководств Digital Ocean, скорее всего, у вас должен быть файл, созданный для вашего веб-сайта внутри /etc/nginx/sites-enabled. Именно здесь объявляется важная конфигурация, позволяющая нам использовать возможности обратного прокси-сервера Nginx! Ниже приведен пример конфигурации для нашей новой веб-страницы и маршрутов API:

Имейте в виду, что это лишь частичный фрагмент файла конфигурации, так как CertBot автоматически добавляет другие строки при получении сертификата Lets Encrypt (см. статьи Digital Ocean), а также другие фрагменты, которые здесь не имеют значения.

Основные детали, которые следует вынести из вышеизложенного, следующие:

  • Мы объявляем блоки location с именами маршрутов и местами, куда мы хотим их проксировать. Например, если запрос должен был прийти с URL-адресом awesomeinc.com/contact, наш сервер перенаправил бы его на порт 8081.
  • URL-адреса proxy_pass соответствуют портам, которые прослушивают наши контейнеры API.
  • limit_req и другие объявления рекомендуются документацией Nginx для ограничения одновременных запросов и не являются полностью необходимыми сами по себе.

После этого все, что осталось, — это перезапустить (или, наконец, запустить) нашу службу Nginx, используя sudo systemctl restart nginx. Если вы размещаете этот сервер на облачной виртуальной машине, используя что-то вроде AWS EC2, обязательно зайдите в свою сетевую панель управления, чтобы разрешить только входящий сетевой трафик на порты 80 и 443 (что должно было быть сделано для получения сертификатов SSL). Если вы создали правильные записи DNS, теперь вы сможете перейти на свою домашнюю страницу и увидеть, что веб-сайт обслуживается должным образом!

Последний шаг

Итак, теперь наш веб-сервер запущен и работает, но наши API пока недоступны.

Убедившись, что ваша основная веб-страница доступна, вернитесь к терминалу вашего сервера и скажите docker-compose, чтобы он развернул эти контейнеры для вас! Прежде чем что-либо делать, чрезвычайно важно убедиться, что ваш компоновочный файл YAML находится в основе каталога вашего проекта, а ваши различные API-интерфейсы сервисного контейнера находятся в их собственной конкретной папке (чтобы соответствовать объявлениям компоновочного файла):

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

sudo docker-compose up -d

Вот что будет делать эта команда:

  • Указывает compose просмотреть каждую папку, объявленную в файле конфигурации, и создать для них «образы», ​​используя Dockerfile в каждом
  • Эти изображения будут использоваться композицией для создания новых контейнеров.
  • После завершения процесса сборки docker-compose запустит все в фоновом режиме, чтобы разрешить дальнейшее использование терминала (-d означает «отключено»).

Вам может понадобиться перезапустить службу nginx, а может и не понадобиться, но как только все будет наконец сделано, вы сможете протестировать запросы к своим серверным службам API! Мы добавили специальный «тестовый» маршрут в приведенный выше пример кода. Откройте терминал на вашем локальном компьютере и используйте curl для запроса вашего домена с тестовой конечной точкой:

curl https://www.awesomeinc.com/test

Если это работает, отличная работа! Если нет… не расстраивайтесь! При настройке серверной части, такой как эта, есть много движущихся частей. Вернитесь к файлам конфигурации, проверьте объявления конечных точек… затем повторите попытку.

Проект и все соответствующие файлы можно найти на GitHub:



¹Что такое обратный прокси-сервер? | Объяснение прокси-серверов | Cloudflare. https://www.cloudflare.com/learning/cdn/glossary/reverse-proxy/.