- PVSM.RU - https://www.pvsm.ru -

Прикручиваем к Nginx патч для динамического размера TLS records от Cloudflare

Если вы используете Nginx для терминации TLS-трафика, то можете улучшить время ответа сервера с помощью патчей от Cloudflare. Подробности под катом.

Прикручиваем к Nginx патч для динамического размера TLS records от Cloudflare - 1

TLS и TCP

Как известно, данные в Интернете передаются с использованием многослойного стека протоколов. Сейчас нас интересует взаимодействие TCP и TLS. Основная задача TCP — надёжная доставка пакетов в исходном порядке. Если у нас есть сервис, использующий TLS (HTTPS-сайт), то все зашифрованные TLS данные будут отправляться с помощью TCP.

На уровне TCP: cразу после подключения, сервер может отправить не больше, чем initcwd пакетов (для старых систем это 3 пакета, для новых — 10). Далее сервер будет ждать подтверждения (ACK) от клиента и постепенно количество пакетов в окне отправки будет расти, а соединение будет увеличивать свою пропускную способность.

В случае с обычным HTTP-трафиком все отлично: с каждым новым пакетом приходят данные, которые браузер может использовать.

Проблема c TLS

Если мы используем TLS, то Nginx использует специальный буфер (размер задаётся директивой ssl_buffer_size [1]), который управляет размером TLS record size. Браузер (клиент) может использовать данные только после получения TLS record полностью. При этом максимальный (и дефолтный в Nginx) размер ssl_buffer_size составляет 16k.

Так как начальное окно для отправки пакетов = 10, то мы можем получить примерно 14k трафика, что меньше TLS record (16k). Это может вызывать задержки в получении полезного контента.

А если вы используете HTTP/2, то стоит обратить внимание на настройку http2_chunk_size (по умолчанию 8k) — она устанавливает максимальный размер части, на которое делится тело ответа. При этом используется только одно подключение к серверу, поэтому в этом TCP соединении передаётся одновременно множество ресурсов, что увеличивает вероятность возникновения задержек.

Что можно сделать?

Самое простое, что можно сделать — уменьшить ssl_buffer_size, например до 8k или 12k. Это можно сделать в стандартной версии Nginx. Однако, при пересылке большого количества данных эффективность будет ниже (выше накладные расходы).

Получается, что идеального ssl_buffer_size не существует.

Динамический размер TLS record

Здесь на помощь приходит Cloudflare со своим набором патчей [2].

С использованием этих патчей мы получаем поддержку динамического размера TLS record.

На свежих соединениях размер записи устанавливается не больше размера одного пакета, после прохождения некоторого количества записей размер можно увеличить до 3 TCP-пакетов, а далее уже до максимального размера (16k). После простоя соединения процесс начинается снова. Все параметры этого процесса настраиваются.

Применение патчей

Чтобы получить новую функциональность, нужно применить патчи и собрать Nginx. О сборке Nginx с OpenSSL я уже писал ранее [3], поэтому остановимся на процессе применения патчей.

Для применения патчей нужно зайти на страницу github [2].

На этой странице нужно вычленить отдельные патчи для каждого файла. Запись самого патча начинается так:

diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c

Из этой записи понятно, к чему относится этот патч (в данном случае это src/event/ngx_event_openssl.c).
Копируем текст патча в файл (например, openssl.c.patch) и кладём рядом с файлом исходника.

Применяем патч следующей командой:

patch ngx_event_openssl.c < openssl.c.patch

Так проходимся по всем файлам патча (всего должно быть 4 файла).
Ну и собираем Nginx как обычно (я использовал 1.11.2, всё получилось).

Настройка Nginx

С патчем приходят новые настройки. Получаем примерно такие значения:

# Начальный размер записи, примерно 1 пакет
ssl_dyn_rec_size_lo 1369;

# Промежуточный размер записи, 3 пакета
ssl_dyn_rec_size_hi 4229;

# Количество записей для перехода к следующему размеру
ssl_dyn_rec_threshold 20;

# Время простоя для сброса размера до начального
ssl_dyn_rec_timeout 10;

# Стандартный буфер, ставим максимальное значение
ssl_buffer_size 16k;

Подробно можно почитать в исходной статье [4] блога Cloudflare.

О самом принципе оптимизации TLS record size можно почитать в книге HPBN [5].
На этом у меня всё, пока внедрили у себя, тестируем. Если у вас уже есть опыт настройки, просьба поделиться в комментариях.

Автор: Nickmob

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/nginx/160134

Ссылки в тексте:

[1] ssl_buffer_size: http://nginx.org/ru/docs/http/ngx_http_ssl_module.html#ssl_buffer_size

[2] набором патчей: https://github.com/cloudflare/sslconfig/blob/master/patches/nginx__dynamic_tls_records.patch

[3] ранее: https://habrahabr.ru/post/301452/

[4] статье: https://blog.cloudflare.com/optimizing-tls-over-tcp-to-reduce-latency/

[5] книге HPBN: https://hpbn.co/transport-layer-security-tls/#optimize-tls-record-size

[6] Источник: https://habrahabr.ru/post/306142/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best