У Nginx есть конфликт с приложением, запущенным на 443

#nginx #port

Вопрос:

В macOS я обычно запускаю свой проект на локальном sudo PORT=443 HTTPS=true ./node_modules/.bin/react-scripts start хостинге . В результате https://localhost/#/start работает в браузере.

Теперь, чтобы запустить стороннюю аутентификацию в localhost, мне нужно запустить nginx. Вот мой /usr/local/etc/nginx/nginx.conf :

 worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    upstream funfun {
        server 178.62.87.72:443;
    }

    server {
        listen              443 ssl;
        server_name localhost;
        ssl_certificate /etc/ssl/localhost/localhost.crt;
        ssl_certificate_key /etc/ssl/localhost/localhost.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_session_timeout 1d;
        ssl_stapling off;
        ssl_stapling_verify off;
        add_header Strict-Transport-Security max-age=15768000;
        add_header X-Frame-Options "";
        proxy_ssl_name "www.funfun.io";
        proxy_ssl_server_name on;

        location ~ /socialLoginSuccess {
            rewrite ^ '/#/socialLoginSuccess' redirect;
        }

        location ~ /auth/(.*) {
            proxy_pass  https://funfun/10studio/auth/$1?$query_string;
            proxy_set_header Host localhost;
        }

        location / {
            proxy_set_header    Host                $host;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto   $scheme;
            proxy_set_header    Accept-Encoding     "";
            proxy_set_header    Proxy               "";
            proxy_pass          https://localhost/;
            # These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove socketio error
            proxy_http_version 1.1;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "upgrade";
        }
    }
    include servers/*;
}
 

Однако запуск nginx возвращает мне следующие ошибки:

 $ sudo nginx
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] still could not bind()
 

Похоже, что nginx столкнулся с приложением, работающим на 443. Кто-нибудь знает, почему?

Кроме того, может ли кто-нибудь сказать мне, какова цель блока location / { ... } в моем файле конфигурации nginx?

Ответ №1:

Только одно приложение может одновременно привязывать/прослушивать данный порт.

Вы запустили приложение, работающее на порту 443: sudo PORT=443 HTTPS=true ./node_modules/.bin/react-scripts start

Затем, когда вы попытались запустить nginx также на порту 443, это не удалось, потому что ваше приложение уже использует 443.

Чтобы исправить это:

  • остановите nginx
  • остановите свое приложение и перезапустите его, запустив на другом порту (например 3000 ):
    • sudo PORT=3000 HTTPS=true ./node_modules/.bin/react-scripts start
  • отредактируйте свою конфигурацию nginx, чтобы сообщить nginx, что ваше приложение («вверх по течению») теперь работает на порту 3000.
    • proxy_pass https://localhost:3000;
  • запустите nginx

Кроме того, я бы посоветовал вам завершить работу по протоколу SSL (https) в nginx и разрешить nginx небезопасно подключаться к вашему приложению на локальном хосте, чтобы уменьшить другие проблемы. В настоящее время похоже, что вы выполняете завершение ssl в nginx, а затем еще одно соединение/завершение ssl с вашим приложением/восходящим потоком. В этом действительно нет необходимости при подключении на локальном хосте или по защищенной/частной сети (например, в AWS VPC).

  • остановите nginx
  • остановите свое приложение и перезапустите его, запустив на другом порту (например 3000 ):
    • удалить HTTPS=true из sudo PORT=3000 HTTPS=true ./node_modules/.bin/react-scripts start
    • …и любые другие изменения, необходимые в вашем приложении react, чтобы отключить ssl/https.
  • отредактируйте конфигурацию nginx, чтобы сообщить nginx, что ваше приложение («вверх по течению») сейчас работает на порту 3000 и небезопасно (измените https на http).
    • proxy_pass http://localhost:3000;
  • запустите nginx

Для производства вы действительно должны всегда запускать nginx перед своими приложениями. Это позволяет легко выполнять завершение ssl, балансировку нагрузки (несколько приложений/потоков), а также обслуживание статических файлов (jpg, css и т.д.) Без запуска через nodejs или другой сервер приложений. Он будет масштабироваться лучше. Правильный инструмент для правильной работы.

Для целей местного развития вы можете просто работать против локальной небезопасности http://localhost:3000. Если вы по какой-то причине действительно не любите использовать порт 3000, то, конечно, вы можете изменить это, используя NODE_ENV в тандеме с dotenv или что-то подобное, чтобы переключить порт, используемый вашим приложением в режиме разработки и производства. На самом деле нет никакой причины, по которой вам нужно использовать https/443 на локальном хосте во время разработки. Вы не сможете получить надежный сертификат SSL для локального хоста, поэтому его действительно нет point…it просто усложняет твою жизнь.

У меня нет проблем с тестированием потоков входа в систему oauth http://localhost:3000 например, с помощью Google.

Комментарии:

1. Может ли кто — нибудь сказать мне, какова цель блока location / { ... } в моем файле конфигурации nginx? Удаление этого, похоже, не повлияло на мои тесты.

2. Блоки расположения сообщают nginx, как вы хотите обрабатывать различные запросы. например, отправлять запросы в /auth в одно место и в /foobar в другом месте или с другими правилами кэширования. Наиболее конкретный (регулярное выражение или самый длинный) соответствующий блок расположения «выигрывает», но см. Приоритет . В вашем случае у вас есть два блока регулярных выражений… /auth который идет на funfun (не domain…in ваш файл hosts или?) и /success который перенаправляет. Все остальные запросы будут обрабатываться по / местоположению, которое перенаправляет ваше приложение.

3. «отредактируйте конфигурацию nginx, чтобы сообщить nginx, что ваше приложение («вверх по течению») сейчас работает на порту 3000 и небезопасно (измените https на http).» => У меня есть несколько > proxy_pass в моем файле, какой из них вы предлагаете заменить proxy_pass http://localhost:3000; ?

4. Я говорю о proxy_pass localhost том, что у вас есть только одно, которое я могу видеть. Другой proxy_pass предназначен для https://funfun/10studio/auth/... , и я не уверен, что это должно делать, так как это не локальный хост и не является реальным доменом. Вы добавили что-то в свой файл hosts или что-то для сопоставления funfun с реальным компьютером?

5. https://funfun/10studio/auth/... имеет отношение к upstream funfun { server 178.62.87.72:443; } .

Ответ №2:

Любой порт может быть привязан один раз к данному интерфейсу. Теперь, если вы запустите сервер приложений react, и он уже привязывает порт 443 к интерфейсу 0.0.0.0 , который в данном случае используется как своего рода подстановочный знак, означающий «прослушивание порта 443 на всех интерфейсах на моем компьютере», то любое другое приложение не сможет использовать этот порт, потому что он уже занят. В вашей конфигурации nginx вы можете увидеть строку, в которой говорится, что она также хочет использовать порт 443:

 server {
    listen              443 ssl;  #<--- this is port config
    server_name localhost;
 

У вас есть (по крайней мере) 2 варианта исправления этой ошибки:

  • изменение PORT=443 в локальном приложении
  • измените строку с номером порта в конфигурации nginx на любую другую, не занятую

Далее — location / { ... } означает, что все запросы, начиная с / которых фактически все запросы, кроме тех, которые были пойманы в двух предыдущих location блоках, будут перенаправлены на другой веб-сервер, расположенный по https://localhost/ адресу, с некоторыми дополнительными заголовками. Это называется обратным прокси-сервером.

Комментарии:

1. Я не хочу вносить изменения PORT=443 в свое приложение, потому что я хочу всегда запускать приложение (включая перенаправление) в разделе https://localhost/... . Я попытался вставить listen 444 ssl; файл конфигурации nginx. Nginx может быть запущен и https://localhost/#/start работает. Однако https://localhost/auth/... перенаправить его, как и раньше, не удалось; Мне пришлось использовать https://localhost:444/auth/... для этого обратный прокси-сервер.

2. Тогда да, это не сработало бы. Тем не менее ответ на ваш вопрос, почему это не работает, все еще остается в силе. Единственное, что я мог бы посоветовать, это изменить порт вашего приложения на другой, например 4433 , и изменить конфигурацию обратного прокси-сервера в nginx на proxy_pass https://localhost:4433/;