null

Проксирование веб-интерфейса OpenNebula Sunstone через nginx

Веб-интерфейс OpenNebula'ы - Sunstone не имеет поддержки SSL из коробки, что требует использования реверс-проксирующего веб-сервера. В данной статье рассмотрим конфигурацию nginx для достижения максимальной скорости загрузки файлов и починим неработающую веб-консоль.

Взяв сперва простейший конфиг реверс-прокси nginx можно столкнуться с тем, что загрузка образов дисков через Sunstone либо становится очень медленной, либо прерывается после первых нескольких процентов. Это происходит из-за того, что для загрузки файлов используется механизм Chunked transfer encoding, представленный в HTTP/1.1, который не терпит буферизации, но таки буферизируется nginx'ом, потому что тот по умолчанию подключается к backend'у используя HTTP/1.0.

Для исправления этой проблемы нужно заставить nginx использовать HTTP/1.1 для подключения к проксируемому серверу и отключить буферизацию запросов и ответов:

        proxy_request_buffering off;
        proxy_buffering         off;
        proxy_http_version      1.1;

Также, для возможности загрузки больших файлов, следует увеличить значения таймаута для отправки и получения данных от бэкэнда, которые по умолчанию составляют 60 секунд, а также максимальный размер передаваемых от клиента данных.

                client_max_body_size    8192M
                proxy_read_timeout      3600s;
                proxy_send_timeout      3600s;

Следующая проблема, с которой придётся столкнуться: неработающая веб-консоль виртуальных машин (VNC). Она связана с механизмом защиты от XSS-атак. Сервер, запрещающий обращения к себе с других сайтов, проверяет в поступающих HTTP-запросах совпадение доменного имени из Host с Origin.

Nginx при проксировании подставляет в заголовок Host домен (или IP-адрес) из proxy_pass. Заголовок Origin отправляется браузером и не модифицируется nginx'ом при проксировании. Это приводит к срабатыванию защиты XSS, встроенной в Sunstone.

HTTP-заголовки, отправляемые браузером:

Host: cloud-provider.tld

HTTP-заголовки, доходящие до Sunstone:

Host: 127.0.0.1:9869

Почему это случается только с VNC и не затрагивает другие запросы к Sunstone? Заголовок Origin подставляется только к так называемым CORS-запросам, т.е. отправляемым на другие Origin'ы. Графическая консоль Sunstone располагается на отдельном порту и подключения к ней попадают под это понятие и дополняются заголовком Origin:

Host: cloud-provider.tld:29876
Origin: https://cloud-provider.tld

Так как Nginx не проксирует подключения к VNC, до Sunstone доходят запросы с разными значениями Host и Origin: 127.0.0.1 и cloud-provider.tld.

Поправить это можно, заставив nginx сохранять оригинальное значение заголовка Host из запроса клиента:

proxy_set_header        Host    $http_host;

Конфигурационный файл nginx со всеми указанными исправлениями:

server {
        listen                  80 default_server;
        server_name             cloud-provider.tld;

        location / {
                return          301 https://$server_name:443;
        }
}

server {
        listen                  443 ssl default_server;
        server_name             cloud-provider.tld;

        ssl_certificate         /etc/ssl/certs/cloud-provider.tld.crt;
        ssl_certificate_key     /etc/ssl/certs/cloud-provider.tld.key;

        client_max_body_size    8192M;
        proxy_request_buffering off;
        proxy_buffering         off;
        proxy_http_version      1.1;

        location / {
                proxy_pass              http://127.0.0.1:9869;
                proxy_read_timeout      3600s;
                proxy_send_timeout      3600s;
                proxy_set_header        Host    $http_host;
        }
}