Nginx connect() не удалось (111: соединение отклонено) при подключении к восходящему потоку, клиент: 192.168.128.1, сервер: hello-1.local

Nginx connect() не удалось (111: соединение отклонено) при подключении к восходящему потоку, клиент: 192.168.128.1, сервер: hello-1.local

Я пытаюсь настроить ssl в моей среде django + docker + nginx. Однако я столкнулся с этой ошибкой:

*19 connect() не удалось (111: соединение отклонено) при подключении к восходящему потоку, клиент: 192.168.128.1, сервер: hello-1.local, запрос: "GET / HTTP/1.1", восходящий поток: "https://192.168.128.4:443/", хост: "hello-1.local"

Моя конфигурация Nginx:

client_max_body_size 10M;

upstream web {  
  ip_hash;
  server web:443;
}

server {
    listen 80;
    server_name hello-1.local;
    return 301 https://$host$request_uri;
}

server {    
    
    location /static/ {    
        autoindex on;    
        alias /src/static/; 
    }

    location /media/ {
        autoindex on;
        alias /src/media/;
    }

``

    location / {
        proxy_pass https://web/;
    }
    
    listen 443 ssl;
    server_name hello-1.local;
    ssl_certificate /etc/certs/hello-1.local.crt;
    ssl_certificate_key /etc/certs/hello-1.local.key;
    
} 

docker-compose.yml:

version: "3"

volumes:
  local_postgres_data: {}
  local_postgres_data_backups: {}

services:
  nginx:
    image: nginx:alpine
    container_name: nz01
    ports:
      - 443:443
      - 80:80
    volumes:
      - ./src:/src
      - ./config/nginx:/etc/nginx/conf.d
      - ./config/certs:/etc/certs
    depends_on:
      - web
    networks:
      - djangonetwork
  web:
    build:
      context: .
      dockerfile: compose/django/Dockerfile
    container_name: dz01
    depends_on:
      - db
    volumes:
      - ./src:/src
    expose:
      - 8000
    links:
      - redis
    env_file:
      - ./.envs/.django
    networks:
      - djangonetwork
  db:
    build:
      context: .
      dockerfile: compose/postgres/Dockerfile
    container_name: pz01
    env_file:
      - ./.envs/.postgres
    volumes:
      - local_postgres_data:/var/lib/postgresql/data
      - local_postgres_data_backups:/backups
    networks:
      - djangonetwork
  redis:
    image: redis:alpine
    container_name: rz01
    ports:
      - "6379:6379"
    networks:
      - djangonetwork

networks:
  djangonetwork:
    driver: bridge

В браузере я получаю ошибку 502 Bad Gateway, а без ssl сайт работает нормально. В чем может быть проблема?

решение1

Так что же такое восходящий поток?

Восходящий поток определяется здесь:

upstream web {  
  ip_hash;
  server web:443;
}

Мое первое прочтение заключается в том, что Nginx не может правильно подключиться к вышестоящему серверу с именем web.

Причин может быть несколько:

  • ваш Nginx не может разрешитьweb
  • веб-сервер, работающий на webне обслуживает https/порт 443
  • веб-сервер, работающий на, webне использует действительный и доверенный сертификат для имени хостаweb

Взглянем на ваш docker-compose.yml:

  • приложение webиспользует порт 8000, но вы хотите подключиться к порту 443 в Nginx, также используя неправильный протокол (я полагаю)

Поэтому решением будет изменить upstream-config в nginx.conf следующим образом:

upstream web {  
  ip_hash;
  server web:8000;
}

и блок местоположения, подобный этому (https --> http):

location / {
    proxy_pass http://web/;
}

Относительно SSL/TLS с прокси/апстримами: пожалуйста, ознакомьтесь с документацией Nginx по этому вопросу:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify

решение2

У меня похожая настройка в моем веб-приложении, где Nginx является обратным прокси для Dockerized Django и React. Я также использую самоподписанный сертификат для SSL в локальной разработке.

У меня возникли трудности, поскольку React (Next.js) извлекает данные из REST API Django, но некоторые запросы поступают с сервера, а другие — с клиента. Серверные запросы могли использовать http://backend:8000(имя службы Docker и открытый порт), но клиентские запросы должны были проходить через https://example.local.

Если кто-то застрял на этом и использует Swagger UI (например, drf-yasg), это была моя ахиллесова пята --- вам НУЖНО настроить OpenAPI "DEFAULT_API_URL". Если у вас есть самоподписанный SSL-сертификат с example.local, вам следует настроить его https://example.localкак свой Swagger URL. С drf-yasg, вот мой settings.py:

# Swagger
ENDPOINT_DOMAIN = "https://example.com"
if DEBUG:
    ENDPOINT_DOMAIN = "https://example.local"
SWAGGER_SETTINGS = {
    'SECURITY_DEFINITIONS': {
        'basic': {
            'type': 'basic'
        }
    },
    'DEFAULT_API_URL': ENDPOINT_DOMAIN,
}

Кроме того, мне пришлось сопоставить это в моей конфигурации Next.js ( next.config.js):

const nextConfig = {
  ...
  assetPrefix: 'https://example.local',
  ...
}

В итоге моя конфигурация Nginx выглядит так:

server {
  listen 80;
  listen [::]:80;

  server_name example.local;
  return 302 https://example.local$request_uri;
}

# Main server directive
server {
  http2               on;

  listen 443          default ssl;
  listen [::]:443     default ssl;

  ssl_certificate     /etc/nginx/certs/example.test.crt;
  ssl_certificate_key /etc/nginx/certs/example.test.key;

  root                /app;
  server_name         example.local;

  charset utf-8;

  gzip on;
  gzip_disable "msie6";
  gzip_comp_level 6;
  gzip_min_length 1100;
  gzip_buffers 16 8k;
  gzip_proxied any;
  gzip_types
    text/plain
    text/css
    text/js
    text/xml
    text/javascript
    application/javascript
    application/json
    application/xml
    application/rss+xml
    image/svg+xml;

  # Setup frontend requests to use port 3000
  location @frontend {
    internal;
    root       /app/frontend/;
    proxy_pass http://frontend:3000;

    proxy_redirect off;
    proxy_set_header Host              $host;
    proxy_set_header X-Forwarded-For   $remote_addr;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-NginX-Proxy     true;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Url-Scheme      $scheme;
  }

  # Setup backend requests to use port 8000
  location @backend {
    proxy_pass http://backend:8000;

    proxy_redirect off;
    proxy_ssl_verify off;
    proxy_set_header Host              $host;
    proxy_set_header X-Forwarded-For   $remote_addr;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-NginX-Proxy     true;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Url-Scheme      $scheme;
  }

  # Frontend =============================================
  location / {
    try_files $uri @frontend;
  }

  location ~ ^/assets/(.*)$ {
    root      /app/frontend/public/;
    try_files $uri @frontend;
  }

  location ~ ^/favicon(.*)$ {
    root      /app/frontend/public/assets/favicon/;
    try_files $uri @frontend;
  }

  location ~ ^/_next/(.*)$ {
    root      /app/frontend/;
    try_files $uri @frontend;
  }

  location /_next/webpack-hmr {
    root      /app/frontend/;
    try_files $uri @frontend;

    # Websockets
    proxy_http_version 1.1;
    proxy_set_header   Connection "upgrade";
    proxy_set_header   Upgrade $http_upgrade;
  }

  location /404 {
    try_files $uri @frontend;
  }


  # Backend ===============================================
  location ~ ^/swagger(.*)$ {
    try_files $uri @backend;
  }

  location ~ ^/redoc(.*)$ {
    try_files $uri @backend;
  }

  location ~ ^/admin(.*)$ {
    try_files $uri @backend;
  }

  location ~ ^/api(.*)$ {
    try_files $uri @backend;
  }

  location ~ ^/webmention(.*)$ {
    try_files $uri @backend;
  }

  location ~ ^/rss(.*)$ {
    try_files $uri @backend;
  }

  location /sitemap.xml {
    try_files $uri @backend;
  }

  location ~ ^/static/(.*)$ {
    root      /app/backend/;
    try_files $uri @backend;

    autoindex on;
  }

  location ~ ^/uploads/(.*)$ {
    root      /app/backend/;
    try_files $uri @backend;
  }

  location /(500|502|503|504) {
    try_files $uri @backend;
  }

  # Error handling
  error_page 404 /404;
  error_page 500 502 503 504 /500;
}

Связанный контент