nginx как обратный прокси с восходящим SSL

18

Я создаю прокси для внутреннего API, чтобы клиенты могли подключаться без необходимости устанавливать самозаверяющие сертификаты.

Клиенты (созданные, принадлежащие и используемые только для внутреннего использования) будут подключаться по протоколу SSL к блоку nginx, где я использую XSendfile для проверки учетных данных на уровне приложения (приложение rails). Если учетные данные верны, соединение передается обратно в nginx, где он использует proxy_pass для отправки соединения на вышестоящий сервер.

Теперь это прекрасно работает для стандартных http-соединений, но я пытаюсь выяснить, как добавить наши сертификаты в соединение.

Этот вопрос почти идентичен этому , но с неудобными требованиями к сертификатам.

Это возможно даже с nginx? Есть ли лучшее решение?

Я также согласился бы на http от клиента -> nginx и самозаверяющий сертификат от nginx к API.

simonmaddox
источник

Ответы:

19

Для любого, кто сталкивается с этим вопросом и хочет использовать nginx, вы можете настроить его, как любой обычный прокси-сервер, и для принятия самозаверяющего сертификата из бэкэнда вам необходимо предоставить экспортированный сертификат pem (и, возможно, ключ) и установить проверку ssl. выкл. Например:

...

server {
    listen       10.1.2.3:80;
    server_name  10.1.2.3 myproxy.mycompany.com;

    location / {
         proxy_pass                    https://backend.server.ip/;
         proxy_ssl_trusted_certificate /etc/nginx/sslcerts/backend.server.pem;
         proxy_ssl_verify              off;

         ... other proxy settings
    }

Если ваш защищенный сервер использует SNI идентификации имени сервера с несколькими хостами, обслуживаемыми на одну пару IP / порт, вам также может потребоваться включить proxy_ssl_server_name on;эту конфигурацию. Это работает на nginx 1.7.0 и выше.

пользователь shonky linux
источник
1
proxy_ssl_server_name on;это было все, что мне нужно, чтобы это работало при проксировании трафика на хосте в Google App Engine с использованием встроенного SSL, управляемого Google! (Это не самоподписанный сертификат или что-то в этом роде, поэтому ему просто нужна была одна строка). Спасибо за отличный совет.
XP84
Я получаю 'ssl_certificate' не определено для директивы listen ... ssl ', если я не использую ssl_certificate. Можно ли использовать SSL через прокси-сервер без предоставления вышестоящего сертификата?
Дэмьен
Комментарий не по теме, так как речь идет о прокси http, подключающемся к восходящему https. Если вы хотите прокси HTTPS, то, вероятно, лучше рассмотреть его как отдельный вопрос. Быстрый и краткий ответ: No Nginx не может «прослушивать» порт https без сертификата и закрытого ключа.
пользователь shonky linux
5

Я думаю, что вы, вероятно, хотите что-то вроде этого (очевидно, упрощенно для этого примера):

worker_processes  1;
events {
    worker_connections  1024;
}

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

    sendfile        on;
    keepalive_timeout  65;

    upstream backend {
        server mybackendserver:443;
    }

    server {
        server_name localhost;
        listen 443 ssl;
        ssl_certificate /etc/nginx/server.crt;
        ssl_certificate_key /etc/nginx/server.key;
        ssl_verify_client off;
        location / {
            proxy_pass  https://backend;
            proxy_set_header Host $http_host;
            proxy_set_header X_FORWARDED_PROTO https;
        }
    }
}

Единственное, что вам, возможно, придется изменить, это сделать «Host» явным - если, например, ваше имя проксируемого хоста не совпадает с именем хоста, используемым на прокси-сервере nginx.

Варенье
источник
Насколько я понимаю, параметры ssl_certificate и ssl_certificate_key относятся к клиентскому соединению, а не к восходящему соединению. Это тот случай?
simonmaddox
1
Из того, что я понимаю, да. В этом примере клиент видит сертификат, предоставленный nginx. nginx видит (и проверяет? Я не уверен ...) тот, который предоставлен сервером, но не передает его клиенту.
Jam
3

Для тех, кто сталкивается с этим в будущем, я не использовал nginx для этого.

Вместо этого я использовал stunnel в «режиме клиента». Очень прост в настройке и делает именно то, что мне нужно.

simonmaddox
источник