Nginx принудительно устанавливает порт 8080 на использовать SSL и переписать или перенаправить http на https [дубликат]

Мне было интересно, может ли nginx обрабатывать запросы http и https на одном и том же порте . [*]

Это то, что я пытаюсь сделать. Я запускаю веб-сервер (lighttpd), обрабатывающий HTTP-запросы, и программу C, которая обслуживает определенный раздел дерева документов через https. Эти два процесса работают на одном сервере.

На уровне брандмауэра i может иметь только один порт, перенаправляющий трафик на этот сервер . Итак, что я хотел бы сделать, так это настроить nginx на этом сервере, чтобы он слушал запросы на одном порту, а затем:

A) перенаправлял все http://myhost.com/ * запросы, чтобы они переходили на localhost: 8080 (где lighttpd слушает)

B) если пользователь запрашивает URL-адрес, начинающийся, например, с https: // myhost.com/app, он отправляет этот запрос на localhost: 8008 (программа C). Обратите внимание, что в этом случае трафик между удаленным браузером и nginx должен быть зашифрован.

Как вы думаете, такое возможно? Если да, то как это можно сделать?

Я знаю, как это сделать, используя два разных порта. Проблема, с которой я сталкиваюсь, заключается в том, чтобы сделать это только с одним портом (к сожалению, у меня нет контроля над конфигурацией брандмауэра в этой конкретной среде, так что это ограничение, которого я не могу избежать). Использование таких методов, как обратный переход портов через ssh для обхода брандмауэра, также не сработает, потому что это должно работать для удаленных пользователей, у которых нет ничего, кроме веб-браузера и интернет-ссылки.

Если это выходит за рамки возможностей nginx, знаете ли вы какой-либо другой продукт, который мог бы удовлетворить этим требованиям? (до сих пор мне не удавалось установить это с помощью lighttpd и pound). Я также предпочел бы избегать Apache (хотя я готов использовать его, если это единственно возможный выбор).

Заранее спасибо, Алекс

[*] Для ясности, я говорю об обработке зашифрованных и ] незашифрованные HTTP-соединения через тот же порт.Не имеет значения, выполняется ли шифрование через SSL или TLS.

19
задан 30 July 2009 в 08:21
2 ответа

Согласно статье в Википедии о кодах состояния, Nginx имеет собственный код ошибки, когда HTTP-трафик отправляется на порт https (код ошибки 497)

И согласно документации nginx на error_page , вы можете определить URI, который будет отображаться для конкретной ошибки.
Таким образом, мы можем создать uri, на который будут отправляться клиенты при возникновении кода ошибки 497.

nginx.conf

#lets assume your IP address is 89.89.89.89 and also that you want nginx to listen on port 7000 and your app is running on port 3000

server {
    listen 7000 ssl;
 
    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
        proxy_pass http://89.89.89.89:3000/;

        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Protocol $scheme;
    }
}

Однако, если клиент делает запрос любым другим методом, кроме GET, этот запрос будет преобразован в ПОЛУЧИТЬ. Таким образом, чтобы сохранить метод запроса, через который пришел клиент; мы используем перенаправление обработки ошибок, как показано в документации nginx на error_page

И поэтому мы используем перенаправление 301 = 307 .

Используя показанный здесь файл nginx.conf, мы можем чтобы http и https прослушивали один и тот же порт

20
ответ дан 4 January 2021 в 10:07

Это, наконец, стало возможным делать правильно, начиная с версии 1.15.2. См. Информацию здесь .

Добавьте в nginx.conf такой блок (вне блока http):

stream {
    upstream http {
        server localhost:8000;
    }

    upstream https {
        server localhost:8001;
    }

    map $ssl_preread_protocol $upstream {
        default https;
        "" http;
    }

    server {
        listen 8080;
        listen [::]:8080;
        proxy_pass $upstream;
        ssl_preread on;
    }
}

Затем вы можете создать свой обычный блок сервера, но прослушивая эти разные порты:

server {
    listen 8000;
    listen [::]:8000;
    listen 8001 ssl;
    listen [::]:8001 ssl;
...

Таким образом, блок потока может предварительно прочитать и определить, является ли он TLS или нет (в этом примере на порт 8080), а затем прокси передает его на правильный порт сервера локально.

3
ответ дан 4 January 2021 в 10:07

Теги

Похожие вопросы