Назад | Перейти на главную страницу

Как обслуживать несколько сертификатов SSL для виртуального хоста по умолчанию на NGINX?

У меня есть статическое приложение на Amazon S3, которое обслуживается через прокси-сервер NGINX. Я использую прокси для того, чтобы позволить пользователям указывать свои домены на мой экземпляр Amazon EC2 (через запись CNAME, указывающую на custom-domain.myproduct.com), чтобы они могли получить доступ к моему приложению через свой собственный URL-адрес, например: myproduct.happyclient.com.

Для этого у меня есть следующая конфигурация nginx (части удалены для краткости):

http {
    server {
    # This is my default route. References:
    # http://stackoverflow.com/a/15799883/91403
    # http://nginx.org/en/docs/http/request_processing.html

    listen 80 default_server;
    server_name custom-domain.myproduct.com;
    location / {
        proxy_pass http://static.myproduct.com; # points to Amazon S3
        proxy_set_header Host myproduct.com;
    }
}

Несмотря на то, что мое статическое приложение на 100% общедоступно (без секретов клиента, только html и javascript), некоторые из моих клиентов хотят получить к нему доступ через SSL. Как я могу динамически выбирать, какой сертификат использовать для SSL-соединения на основе заголовка Host? Обратите внимание, что я не могу просто жестко указать путь к сертификату.

PS.: Клиенты смогут загружать свои сертификаты в мой экземпляр
PS2.: Эта настройка уже отлично работает только с HTTP.

Что я пробовал

Я пробовал что-то подобное, но безуспешно:

server {
    listen 443 default_server;
    server_name custom-domain.myproduct.com;
    ssl on;
    ssl_certificate /etc/nginx/ssl/$http_host/server.crt; # note the http_host variable
    ssl_certificate_key /etc/nginx/ssl/$http_host/server.key; # also here
}

Как я могу динамически выбирать, какой сертификат использовать для SSL-соединения на основе заголовка Host?

Заголовок Host является частью протокола HTTP, но HTTPS - это HTTP, встроенный в соединение SSL. Это означает, что вам сначала нужно установить SSL-соединение (для которого нужен сертификат), прежде чем вы получите доступ к заголовку Host.

Если клиент поддерживает SNI (все современные браузеры поддерживают, но IE / XP нет), он уже отправит целевое имя внутри SSL-подтверждения. Предоставление разных сертификатов на основе целевого имени обычно выполняется с разными разделами сервера в nginx. Вы можете попробовать использовать $ssl_server_name в разделе по умолчанию, но я не уверен, что это сработает, и даже если это сработает, это может негативно повлиять на оптимизацию, такую ​​как кеширование сеанса.