Прокси-сервер Nginx для фоновой работы с аутентификацией SSL-сертификата клиента

14

У меня есть два сервера, оба имеют nginx. Сервер A прослушивает 443 и настроен для аутентификации с помощью SSL-сертификата клиента.

Сервер B имеет внутренний процесс, который должен взаимодействовать с сервером A через nginx.

Я хотел бы настроить Nginx на сервере B, который будет прослушивать 8080 (без шифрования, поскольку все это локальная связь) и proxy_pass для ServerA: 443.

Вопрос в том, как ввести сертификат клиента? Я не нашел ни одной функции proxy_xxxx, которая бы это делала.

Я знаю, как сделать аналог с socat, но мое требование - использовать nginx.

Bastien974
источник
2
Глядя на директивы в прокси-модуле nginx, кажется, что невозможно заставить сервер nginx использовать сертификат для аутентификации: nginx.org/en/docs/http/ngx_http_proxy_module.html Apache поддерживает эту функцию.
NuTTyX
Вот чего я боялся ... есть идеи, есть ли какой-нибудь пользовательский модуль или что-то такое, что может сделать эту работу? Такая особенность должна существовать!
Bastien974
Я нашел утилиту для переноса файлов конфигурации из apache в nginx ( github.com/nhnc-nginx/apache2nginx ), поэтому я скачал его, создал фиктивный apache.conf и передал его через инструмент, но у меня получился такой результат :### Section 2: Unconverted directives ### # Flag Description # [S] Unsupported directives. # In conf file: dummy.conf # Line 32: SSLProxyMachineCertificateFile /path/to/cert (mod_ssl.c) # [S] SSLProxyMachineCertificateFile: No relevant directive in Nginx.
NuTTyX

Ответы:

21

Достаточно ли пройти через детали сертификата клиента?

Можете добавить

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

к вашей конфигурации, а затем информация о сертификате доступна для сервера B через заголовок X-SSL-Cert.

jwilkins
источник
1
Как отмечалось здесь , знайте, может ли ваш бэкэнд заменить \tна \nэтот заголовок после прочтения.
lucasvc
3
Согласно документации nginx , $ssl_client_certпеременная устарела; $ssl_client_escaped_certпеременная должна использоваться вместо этого.
Дюбек
1
@dubek хороший улов, я бы обновил ответ прямо в таких случаях.
Крис Стрычински
Я пробовал это решение, но кажется, что оно проходит проверку, только если проверка сертификата включена. Я не хочу включать его, есть ли способ заставить его работать без установки проверки?
Юхако
5

По-видимому, это то, что вы ищете: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate Доступно с версии 1.7.8.

location / {
    ...
    proxy_pass     the_other_nginx;
    proxy_ssl_certificate  the_certificate.pem;
    ...
}
Николас Мальбран
источник
1
Это не верно. Это назначает сертификат клиента для прокси, который будет использоваться для запросов к бэкэнду. Но спросил, сказал, что это сообщение не зашифровано только локально, поэтому нет проверки сертификата клиента. Ответ jwilkins работает хорошо.
Кеньякорн Кецомбут
@KenyakornKetsombut Я полагаю, вы неправильно поняли вопрос. Сервер B не имеет шифрования (прослушивание на 8080), но должен связаться с сервером A (прослушивание на 443, с шифрованием). Поэтому B необходимо отправить клиентский сертификат A для аутентификации. Вы можете использовать proxy_ssl_certificate для достижения этой цели. jwilkins ответит, передаст A сертификат, данный B. Эти оба могут работать в зависимости от того, что вам нужно.
Николя Мальбран
Привет, Николас. Я пытался сказать: если Сервер B не использует шифрование (на порту 8080), он не использует ничего, например HTTPS / SSL, или как вы его называете. Клиентские сертификаты являются частью SSL, поэтому эта часть не может быть выполнена сервером B. B не может отправлять или получать какие-либо клиентские сертификаты.
Кеньякорн Кецомбут
1
Я получаю nginx: [emerg] не определено "proxy_ssl_certificate_key" для сертификата "certs / Roro_Client.pem" nginx: сбой теста файла конфигурации /etc/nginx/nginx.conf при попытке выполнить это с 1.8.0
Вольфганг Фал
4

Проблема, по-видимому, в значительной степени зависит от версии. В Ubuntu 14.04 LTS по умолчанию nginx является устаревшим 1.4. Сначала вам нужно установить версию на основе PPA

https://leftshift.io/upgrading-nginx-to-the-latest-version-on-ubuntu-servers

показывает, как это сделать с помощью:

sudo add-apt-repository ppa:nginx/stable
sudo aptitude safe-upgrade

вы должны в конечном итоге:

nginx -v
nginx version: nginx/1.8.0

Конфигурация из ответа @ xatr0z https://serverfault.com/a/636455/162693, указывающая на http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate , не работает:

нерабочее предложение

backend {
    server some-ip:443;
}

server {
    listen 80;


    location / {
        proxy_ssl_certificate        certs/client.crt;
        proxy_ssl_certificate_key    certs/client.key;


        proxy_pass https://backend;
    }
}

не работает из коробки с 1.8.0. Это, вероятно, подразумевается только как подсказка и не должен использоваться как файл конфигурации как таковой или зависит от другой версии.

Я тестирую сервер A, работающий на основе Apache2, с включенными SSL и самозаверяющими клиентскими сертификатами. Параметры SSL конфигурации Apache установлены на:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

Это облегчает отладку ситуации, так как сценарий phpinfo () на стороне сервера покажет информацию о стороне сервера и клиента.

Чтобы проверить это, я использовал:

https: // бэкенд / тест / phpinfo

с сертификатом SSL, установленным в браузере, и я получаю такие разделы, как: SSL_SERVER_S_DN_CN для сертификата сервера и SSL_CLIENT_S_DN_CN для сертификата клиента.

Для начала я использовал (заполните части в скобках) для настройки nginx на внешнем сервере B:

server {
  listen 8080;
  server_name <frontend>;

  location / {
    proxy_buffering off;
    proxy_pass https://<backend>;
    #proxy_ssl_certificate      certs/<SSL Client Certificate>.crt;
    #proxy_ssl_certificate_key  certs/<SSL Client Certificate>.key;
  }
}

откомментируйте конкретную часть SSL-сертификата клиента только для проверки работы самого обратного прокси-сервера.

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
service nginx restart
nginx stop/waiting
nginx start/running, process 8931

Теперь http: // frontend: 8080 / test / phpinfo.php работает

SSL_SERVER_S_DN_CN для сертификата сервера отображается, а SSL_CLIENT_S_DN_CN для сертификата клиента (пока) не отображается

Теперь после комментирования:

server {
  listen 8080;
  server_name <frontend>;

  location / {
    proxy_buffering off;
    proxy_pass https://<backend>;
    proxy_ssl_certificate      certs/<SSL Client Certificate>.crt;
    proxy_ssl_certificate_key  certs/<SSL Client Certificate>.key;
  }
}

и проверка / перезапуск

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
service nginx restart
nginx stop/waiting
nginx start/running, process 8931

http: // frontend: 8080 / test / phpinfo.php работает и

SSL_SERVER_S_DN_CN для сертификата сервера отображается и SSL_CLIENT_S_DN_CN для сертификата клиента отображается

так что теперь у нас все работает так, как просили.

Обратите внимание на ошибку https://trac.nginx.org/nginx/ticket/872#ticket

Вольфганг Фаль
источник
Возможно, вы захотите остерегаться вопроса пересмотра ruby-forum.com/topic/6875137, который может испортить шоу
Вольфганг Фаль
1

Есть довольно аккуратная статья о клиентских сертификатах nginx и SSL; он использует PHP с FastCGI в качестве примера, но я думаю, вы можете адаптировать его к настройке обратного прокси:

server {
    listen        443;
    ssl on;
    server_name example.com;

    ssl_certificate      /etc/nginx/certs/server.crt;
    ssl_certificate_key  /etc/nginx/certs/server.key;
    ssl_client_certificate /etc/nginx/certs/ca.crt;
    ssl_verify_client optional;

    location / {
        root           /var/www/example.com/html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME /var/www/example.com/lib/Request.class.php;
        fastcgi_param  VERIFIED $ssl_client_verify;
        fastcgi_param  DN $ssl_client_s_dn;
        include        fastcgi_params;
    }
}

Источник http://nategood.com/client-side-certificate-authentication-in-ngi

Эрик Каплун
источник