Мне было интересно, может ли 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.
Согласно статье в Википедии о кодах состояния, Nginx имеет собственный код ошибки, когда HTTP-трафик отправляется на порт https (код ошибки 497)
И согласно документации nginx на error_page , вы можете определить URI, который будет отображаться для конкретной ошибки.
Таким образом, мы можем создать uri, на который будут отправляться клиенты при возникновении кода ошибки 497.
#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 прослушивали один и тот же порт
Это, наконец, стало возможным делать правильно, начиная с версии 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), а затем прокси передает его на правильный порт сервера локально.