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

Nginx обслуживает контент с неправильного «виртуального хоста» при доступе по https

У меня есть сервер, на котором запущены как Nginx, так и Apache в настройке прокси, Nginx обслуживает статический контент, а Apache - динамический контент, который работает очень хорошо.

В этой конфигурации в настоящее время размещены две версии одного и того же сайта, давайте назовем их production.com и staging.com.

Я только что закончил настройку сайта production.com с использованием SSL, который также работает очень хорошо, но обнаружил, что если бы я перешел на staging.com также с использованием SSL, я бы получил содержимое корневого веб-сайта production.com. , что явно неверно.

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

Прямо сейчас у меня есть эта конфигурация, включенная в nginx.conf

default_80.conf
server {
    listen 80;
    server_name "";
    return 444;
}
default_443.conf
server {
    listen 443 default_server ssl;
    server_name "";
    return 444;
}
staging.com.conf
server {

    listen 80;
    server_name staging.com;
    access_log /var/log/nginx/staging.com.log;

    # static content folders
    location ^~ /(images|css|js) {
            root /var/www/staging.com/current;
            access_log /var/log/nginx/staging.com.static.log;
    }

    # static content files
    location ~* \.(js|css|rdf|xml|ico|txt|jpg|gif|png|jpeg)$ {
            root /var/www/staging.com/current;
            access_log /var/log/nginx/staging.com.static.log;
    }

    # proxy the rest to apache
    location / {

        proxy_pass         http://127.0.0.1:8080/;
        proxy_redirect     off;

        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;

        proxy_buffer_size          4k;
        proxy_buffers              4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    }
}
production.com.conf
server {

    listen 80;
    server_name production.com;
    rewrite ^       https://$server_name$request_uri? permanent;
}

server {

    listen 443 ssl;
    server_name production.com;
    access_log /var/log/nginx/production.com.log;

    ssl_certificate /etc/httpd/conf.d/SSL/ev.crt;
    ssl_certificate_key /etc/httpd/conf.d/SSL/server.key;
    keepalive_timeout 60;

    # static content folders
    location ^~ /(images|css|js) {
            root /var/www/production.com/current;
            access_log /var/log/nginx/production.com.static.log;
    }

    # static content files
    location ~* \.(js|css|rdf|xml|ico|txt|jpg|gif|png|jpeg)$ {
            root /var/www/production.com/current;
            access_log /var/log/nginx/production.com.static.log;
    }

    # proxy the rest to apache
    location / {

        # proxy settings
        proxy_pass         http://127.0.0.1:8080/;
        proxy_redirect     off;

        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;

        proxy_buffer_size          4k;
        proxy_buffers              4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    }

}

Эти настройки уничтожают все виды SSL-доступа к любому из двух сайтов, и если я удалю директиву default_server из default_443.conf, она будет работать для обоих сайтов.

Итак, вопрос в том, как отключить SSL-доступ (https://staging.com возвращает 444) для staging.com и включает его на production.com?

С уважением, Ларс

Во-первых, убедитесь, что ваша версия Nginx поддерживает SNI, если вы используете один из этих странных дистрибутивов (вы должны увидеть, что поддержка TLS SNI включена вверху):

nginx -V

Я разместил настройку ниже, вот результаты на моем ящике (/var/www/production/index.html содержит PRODUCTION и /var/www/staging/index.html, STAGING)

http://192.168.56.101 сброс подключения (444)
https://192.168.56.101 сброс подключения (444)
http://staging.example.com СТАДИЯ
https://staging.example.com перенаправление на http
http://production.example.com перенаправление на https
https://production.example.com ПРОИЗВОДСТВО

Для справки, я использовал стабильную версию nginx из репозиториев debian (0.7.67), но у меня очень похожая установка на 1.0. Что-то работает почти так же. Если вы не можете заставить его работать, сообщите нам свою точную версию.

В вашем случае вы, вероятно, захотите изменить оба значения по умолчанию на default_server. Вы также можете сделать перезапись постоянной и, возможно, изменить ее на return 301, если ваша версия nginx это позволяет.


/ и т.д. / nginx / сайты-включен / по умолчанию

server {
    listen 80 default;
    return 444;
}

server {
    listen 443 default;
    ssl on;
    ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
    return 444;
}

/ и т. д. / nginx / сайты с поддержкой / производство

server {
    listen   80; ## listen for ipv4
    server_name production.example.com;
    rewrite ^ https://production.example.com$request_uri?;
}

server {
    listen  443;
    server_name production.example.com;
    ssl on;
    ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
    keepalive_timeout 60;

    location / {
            proxy_pass      http://127.0.0.1:81;
            proxy_set_header        Host    $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

/ и т.д. / nginx / сайты с поддержкой / постановка

server {
    listen  80;
    server_name staging.example.com;
    keepalive_timeout 60;

    location / {
            proxy_pass      http://127.0.0.1:81;
            proxy_set_header        Host    $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

server {
    listen   443; ## listen for ipv4
    server_name staging.example.com;
    ssl on;
    ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
    keepalive_timeout 60;

    rewrite ^(.*) http://staging.example.com$1;
}

/ и т.д. / apache2 / сайты с поддержкой / производство

<VirtualHost *:81>
    ServerAdmin webmaster@localhost
    ServerAlias production.example.com

    DocumentRoot /var/www/production
    <Directory />
            Options FollowSymLinks
            AllowOverride None
    </Directory>
    <Directory /var/www/production>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride None
            Order allow,deny
            allow from all
    </Directory>

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
            AllowOverride None
            Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
            Order allow,deny
            Allow from all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

/ и т.д. / apache2 / сайты с поддержкой / постановка

<VirtualHost *:81>
    ServerAdmin webmaster@localhost
    ServerAlias staging.example.com

    DocumentRoot /var/www/staging
    <Directory />
            Options FollowSymLinks
            AllowOverride None
    </Directory>
    <Directory /var/www/staging>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride None
            Order allow,deny
            allow from all
    </Directory>

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
            AllowOverride None
            Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
            Order allow,deny
            Allow from all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

/etc/apache2/ports.conf

NameVirtualHost *:81
Listen 81

Я (с помощью 3molo на IRC) решил это, добавив серверный блок с использованием ssl для staging.com с переписью на HTTP, что, на мой взгляд, является одобренным обходным путем.

server {
    listen 443 ssl;
    server_name staging.com;

    ssl_certificate /etc/httpd/conf.d/SSL/ev.crt;
    ssl_certificate_key /etc/httpd/conf.d/SSL/server.key;
    keepalive_timeout 60;

    rewrite ^       http://$server_name$request_uri? permanent;
}

Но проблема все еще остается, почему Nginx обслуживает контент, когда $ http_host и server_name не совпадают? Если у кого-то есть ответ на этот вопрос, я с радостью его выслушаю.

Если staging.com и production.com указывают на одни и те же IP-адреса, это не зависит от вас, поскольку SSL согласовывается до отправки заголовка Host клиентом.

Если возможно, используйте один IP-адрес для каждого сайта, а если нет, вы можете, однако, иметь возможность «if $ host = staging.com ..» в контексте сервера для production.com.