Настройка реверс-прокси NGINX: различия между версиями
Dm sem (обсуждение | вклад) (Initial commit) |
Dm sem (обсуждение | вклад) м (Dm sem переименовал страницу WEB:NGINX:Настройка реверс-прокси в Настройка реверс-прокси NGINX без оставления перенаправления) |
||
(не показаны 3 промежуточные версии этого же участника) | |||
Строка 1: | Строка 1: | ||
[[Category:NGINX]] | |||
==Положение== | |||
В данном гайде описано, как настроить реверс-прокси в NGINX. | |||
===Пример такого применения=== | |||
# Есть docker-контейнеры или другие приложения внутри локальной сети. | |||
# К ним необходимо получить доступ из глобальной сети. | |||
# Необходимо обеспечить разные адреса для разных приложений в рамках одного домена. | |||
# Необходимо обеспечить эти адреса SSL-сертификатами, централизованно ими управлять, без передачи их приложению. | |||
===Предварительные требования=== | |||
* Настроенная DNS-запись на домен (А-типа). | |||
* Опционально необходимые домены 3 уровня (поддомены) или wildcard. | |||
:: Пример такой записи: | |||
:: <kbd>A *.crazygeeks.info 123.123.123.123</kbd> | |||
===Инструменты, используемые в инструкции=== | |||
* Веб-сервер NGINX. | |||
* Утилита certbot. | |||
==Краткая справка== | |||
===Теория=== | |||
[[File:Reverse proxy h2g2bob.svg|thumb|right|280px|alt=Прокси-сервер подключает интернет к внутренней локальной сети.|Пример сценария: Клиент в Интернете (''облако слева'') делает запрос к '''реверс-прокси''' серверу (''красный овал посередине''). Прокси-сервер проверяет запрос, убеждается в его корректности и в том, что у него нет ресурсов в собсвтенном кэше. Затем передаёт запрос на некоторый веб-сервер во внутренней сети (''овал справа''). Сервер во внутренней сети отвечает на запрос обратно прокси-серверу, который, в свою очередь, передаёт ответ клиенту. При этом клиент в сети не знает о внетренней сети и не может определить, общается ли он с прокси-сервером или напрямую с целевым веб-сервером.]] | |||
Выдержка из [[wikipedia:ru:Обратный прокси|оригинальной статьи]]: | |||
<blockquote> | |||
'''Обратный прокси-сервер''' (англ. ''reverse proxy'') — тип прокси-сервера, который ретранслирует запросы клиентов из внешней сети на один или несколько серверов, логически расположенных во внутренней сети. При этом для клиента это выглядит так, будто запрашиваемые ресурсы находятся непосредственно на прокси-сервере. В отличие от классического прокси, который перенаправляет запросы клиентов к любым серверам в Интернете и возвращает им результат, обратный прокси непосредственно взаимодействует лишь с ассоциированными с ним серверами и возвращает ответ только от них. | |||
</blockquote> | |||
'''Простыми словами:''' | |||
Реверс-прокси сервер позволяет производить общение с серверами во внутренней сети под видом основного сервера. | |||
Такой подход позволяет повысить масштабируемость, производительность, отказоустойчивость и безопасность. Позволяет развернуть множество сервисов на одном IP, используя различные URL, а не порты, что может быть удобнее со стороны пользователя. | |||
Он используется многими крупными сайтами и сервисами для балансировки нагрузки. Реверс-прокси также позволяет удобно кешировать статический контент, дабы разгрузить внутренние серверы и внутрненюю сеть. Обычно он используется для компрессии и добавления TLS-шифрования. | |||
=== Ограничения === | |||
Реверс-прокси работает только с 7 уровнем [[wikipedia:ru:Сетевая модель OSI|модели OSI]]. | |||
Иными словами, если нужно перенаправить трафик, отличный от HTTP (например TCP для SSH), следует использовать NGINX [https://nginx.org/en/docs/stream/ngx_stream_core_module.html mod_stream] | |||
===Работа с NGINX=== | |||
Директория, где находятся предварительные конфигурации сайтов | |||
<syntaxhighlight lang="bash"> | |||
/etc/nginx/sites-available | |||
</syntaxhighlight> | |||
Директория, где находятся активные конфигурации сайтов в сети | |||
<syntaxhighlight lang="bash"> | |||
/etc/nginx/sites-enabled | |||
</syntaxhighlight> | |||
Команды для перезапуска NGINX | |||
<syntaxhighlight lang="bash"> | |||
sudo nginx -t # NGINX Test command | |||
sudo nginx -s reload # NGINX Signal reload command | |||
</syntaxhighlight> | |||
==Инструкция== | |||
===Шаг 1. Пакеты=== | |||
Устанавливаем <kbd>nginx</kbd> и все прочие необходимые пакеты | |||
Для <kbd>deb/ubuntu</kbd>: | |||
<syntaxhighlight lang="bash"> | |||
sudo apt install nginx certbot python3-certbot-nginx | |||
</syntaxhighlight> | |||
Для <kbd>centos/fedora/rhel</kbd>: | |||
<syntaxhighlight lang="bash"> | |||
sudo dnf install nginx certbot python3-certbot-nginx | |||
</syntaxhighlight> | |||
Все дальнейшие действия выполняем от '''<kbd>sudo</kbd>''' | |||
<syntaxhighlight lang="bash"> | |||
sudo su | |||
</syntaxhighlight> | |||
===Шаг 2. Заглушка=== | |||
''Опционально'' настраиваем базовую заглушку для домена. | |||
Нужно, если на основном домене (не на поддомене) ничего не висит, а все приложения находятся на поддоменах. | |||
''Just for fan можно повесить какую-нибудь пугалку.'' | |||
<syntaxhighlight lang="bash"> | |||
# переходим в директорию, где находятся конфигурации сайтов | |||
cd /etc/nginx/sites-available | |||
# создаём файл конфигурации для сайта | |||
nano {example.com} # замените {example.com} на свой домен | |||
</syntaxhighlight> | |||
'''Наполнение файла <kbd>example.com</kbd>:''' | |||
<blockquote> | |||
''Приведён для примера, может быть другим'' | |||
</blockquote> | |||
<syntaxhighlight lang="nginx"> | |||
server { | |||
server_name {example.com}; # замените {example.com} на свой домен | |||
# Server web page location / Расположение директории с сайтом | |||
root /usr/share/nginx/{site_dir}; # замените {site_dir} на свою директорию | |||
# Load configuration files for the default server block. | |||
include /etc/nginx/default.d/*.conf; | |||
error_page 404 /404.html; | |||
location = /404.html { | |||
} | |||
error_page 500 502 503 504 /50x.html; | |||
location = /50x.html { | |||
} | |||
} | |||
</syntaxhighlight> | |||
Выходим из <kbd>nano</kbd> нажатием <kbd>Ctrl+X</kbd>, затем <kbd>Y</kbd>. | |||
===Шаг 3. Создание шаблона=== | |||
В директории <kbd>sites-available</kbd> создаём шаблон для реверс-прокси. | |||
<syntaxhighlight lang="bash"> | |||
# переходим в директорию, где находятся предварительные конфигурации | |||
cd /etc/nginx/sites-available | |||
# создаём файл-шаблон конфигурации для сайта | |||
nano template.site | |||
</syntaxhighlight> | |||
'''Содержание template.site:''' | |||
<blockquote> | |||
''Скопируйте содержимое и сохраните файл '''как есть''''' | |||
</blockquote> | |||
<syntaxhighlight lang="nginx"> | <syntaxhighlight lang="nginx"> | ||
server { | server { | ||
# replace {example.com} with your domain | |||
server_name {example.com}; | |||
location / { | |||
# replace {server_address} with yours, for example "127.0.0.1:8000" | |||
proxy_pass http://{server_address}; | |||
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; | |||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
Выходим из <kbd>nano</kbd> нажатием <kbd>Ctrl+X</kbd>, затем <kbd>Y</kbd>. | |||
===Шаг 4. Создание конфигурации сайта=== | |||
Создаём конфигурацию для конкретного сайта. | |||
Копируем файл <kbd>template.site</kbd> и вносим изменения: | |||
<syntaxhighlight lang="bash"> | |||
# переходим в директорию, где находятся конфигурации сайтов | |||
cd /etc/nginx/sites-available | |||
# создаём файл с конкретным сайтом | |||
cp template.site {app1.example.com} # замените {app1.example.com} на свой домен | |||
</syntaxhighlight> | |||
Наполнение <kbd>app1.example.com</kbd>: | |||
<blockquote> | |||
''Приведён для примера, может быть другим'' | |||
</blockquote> | |||
<syntaxhighlight lang="nginx"> | |||
server { | |||
server_name app1.example.com; # слушаем пакеты с URL "app1.example.com" | |||
# по корню / сайта | |||
location / { | |||
proxy_pass http://192.168.10.254:8080; # Пересылаем их на адрес 192.168.10.254: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; | |||
} | |||
# по uri /api | |||
location /api { | |||
proxy_pass http://192.168.10.253:8000; # Пересылаем их на адрес 192.168.10.253:8000 | |||
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; | |||
} | |||
} | |||
</syntaxhighlight> | |||
В данном случае адрес пересылки указан http, так как подразумевается, что трафик "ходит" внутри локальной сети и его невозможно взломать. | |||
SSL-сертификат будет выпущен в шаге 6. | |||
===Шаг 5. Запуск сайта=== | |||
Для запуска сайта необходимо сделать символическую ссылку на конфигурацию сайта из <kbd>sites-available</kbd> в <kbd>sites-enabled</kbd> | |||
<syntaxhighlight lang="bash"> | |||
# переходим в директорию, где находятся активные конфигурации | |||
cd /etc/nginx/sites-enabled | |||
# для удобства называйте ссылку так же, как и домен | |||
# синтаксис: ln -s файл_откуда_берём_ссылку файл-ссылка | |||
ln -s ../sites-available/{app1.example.com} {app1.example.site} | |||
# замените {app1.example.site} своим доменом | |||
</syntaxhighlight> | |||
Проверяем, что всё хорошо: | |||
<syntaxhighlight lang="bash"> | |||
root@cg-server:/etc/nginx/sites-enabled# ls -al | |||
total 4 | |||
drwxr-xr-x. 1 root root 158 Apr 8 02:11 . | |||
drwxr-xr-x. 1 root root 562 Apr 8 02:09 .. | |||
lrwxrwxrwx. 1 root root 23 Apr 8 02:10 example.com -> ../sites-available/example.site | |||
lrwxrwxrwx. 1 root root 23 Apr 8 02:11 app1.example.site -> ../sites-available/app1.example.site | |||
root@cg-server:/etc/nginx/sites-enabled# | |||
</syntaxhighlight> | |||
Производим проверку и перезапускаем NGINX. | |||
<syntaxhighlight lang="bash"> | |||
sudo nginx -t # NGINX Test command | |||
sudo nginx -s reload # NGINX Signal reload command | |||
</syntaxhighlight> | |||
===Шаг 6. Выпуск сертификата=== | |||
С помощью <kbd>certbot</kbd> выпустим SSL-сертификат для сайта: | |||
<blockquote> | |||
''Следуйте интерактивной инструкции утилиты'' | |||
</blockquote> | |||
<syntaxhighlight lang="bash"> | |||
> certbot | |||
Saving debug log to /var/log/letsencrypt/letsencrypt.log | |||
Which names would you like to activate HTTPS for? | |||
We recommend selecting either all domains, or all domains in a VirtualHost/server block. | |||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |||
1: example.com | |||
2: app1.example.com | |||
3: app2.example.com | |||
4: .... | |||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |||
Select the appropriate numbers separated by commas and/or spaces, or leave input | |||
blank to select all options shown (Enter 'c' to cancel): | |||
</syntaxhighlight> | |||
После этого будет выпущен сертификат, <kbd>certbot</kbd> автоматически отредактирует конфигурацию <kbd>NGINX</kbd>. Также будет настроен автоматический редирект с Non-SSL (HTTP) на HTTPS версию сайта. | |||
Файл будет иметь следующий вид: | |||
<syntaxhighlight lang="nginx"> | |||
server { | |||
server_name example.com; | |||
# ... | |||
# Содержание конфигурационного файла | |||
# ... | |||
listen [::]:443 ssl ipv6only=on; # managed by Certbot | |||
listen 443 ssl; # managed by Certbot | |||
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot | |||
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot | |||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot | |||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot | |||
} | |||
server { | |||
if ($host = example.com) { | |||
return 301 https://$host$request_uri; | |||
} # managed by Certbot | |||
listen 80; | |||
listen [::]:80; | |||
server_name example.com; | |||
return 404; # managed by Certbot | |||
} | |||
</syntaxhighlight> | |||
Используемые сертификаты можно использовать и для передачи внутрь приложений, если это необходимо. | |||
<blockquote> | |||
'''Учтите!''' | |||
<kbd>Certbot</kbd> генерирует сертификаты, которые существуют 90 дней. Они обновляются в автоматическом режиме, поэтому необходимо позаботиться о том, чтобы постоянно обновлять файлы сертификатов для вашего приложения. | |||
</blockquote> | |||
===Шаг 7. Перезапуск сервера=== | |||
Окончательно перезапускаем NGINX и вводим в эксплуатацию новую конфигурацию. | |||
<syntaxhighlight lang="bash"> | |||
sudo nginx -t # NGINX Test command | |||
sudo nginx -s reload # NGINX Signal reload command | |||
</syntaxhighlight> | |||
Если всё в порядке, получим примерно такой вывод консоли: | |||
<syntaxhighlight lang="bash"> | |||
root@cg-server:~# nginx -t | |||
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok | |||
nginx: configuration file /etc/nginx/nginx.conf test is successful | |||
root@cg-server:~# nginx -s reload | |||
root@cg-server:~# | |||
</syntaxhighlight> | </syntaxhighlight> |
Текущая версия от 20:16, 17 мая 2024
Положение
В данном гайде описано, как настроить реверс-прокси в NGINX.
Пример такого применения
- Есть docker-контейнеры или другие приложения внутри локальной сети.
- К ним необходимо получить доступ из глобальной сети.
- Необходимо обеспечить разные адреса для разных приложений в рамках одного домена.
- Необходимо обеспечить эти адреса SSL-сертификатами, централизованно ими управлять, без передачи их приложению.
Предварительные требования
- Настроенная DNS-запись на домен (А-типа).
- Опционально необходимые домены 3 уровня (поддомены) или wildcard.
- Пример такой записи:
- A *.crazygeeks.info 123.123.123.123
Инструменты, используемые в инструкции
- Веб-сервер NGINX.
- Утилита certbot.
Краткая справка
Теория
Выдержка из оригинальной статьи:
Обратный прокси-сервер (англ. reverse proxy) — тип прокси-сервера, который ретранслирует запросы клиентов из внешней сети на один или несколько серверов, логически расположенных во внутренней сети. При этом для клиента это выглядит так, будто запрашиваемые ресурсы находятся непосредственно на прокси-сервере. В отличие от классического прокси, который перенаправляет запросы клиентов к любым серверам в Интернете и возвращает им результат, обратный прокси непосредственно взаимодействует лишь с ассоциированными с ним серверами и возвращает ответ только от них.
Простыми словами:
Реверс-прокси сервер позволяет производить общение с серверами во внутренней сети под видом основного сервера.
Такой подход позволяет повысить масштабируемость, производительность, отказоустойчивость и безопасность. Позволяет развернуть множество сервисов на одном IP, используя различные URL, а не порты, что может быть удобнее со стороны пользователя.
Он используется многими крупными сайтами и сервисами для балансировки нагрузки. Реверс-прокси также позволяет удобно кешировать статический контент, дабы разгрузить внутренние серверы и внутрненюю сеть. Обычно он используется для компрессии и добавления TLS-шифрования.
Ограничения
Реверс-прокси работает только с 7 уровнем модели OSI.
Иными словами, если нужно перенаправить трафик, отличный от HTTP (например TCP для SSH), следует использовать NGINX mod_stream
Работа с NGINX
Директория, где находятся предварительные конфигурации сайтов
/etc/nginx/sites-available
Директория, где находятся активные конфигурации сайтов в сети
/etc/nginx/sites-enabled
Команды для перезапуска NGINX
sudo nginx -t # NGINX Test command
sudo nginx -s reload # NGINX Signal reload command
Инструкция
Шаг 1. Пакеты
Устанавливаем nginx и все прочие необходимые пакеты
Для deb/ubuntu:
sudo apt install nginx certbot python3-certbot-nginx
Для centos/fedora/rhel:
sudo dnf install nginx certbot python3-certbot-nginx
Все дальнейшие действия выполняем от sudo
sudo su
Шаг 2. Заглушка
Опционально настраиваем базовую заглушку для домена.
Нужно, если на основном домене (не на поддомене) ничего не висит, а все приложения находятся на поддоменах.
Just for fan можно повесить какую-нибудь пугалку.
# переходим в директорию, где находятся конфигурации сайтов
cd /etc/nginx/sites-available
# создаём файл конфигурации для сайта
nano {example.com} # замените {example.com} на свой домен
Наполнение файла example.com:
Приведён для примера, может быть другим
server {
server_name {example.com}; # замените {example.com} на свой домен
# Server web page location / Расположение директории с сайтом
root /usr/share/nginx/{site_dir}; # замените {site_dir} на свою директорию
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
Выходим из nano нажатием Ctrl+X, затем Y.
Шаг 3. Создание шаблона
В директории sites-available создаём шаблон для реверс-прокси.
# переходим в директорию, где находятся предварительные конфигурации
cd /etc/nginx/sites-available
# создаём файл-шаблон конфигурации для сайта
nano template.site
Содержание template.site:
Скопируйте содержимое и сохраните файл как есть
server {
# replace {example.com} with your domain
server_name {example.com};
location / {
# replace {server_address} with yours, for example "127.0.0.1:8000"
proxy_pass http://{server_address};
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;
}
}
Выходим из nano нажатием Ctrl+X, затем Y.
Шаг 4. Создание конфигурации сайта
Создаём конфигурацию для конкретного сайта.
Копируем файл template.site и вносим изменения:
# переходим в директорию, где находятся конфигурации сайтов
cd /etc/nginx/sites-available
# создаём файл с конкретным сайтом
cp template.site {app1.example.com} # замените {app1.example.com} на свой домен
Наполнение app1.example.com:
Приведён для примера, может быть другим
server {
server_name app1.example.com; # слушаем пакеты с URL "app1.example.com"
# по корню / сайта
location / {
proxy_pass http://192.168.10.254:8080; # Пересылаем их на адрес 192.168.10.254: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;
}
# по uri /api
location /api {
proxy_pass http://192.168.10.253:8000; # Пересылаем их на адрес 192.168.10.253:8000
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;
}
}
В данном случае адрес пересылки указан http, так как подразумевается, что трафик "ходит" внутри локальной сети и его невозможно взломать.
SSL-сертификат будет выпущен в шаге 6.
Шаг 5. Запуск сайта
Для запуска сайта необходимо сделать символическую ссылку на конфигурацию сайта из sites-available в sites-enabled
# переходим в директорию, где находятся активные конфигурации
cd /etc/nginx/sites-enabled
# для удобства называйте ссылку так же, как и домен
# синтаксис: ln -s файл_откуда_берём_ссылку файл-ссылка
ln -s ../sites-available/{app1.example.com} {app1.example.site}
# замените {app1.example.site} своим доменом
Проверяем, что всё хорошо:
root@cg-server:/etc/nginx/sites-enabled# ls -al
total 4
drwxr-xr-x. 1 root root 158 Apr 8 02:11 .
drwxr-xr-x. 1 root root 562 Apr 8 02:09 ..
lrwxrwxrwx. 1 root root 23 Apr 8 02:10 example.com -> ../sites-available/example.site
lrwxrwxrwx. 1 root root 23 Apr 8 02:11 app1.example.site -> ../sites-available/app1.example.site
root@cg-server:/etc/nginx/sites-enabled#
Производим проверку и перезапускаем NGINX.
sudo nginx -t # NGINX Test command
sudo nginx -s reload # NGINX Signal reload command
Шаг 6. Выпуск сертификата
С помощью certbot выпустим SSL-сертификат для сайта:
Следуйте интерактивной инструкции утилиты
> certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: example.com
2: app1.example.com
3: app2.example.com
4: ....
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
После этого будет выпущен сертификат, certbot автоматически отредактирует конфигурацию NGINX. Также будет настроен автоматический редирект с Non-SSL (HTTP) на HTTPS версию сайта.
Файл будет иметь следующий вид:
server {
server_name example.com;
# ...
# Содержание конфигурационного файла
# ...
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com;
return 404; # managed by Certbot
}
Используемые сертификаты можно использовать и для передачи внутрь приложений, если это необходимо.
Учтите!
Certbot генерирует сертификаты, которые существуют 90 дней. Они обновляются в автоматическом режиме, поэтому необходимо позаботиться о том, чтобы постоянно обновлять файлы сертификатов для вашего приложения.
Шаг 7. Перезапуск сервера
Окончательно перезапускаем NGINX и вводим в эксплуатацию новую конфигурацию.
sudo nginx -t # NGINX Test command
sudo nginx -s reload # NGINX Signal reload command
Если всё в порядке, получим примерно такой вывод консоли:
root@cg-server:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@cg-server:~# nginx -s reload
root@cg-server:~#