Настройка реверс-прокси NGINX: различия между версиями

Материал из CrazyGeeks Wiki
(Initial commit)
 
м (Dm sem переименовал страницу WEB:NGINX:Настройка реверс-прокси в Настройка реверс-прокси NGINX без оставления перенаправления)
 
(не показаны 3 промежуточные версии этого же участника)
Строка 1: Строка 1:
Шаблон для {nginx}/sites-available
[[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 domain name, for example "example.com"
# replace {example.com} with your domain
        server_name {domain_name};
server_name {example.com};
        location / {
 
        proxy_pass http://{server_address};    # Replace server address, for example "127.0.0.1"
location / {
        proxy_set_header Host $host;
# replace {server_address} with yours, for example "127.0.0.1:8000"
        proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://{server_address};
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
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.

Пример такого применения

  1. Есть docker-контейнеры или другие приложения внутри локальной сети.
  2. К ним необходимо получить доступ из глобальной сети.
  3. Необходимо обеспечить разные адреса для разных приложений в рамках одного домена.
  4. Необходимо обеспечить эти адреса 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:~#