Как улучшить медленное рукопожатие TLS в обратном прокси Nginx?

Вопрос или проблема

Когда я пытаюсь подключиться к обратному прокси Nginx с помощью curl, я замечаю некоторые проблемы с задержкой во время рукопожатия TLS.

ck@mint ~ $ time curl -s https://www.example.com/up -o /dev/null  -v
*   Подключение к 192.168.100.100:443...
* Подключено к www.example.com (192.168.100.100) порт 443 (#0)
* ALPN, предлагая h2
* ALPN, предлагая http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), заголовок TLS, Статус сертификата (22):
} [5 байт данных]
* TLSv1.3 (OUT), рукопожатие TLS, Client hello (1):
} [512 байт данных]
* TLSv1.2 (IN), заголовок TLS, Статус сертификата (22):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Server hello (2):
{ [88 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Завершено (20):
} [5 байт данных]
* TLSv1.3 (OUT), изменения шифра TLS, Изменить шифровые спецификации (1):
} [1 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Статус сертификата (22):
} [5 байт данных]
* TLSv1.3 (OUT), рукопожатие TLS, Client hello (1):
} [512 байт данных]
* TLSv1.2 (IN), заголовок TLS, Завершено (20):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Статус сертификата (22):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Server hello (2):
{ [187 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Зашифрованные расширения (8):
{ [19 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Сертификат (11):
{ [2607 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Проверка сертификата (15):
{ [264 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Завершено (20):
{ [52 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.3 (OUT), рукопожатие TLS, Завершено (20):
} [52 байт данных]
* SSL соединение с использованием TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, сервер принял использование h2
* Сертификат сервера:
*  субъект: CN=www.example.com
*  дата начала: 27 авг 20:22:22 2024 GMT
*  дата истечения: 25 ноя 20:22:21 2024 GMT
*  subjectAltName: хост "www.example.com" совпал с сертификатом "www.example.com"
*  эмитент: C=US; O=Let's Encrypt; CN=R10
*  SSL сертификат успешно подтверждён.
* Используется HTTP2, сервер поддерживает мультиплексирование
* Состояние соединения изменено (HTTP/2 подтверждено)
* Копирование данных HTTP/2 из буфера потока в буфер соединения после обновления: длина=0
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* Используя ID потока: 1 (простое управление 0x607638c00cd0)
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
> GET /up HTTP/2
> Host: www.example.com
> user-agent: curl/7.81.0
> accept: */*
> 
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Новый билет сеанса (4):
{ [297 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Новый билет сеанса (4):
{ [297 байт данных]
* старый SSL идентификатор сессии устарел, удаляем
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* Состояние соединения изменено (MAX_CONCURRENT_STREAMS == 128)!
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]

< !!! рукопожатие тут приостановлено на мгновение !!! >

* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
< HTTP/2 200 
< server: nginx
< дата: Чт, 26 сен 2024 13:13:43 GMT
< content-type: text/html; charset=UTF-8
< vary: Accept-Encoding
< cache-control: private, must-revalidate
< pragma: no-cache
< expires: -1
< phpdebugbar-id: Xbeebf9bb96072f5ec137425d71d81685
< set-cookie: XSRF-TOKEN=eyJpdiI6IkxMOHpmaW1sSVRuUkJ4Vk1JZDQ5aHc9PSIsInZhbHVlIjoieXVWRzJwYzRhaklTNDRyRkNoNnRVb1BhRmJ5VHNPV1ZGRFhFWWg2VEVzRGZUUmVOWVd6QlhWTEtEaE1FTk5FWHlzS29MSkEzQVJURVFXUnVFV25WdkpKcmtPTmtKREc5QU0xaDZZam9nYUc2ZVdZSmQ3M3YwZ0puZUZ4Zy9ITDIiLCJtYWMiOiJkMWQ5NjQ5MjdkODQ4MjE2YWVlZmY0NjBkMTJlMmU2MWUwMzUzYmIwODc1MGU2ODY1NDY4NjNlYTgzNDM5YWI5IiwidGFnIjoiIn0%3D; expires=Thu, 26 Sep 2024 15:13:43 GMT; Max-Age=7200; path=/; secure; samesite=lax
< set-cookie: example_portal_session=eyJpdiI6IndUb2NWVFRxd29NelFMZUpkc3JBS1E9PSIsInZhbHVlIjoieTg4cTBkVE1WL1lmTExuZ2xyWEFDYXNSaWRWYzF2YlkzWVUrOUZwNEY1K2JqWTA4RWtvc2xPQjdjR3J2VThmMWw3Z0VzR2EwMEQ3RDYxSnBSaTJaRURTR0djNW9VUmZnV3M4Ty8yMFBQMjA5UE0rOUI3bTcvYUFWalBPZTRDSWMiLCJtYWMiOiIwYzU0YjYzMmVmYmQ1ZWM2ZDBkNTZmZjRjYjU1YzczNjU3MmM1YWIxMGNiYjc4ODA5MDZiMWVlZWFjZjJhOGFjIiwidGFnIjoiIn0%3D; expires=Thu, 26 Sep 2024 15:13:43 GMT; Max-Age=7200; path=/; httponly; samesite=lax
< vary: Accept-Encoding
< strict-transport-security: max-age=63072000
< 
{ [3134 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* Соединение #0 с узлом www.example.com осталось нетронутым

реально    0m0.989s
пользователь    0m0.046s
система 0m0.014s

Это заняло 0.989 секунд для установки соединения и получения содержимого с сайта. Я уже настроил некоторые параметры Nginx (источник) и настройку TCP (источник) на этом обратном прокси, что уже значительно улучшило скорость соединения.

Тот же сайт был настроен в другой среде (где, к сожалению, я не имею представления, как сконфигурирован обратный прокси), и тот же сайт отвечает гораздо быстрее:

ckadm@mintp ~ $ time curl -s https://www.example.com/up -o /dev/null  -v
*   Подключение к 192.168.200.200:443...
* Подключено к www.example.com (192.168.200.200) порт 443 (#0)
* ALPN, предлагая h2
* ALPN, предлагая http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), заголовок TLS, Статус сертификата (22):
} [5 байт данных]
* TLSv1.3 (OUT), рукопожатие TLS, Client hello (1):
} [512 байт данных]
* TLSv1.2 (IN), заголовок TLS, Статус сертификата (22):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Server hello (2):
{ [122 байт данных]
* TLSv1.2 (IN), заголовок TLS, Завершено (20):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Зашифрованные расширения (8):
{ [15 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Сертификат (11):
{ [2644 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Проверка сертификата (15):
{ [264 байт данных]
* TLSv1.3 (IN), рукопожатие TLS, Завершено (20):
{ [52 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Завершено (20):
} [5 байт данных]
* TLSv1.3 (OUT), изменения шифра TLS, Изменить шифровые спецификации (1):
} [1 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.3 (OUT), рукопожатие TLS, Завершено (20):
} [52 байт данных]
* SSL соединение с использованием TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, сервер принял использование h2
* Сертификат сервера:
*  субъект: CN=www.example.com
*  дата начала: 17 сен 12:52:09 2024 GMT
*  дата истечения: 16 дек 12:52:08 2024 GMT
*  subjectAltName: хост "www.example.com" совпал с сертификатом "www.example.com"
*  эмитент: C=US; O=Let's Encrypt; CN=R11
*  SSL сертификат успешно подтверждён.
* Используется HTTP2, сервер поддерживает мультиплексирование
* Состояние соединения изменено (HTTP/2 подтверждено)
* Копирование данных HTTP/2 из буфера потока в буфер соединения после обновления: длина=0
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* Используя ID потока: 1 (простое управление 0x629e73d31cd0)
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
> GET /up HTTP/2
> Host: www.example.com
> user-agent: curl/7.81.0
> accept: */*
> 
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (OUT), заголовок TLS, Дополнительные данные (23):
} [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
< HTTP/2 200 
< content-type: text/html; charset=UTF-8
< cache-control: no-cache, private
< phpdebugbar-id: Xec25fca614e7e1bca1d58f630ae2f40d
< set-cookie: XSRF-TOKEN=eyJpdiI6IlZjWnZZK3g0T2E0UDVyMldJTWxTL1E9PSIsInZhbHVlIjoieVl6L1M4T3ptT1R1aUl4cmxWM2pIdVpVek02aGEvcDNyY3dPRXl2MGR1MElPb2R1Z0lUQU9CK0VNSm5CNU5TekQyS29VTDl3WVdQMjhCRlV1U1NleFJGUWp1Um1pU1NVRjZGa1U1dVhpdkQxSlJ2ZHg1RTNBbmJQbHFvS2YrRkMiLCJtYWMiOiJkMmQ4MzBiYTVjYjRjN2FjYWVhYjE0NDNmYmI1ZDY1MTJjNDcwODNhZGRkOTRkYWU3NjA2YjQ2NzdkYWJjMzk2IiwidGFnIjoiIn0%3D; expires=Thu, 26 Sep 2024 15:21:42 GMT; Max-Age=7200; path=/; secure; samesite=lax
< set-cookie: example_portal_session=eyJpdiI6IithWEx2ZHU4RktsQjBiRTdNMEFWUmc9PSIsInZhbHVlIjoiV05FQUVOck9vQXdVd0xlbitzd0dLbkFxeHZ6V2hFQitqbTVhWGZpRlJLYzhJTDQ5a0lmbWJ6YmpZazkxQTd1NTMwVzV2K2dDYmRNaFZTWjRLSDU4Snk1Y1pLOWMxc3dDSkpmQVZad0pOcmdLdnN1bU9HYnpsS3BlNGlzbWdjb3MiLCJtYWMiOiJmMjJiNWVkOGM1NmE0OWE3MDU1MDdmOWUwZDBmYzYyNmY2Y2Y4OWU3Y2MyZmZhZDhmMTMwMjBjNTc2ZDUwNTBmIiwidGFnIjoiIn0%3D; expires=Thu, 26 Sep 2024 15:21:42 GMT; Max-Age=7200; path=/; httponly; samesite=lax; secure
< дата: Чт, 26 сен 2024 13:21:42 GMT
< alt-svc: h3=":443"; ma=2592000, h3-29=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q043=":443"; ma=2592000, quic=":443"; ma=2592000; v="43,46"
< 
{ [15408 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* TLSv1.2 (IN), заголовок TLS, Дополнительные данные (23):
{ [5 байт данных]
* Соединение #0 с узлом www.example.com осталось нетронутым

реально    0m0.517s
пользователь    0m0.041s
система 0m0.013s

Сравнение подробного вывода curl между двумя обратными прокси показывает гораздо более быстрое соединение на втором обратном прокси (и также гораздо меньше событий TLS).

У меня в основном есть вопросы по следующим пунктам:

  • Что могло привести к “паузе” во время рукопожатия, видно сразу после Состояние соединения изменено (MAX_CONCURRENT_STREAMS == 128)!?
  • Почему на моем обратном прокси происходит так много событий (IN) по сравнению со вторым обратным прокси?

Спасибо за любые подсказки!

Ответ или решение

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

1. Оптимизация параметров Nginx

  • Настройка ssl_session_cache: Убедитесь, что у вас активирован кеш сессий SSL. Это позволяет повторно использовать секреты для отдельных сессий, уменьшая время установки.

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
  • Настройка параметров ssl_prefer_server_ciphers и ssl_ciphers: Убедитесь, что используете современные и безопасные шифры для ускорения процесса. Вы можете использовать более легковесные шифры, но не забывайте о безопасности.

    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_protocols TLSv1.2 TLSv1.3;

2. Использование HTTP/2

  • Убедитесь, что поддержка HTTP/2 активирована, так как она значительно уменьшает количество необходимых обратно-прокси запросов в процессе установки соединения. Для этого важно убедиться в использовании listen с параметром http2.
    server {
        listen 443 ssl http2;
        # Другие параметры...
    }

3. Уменьшение числа TLS-событий

  • Обработка сертификатов: Проанализируйте ваше использование сертификатов. Статические сертификаты (также известные как "certificate pinning") могут уменьшить количество событий во время установки. Убедитесь, что у вас минимально возможное количество сертификатов и цепочек.

  • Обновление/Оптимизация используемого сертификата: Убедитесь, что ваши сертификаты действительны и пришли из надежных источников. Старые или ненадежные сертификаты могут увеличить время установки.

4. Параметры TCP

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

  • tcp_fastopen
  • tcp_nodelay
  • tcp_keepalive_time

5. Включение OCSP Stapling

  • Использование OCSP Stapling может уменьшить временные задержки, связанные с проверкой статуса сертификата:
    ssl_stapling on;
    ssl_stapling_verify on;

6. Изучение логов

  • Проверьте логи Nginx (error.log и access.log), чтобы исключить проблемы с подключениями (например, тайм-ауты, ошибки установки и др.). Это может дать вам дополнительное понимание о том, где происходят задержки.

7. Переключение на QUIC и HTTP/3

  • Если это применимо и поддерживается вашим окружением, рассмотрите возможность использования QUIC и HTTP/3, которые обеспечивают более быстрое и надежное соединение для постоянных клиентов.

Заключение

Подводя итоги, важно настраивать не только параметры Nginx, но и сам процесс использования TLS. Это включает в себя правильную настройку SSL, оптимизацию параметров TCP и использование современных протоколов. Постепенно проводите изменения и тестируйте их, чтобы лучше понять, какие из них оказывают наибольшее влияние на производительность. Удачи в оптимизации вашего Nginx реверс-прокси!

Оцените материал
Добавить комментарий

Капча загружается...