LINUX.ORG.RU

nginx: переменная в ssl_certificate

 ,


1

1

Хочу в конфиге сделать что-то вроде такого:

server{
	server_name ^.*?\.(?<basename>.*?);
	...
	ssl_certificate /path/to/cert/$basename/cert.pem
}

Это позволило бы в одном месте конфига указать сертификаты сразу для нескольких доменов. В итоге переменная не применяется (хотя она точно непустая - проверял путём добавления её значения в заголовок ответа) - в логе сообщение о том, что по пути «/path/to/cert//cert.pem» сертификат не найден.

Версия nginx 1.21, версия модуля openssl 1.0.2k (built with OpenSSL 1.0.2k-fips 26 Jan 2017). Вроде переменные должны в этом месте поддерживаться с nginx 1.15.9 (у меня явно новее). И с версии openssl 1.0.2. Я как-то не так понимаю использование переменных в пути к сертификату?



Последнее исправление: Novascriptum (всего исправлений: 2)

Конфиг читается до обращения клиента.

Имя из сертификата можно узнать только прочитав сертификат.

2 варианта:

- делай SNI сертификат на все имена и используй дефолтный server.

- генерация конфигов и их включение через include «ssl.d/*.conf» IMHO самое разумное решение. если все остальные директивы в server общие, то их можно добавлять через include.

vel ★★★★★
()
Ответ на: комментарий от vel

Имя из сертификата можно узнать только прочитав сертификат

Зачем нужно узнавать имя из сертификата ?
nginx отдаёт клиенту любой сертификат, который указан в соответствующем vhost-е (директива server {...}), вне зависимости от имён в сертификате.

spirit ★★★★★
()
Последнее исправление: spirit (всего исправлений: 1)

Я как-то не так понимаю использование переменных в пути к сертификату?

Судя по всему nginx не сразу выставляет значение всех переменных, когда нам кажется, что должен бы. В момент работы модуля ssl, он выставляет свой набор переменных. Именно поэтому в примерах из документации nginx используется $ssl_server_name. Ваша $basename на этот момент ещё пустая, поэтому магия не случается. Победить ситуацию можно с помощью директивы map. Такой вариант проверил у себя - 100% рабочий:

map $ssl_server_name $basename {
    default          default;
    ~^.*\.(.*)$      $1;
}

server {
    listen 443 ssl;

    # server_name ...;

    ssl_certificate     ssl/test/$basename-cert.pem;
    ssl_certificate_key ssl/test/$basename-key.pem;
}

Для теста сгенерировал 3 пары cert/key - default, test1 и test2. Важно: сертификаты/ключи должны иметь права, позволяющие их читать пользователю, из-под которого работают worker-ы nginx. Проверка:

$ for domain in domain-without-dot test1 test2 aa.test1 x.y.z.test2; do echo -ne "$domain\t"; openssl s_client -connect 127.0.0.1:443 -servername $domain < /dev/null 2> /dev/null | openssl x509 -subject -noout; done | column -t

domain-without-dot  subject=CN  =  default
test1               subject=CN  =  default
test2               subject=CN  =  default
aa.test1            subject=CN  =  test1
x.y.z.test2         subject=CN  =  test2

P.S.

  1. У вас в server_name ~ перед regexp-ом не хватает.
  2. Версия OpenSSL, c которой был собран nginx, ещё не означает, что он работает с такой. Не помешает проверить версию самой библиотеки openssl - openssl version
spirit ★★★★★
()
Последнее исправление: spirit (всего исправлений: 1)
Ответ на: комментарий от spirit

«map $ssl_server_name $basename» действительно работает! Спасибо тебе, добрый человек!

Novascriptum
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.