Обратный прокси с SSL


Введение

Часто бывает полезно сделать приложение, находящееся в локальной разработке, временно доступным в публичном интернете. В Blended Edge, например, наша работа по автоматизации интеграций означает, что мы используем много потоков OAuth2, а использование OAuth2 для разрабатываемого приложения (обычно) требует общедоступной конечной точки с SSL-сертификатом.

Ngrok — это инструмент обратного прокси, который делает это очень просто, но также довольно легко настроить обратный прокси, используя экземпляр AWS EC2, certbot от Let’s Encrypt и команду ssh.

Это описание предполагает наличие базовых знаний о DNS, ssh и экземплярах EC2 (или аналогичных облачных вычислительных ресурсах).

Создание удаленного сервера

Мы начнем с запуска экземпляра EC2 на AWS, который будет выступать в качестве удаленного сервера. Конечно, это можно сделать с помощью любого облачного провайдера, например Azure или Digital Ocean.

Задайте имя экземпляра как «Reverse-Proxy», а в разделе «Образы приложений и ОС» выберите Ubuntu. На момент написания этой статьи образ Ubuntu по умолчанию — 22.04.

У меня уже есть пара ключей SSH, которую я буду использовать для доступа к этому экземпляру, но если у вас ее нет или вы хотите использовать новую пару ключей, просто нажмите «Создать новую пару ключей».

Создайте новую группу безопасности, которая разрешит HTTP/HTTPS трафик с любого IP адреса, но ограничит SSH трафик только вашим собственным IP.

Нажмите «Launch Instance», перейдите на страницу обзора экземпляров и подождите, пока пройдет проверка состояния нового экземпляра. Это может занять пару минут.

Когда экземпляр будет готов, перейдите на страницу обзора экземпляра и нажмите «Подключиться» в правом верхнем углу. Выполните следующие шаги для подключения.

# if this is a new ssh key you may need to specify the path to the key
# ssh -i /path/to/key.pem <user>@<address>
ssh ubuntu@ec2-13-59-152-133.us-east-2.compute.amazonaws.com
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Установите Nginx

Обновите список пакетов, обновите пакеты и установите nginx.

sudo apt update
sudo apt upgrade -y
sudo apt install nginx
Войдите в полноэкранный режим Выход из полноэкранного режима

Если вы отправите GET-запрос на IP-адрес вашего экземпляра через веб-браузер или curl, вы получите страницу nginx по умолчанию.

curl http://13.59.152.133
Войдите в полноэкранный режим Выход из полноэкранного режима
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
Войдите в полноэкранный режим Выход из полноэкранного режима

Домен и SSL

Укажите домен на публичный IP-адрес вашего экземпляра. Серверы имен для моего домена hydewd.com находятся в DigitalOcean, поэтому в моем случае обновление записи A для указания домена на мой экземпляр выглядит следующим образом:

Примечание: Если вы собираетесь выполнять серьезную или долгосрочную работу с этой установкой, вам следует выделить эластичный IP-адрес, связать его с вашим экземпляром и указать ваш домен на эластичный IP.

Установите certbot от Let’s Encrypt для автоматической установки SSL-сертификата.

sudo apt install certbot python3-certbot-nginx -y
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Теперь запустите certbot, чтобы сделать запрос на SSL-сертификат. Здесь я указываю, что хочу покрыть как голый домен hydewd.com, так и www.hydewd.com. Вам будет предложено указать адрес электронной почты для уведомлений о продлении, согласиться с условиями предоставления услуг, а также спросить, согласны ли вы предоставить свою электронную почту Electronic Frontier Foundation (последнее необязательно).

sudo certbot --nginx -d hydewd.com -d www.hydewd.com
Вход в полноэкранный режим Выйдите из полноэкранного режима

Если все сработало, теперь вы должны иметь возможность загрузить страницу nginx по умолчанию по адресу https://<your-domain>.

Конфигурация Nginx

Следующий шаг — указать nginx перенаправлять http/https запросы на другой порт (8080). На следующем шаге мы туннелируем этот порт на нашу локальную машину.

sudo vi /etc/nginx/sites-available/default
Вход в полноэкранный режим Выход из полноэкранного режима

В блоке location стандартного блока server добавьте строку для перенаправления трафика на http://127.0.0.1:8080.

Мы будем изменять содержимое блока location. Вот как это выглядит для начала:

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
Вход в полноэкранный режим Выйти из полноэкранного режима

Измените содержимое блока location на:

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://127.0.0.1:8080/;
    }
Войти в полноэкранный режим Выйти из полноэкранного режима

Сохраните файл и убедитесь, что конфигурация верна, выполнив команду sudo nginx -t. Если ошибки нет, перезапустите nginx, чтобы применить последние изменения.

sudo nginx -s reload
Вход в полноэкранный режим Выход из полноэкранного режима

Удаленная переадресация SSH

Последним шагом будет туннелирование запросов с порта 8080 сервера на локальную машину. Это можно сделать с помощью команды ssh remote forwarding.

ssh -R 8080:localhost:8080 ubuntu@ec2-18-217-182-155.us-east-2.compute.amazonaws.com
Вход в полноэкранный режим Выйдите из полноэкранного режима

Теперь запустите сервер локально на порту 8080. Вот, например, простой сервер node, использующий фреймворк express, который будет отвечать на все запросы GET с некоторой информацией о том, что сервер видит во входящем запросе.

mkdir local-server && cd local-server
npm init -y
npm install express
Вход в полноэкранный режим Выход из полноэкранного режима

Создайте файл index.js со следующим содержимым:

const express = require('express')
const app = express()
const port = 8080;

app.get('*', (req, res) => {
  const { baseUrl, headers, hostname, ip, method, originalUrl, path, protocol } = req;
  res.json({
    baseUrl,
    headers,
    hostname,
    ip,
    method,
    originalUrl,
    path,
    protocol
  })
});

app.listen(port, () => console.log(`App listening at http://localhost:${port}`));
Вход в полноэкранный режим Выход из полноэкранного режима
node index.js
Войти в полноэкранный режим Выйти из полноэкранного режима

Отправка запроса на ваш домен теперь будет возвращать ответ с вашего локального экспресс-сервера.

curl -s 'https://www.hydewd.com/some/path?some=query&another=123'
Войти в полноэкранный режим Выйти из полноэкранного режима

Пример ответа:

{
  "baseUrl": "",
  "headers": {
    "host": "www.hydewd.com",
    "x-real-ip": "104.1.2.3",
    "connection": "close",
    "user-agent": "curl/7.68.0",
    "accept": "*/*"
  },
  "hostname": "www.hydewd.com",
  "ip": "::ffff:127.0.0.1",
  "method": "GET",
  "originalUrl": "/some/path?some=query&another=123",
  "path": "/some/path",
  "protocol": "http"
}
Войти в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что заголовок x-real-ip отображает IP-адрес конечного пользователя, делающего запрос, а не IP-адрес экземпляра. Это результат работы строки конфигурации proxy_set_header X-Real-IP $remote_addr;.

Заключение

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

Полезные ссылки

Руководство Digital Ocean: Как установить Nginx

Nginx Docs: Документация по обратному прокси

Документы Nginx: Установка Lets Encrypt

Оцените статью
devanswers.ru
Добавить комментарий