У меня есть 2 FQDN stage.external.example.net
и external.example.net
, которые разрешаются в один и тот же внешний публичный IP-адрес, например, 140.240.40. 111
(настроен на внешнем DNS)
HTTPS запросы к этому IP (например, GET https://stage.external.example.net) затем направляются на мой NGINX сервер, который имеет одну ногу в DMZ, например, 172.20.180.111
и другую во внутреннюю сеть, например, 10.222.20. 1/16
, на котором у меня есть 2 докер-хоста, которые разрешаются внутри следующим образом:
stage.internal.example.net
=> 10.222.20.14
internal.example.net
=> 10.222.20.15
Я пытаюсь настроить мой NGINX на маршрутизацию:
stage.external.example. net:443
на внутренний stage.internal.example.net:443
external.example.net:443
на внутренний internal.example.net:443
stage.external.example.net:443 -> 140.240.40.111:443 -> 172.20.180.111:443 (NGINX) -> 10.222.20.14:443 (stage.internal.example.net)
external.example.net:443 -> 140.240.40.111:443 -> 172.20.180.111:443 (NGINX) -> 10.222.20.15:443 (internal.example.net)
Я вижу, что запросы попадают на мой NGINX в access.log, но затем запрос, похоже, не направляется на мои докер-хосты.
Ниже приведена конфигурация, которую я пробовал, любые указания приветствуются:
nginx. conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
upstream internal_stage {
server 10.222.20.14:443; # docker host stage.internal.example.net
}
upstream internal_production {
server 10.222.20.15:443; # docker host internal.example.net
}
# Forward all requests to stage.external.example.net:443
server {
listen 443;
server_name stage.external.example.net;
location / {
proxy_pass http://internal_stage;
}
}
# Forward all requests to external.example.net:443
server {
listen 443;
server_name external.example.net;
location / {
proxy_pass http://internal_production;
}
}
}
error_log
to info
Теперь я могу наблюдать, что получаю 400 Bad Request
Client sent invalid request while reading client request line
stream
блока и ssl_preread
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.service-api.log main;
error_log /var/log/nginx/error.service-api.log info;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
}
include /etc/nginx/passthrough.conf;
stream {
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log /var/log/nginx/access.log basic;
error_log /var/log/nginx/error.log;
upstream internal_stage {
server 10.222.20.14:443 max_fails=5 fail_timeout=300; # docker host stage.internal.domain.net
}
upstream internal_production {
server 10.222.20.15:443 max_fails=5 fail_timeout=300; # docker host stage.internal.domain.net
}
map $ssl_preread_server_name $upstream {
stage.external.polylabs.net internal_stage;
external.polylabs.net internal_production;
}
server {
listen 443;
proxy_pass $upstream;
ssl_preread on;
proxy_next_upstream on;
}
}
Похоже, в вашем вопросе вы объединяете порт 443 с HTTPS. Если вы имеете в виду HTTP с шифрованием на порту 443, то это просто https, но имя хоста: 443 ничего не говорит нам ни о протоколе, ни о том, есть ли шифрование. Возможная причина для отклонения вопроса.
Когда вы используете «proxy_pass», nginx перенаправляет HTTP-запрос на указанный адрес, но HTTP явно поддерживает мультиплексирование разных (виртуальных) имен хостов на одном IP-адресе.Стоит упомянуть, что существует другой дополнительный метод, реализованный в TLS для мультиплексирования имени хоста (SNI), и здесь предоставленная вами конфигурация конфликтует с тем, что я считаю вашей целью; подключение к https на сервере. Ваша конфигурация подключается к http. Еще одна причина, по которой кто-то отклонил ваш вопрос. Однако директива proxy_pass Nginx будет обрабатывать перезапись подтверждения SNI автоматически, так что это не причина ваших текущих проблем.
При этом, если вы явно не укажете Nginx не делать этого, он проверит сертификат, предоставленный внутренним сервером. Использует ли он сертификат, который должен быть проверен nginx? Вы можете проверить это на хосте nginx с помощью openssl s_client.
похоже, что запрос не перенаправляется на мои докеры.
Как вы пришли к такому выводу? (отсутствие обоснования этого может быть еще одной причиной отклонения вашего вопроса).
Это может быть так, но даже если запросы перенаправляются на предполагаемый IP-адрес / порт, они приведут к ошибке, если этот бэкэнд не считает себя исходным сервером для "stage.external.domain.net ".
Безусловно, самое простое решение - сообщить внутреннему веб-серверу, что это действительно "stage.external.domain.net". Но можно и запрос переписать ....
server_name external.polylabs.net;
location / {
proxy_set_header Host "internal.polylabs.net";
proxy_ssl_verify off;
proxy_pass https://internal.polylabs.net;
}
кажется, что серверная часть - это https, поэтому proxy_pass должен быть https, как показано ниже: location / upstream { proxy_pass https://backend.example.com; } Пожалуйста, проверьте ссылку ниже: { {1}} https://docs.nginx.com/nginx/admin-guide/security-controls/securing-http-traffic-upstream/