HTTP/2 не работает на Windows Server 2019

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

Мой веб-сайт обслуживает файлы (например, изображения, js и т.д.), он не использует http/2, он обрабатывает запросы с помощью http/1.

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

  1. Использовал IIS Crypto, я установил это и отключил tls1.0 и tls1.1:
    image

  2. Отключил поддержку tls1.0 и tls1.1 в настройках Internet Explorer: https://markcz.wordpress.com/2014/10/26/full-http2-support-in-windows-10/

  3. Принудил https через web.config:

    <!-- Перенаправление HTTP на HTTPS на www -->
    <rule name="Force HTTPS on www" stopProcessing="true">
      <match url=".*" />
      <conditions>
        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
        <add input="{HTTP_HOST}" pattern="^www\.example\.com$" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />
    </rule>
    
  4. Выдал группе IIS_IUSRS права на чтение в корневом каталоге

  5. Включил анонимную аутентификацию для моего веб-сайта

  6. У меня есть https привязки для моего веб-сайта: снял отметку “Отключить HTTP/2”, отметил “Требовать указание имени сервера”, привязан к порту 443, IP-адрес установлен на “Все не назначенные”

ОБНОВЛЕНИЕ 1

  1. Попробовал h21:

    h2i www.example.com
    Подключение к www.example.com:443
    Подключено к 123.123.123.123:443
    Договорился о протоколе “h2”
    Отправка: []
    h2i> ←[5D←[K[FrameHeader SETTINGS len=18]
    h2i> ←[5D←[K [MAX_CONCURRENT_STREAMS = 100]
    h2i> ←[5D←[K [UNKNOWN_SETTING_16 = 2]
    h2i> ←[5D←[K [INITIAL_WINDOW_SIZE = 1048576]
    h2i> ←[5D←[K[FrameHeader WINDOW_UPDATE len=4]
    h2i> ←[5D←[K Window-Increment = 983041
    h2i> ←[5D←[K[FrameHeader SETTINGS flags=ACK len=0]
    h2i>

  2. IIS Application Request Routing не установлен на моем сервере

  3. Я проверил настройки SSL/TLS и совместимость сертификата с HTTP/2 через SSL Labs. Там указано “TLS 1.2 > h2”, “TLS 1.2” для современных браузеров. Только старые браузеры показывают “TLS 1.2 > http/1.1”

  4. Я не использую никакие CDN или обратные прокси

  5. Мой applicationhost.config выглядит так:

<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
    <staticTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/javascript" enabled="true" />
        <add mimeType="application/atom+xml" enabled="true" />
        <add mimeType="application/xaml+xml" enabled="true" />
        <add mimeType="image/svg+xml" enabled="true" />
    </staticTypes>
    <dynamicTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="application/javascript" enabled="true" />
    </dynamicTypes>
</httpCompression>
  1. мой web.config выглядит так:
<staticContent>
  <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" /> <!-- 365 дней -->     
</staticContent>
  1. мой www.example.com и example.com правильно привязаны в IIS
  2. “Get-ItemProperty -Path “HKLM:\System\CurrentControlSet\Services\HTTP\Parameters” -Name Http2Enabled” указывает, что Http2Enabled установлен в 1
  3. Я попробовал curl к одному из файлов с проблемой: `-I –http2 https://www.example.com/js/_myfuncs.min.js?v=1
HTTP/1.1 200 OK
Cache-Control: max-age=31536000
Content-Length: 44124
Content-Type: application/javascript
Last-Modified: Tue, 24 Sep 2024 18:29:47 GMT
Accept-Ranges: bytes
ETag: "5ec25bcafedb1:0"
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Strict-Transport-Security: max-age=63072000; includeSubDomains
Date: Sun, 29 Sep 2024 19:52:10 GMT

ОБНОВЛЕНИЕ 2

Я запустил curl -vso /dev/null --http2 https://www.example.com/js/_myfuncs.min.js?v=1

Это вывод:

* Хост www.example.com:443 был разрешен.
* IPv6: (нет)
* IPv4: 123.123.123.123
*   Пытаюсь 123.123.123.123:443...
* ALPN: curl предлагает h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Клиентское приветствие (1):
} [315 байт данных]
*  CAfile: C:\ProgramData\curl\bin\curl-ca-bundle.crt
*  CApath: нет
* TLSv1.3 (IN), TLS handshake, Серверное приветствие (2):
{ [94 байта данных]
* TLSv1.2 (IN), TLS handshake, Сертификат (11):
{ [3282 байта данных]
* TLSv1.2 (IN), TLS handshake, Обмен ключами сервера (12):
{ [493 байта данных]
* TLSv1.2 (IN), TLS handshake, Сервер завершил (14):
{ [4 байта данных]
* TLSv1.2 (OUT), TLS handshake, Обмен ключами клиента (16):
} [102 байта данных]
* TLSv1.2 (OUT), TLS изменение шифра, Изменить спецификацию шифра (1):
} [1 байт данных]
* TLSv1.2 (OUT), TLS handshake, Завершено (20):
} [16 байт данных]
* TLSv1.2 (IN), TLS изменение шифра, Изменить спецификацию шифра (1):
{ [1 байт данных]
* TLSv1.2 (IN), TLS handshake, Завершено (20):
{ [16 байт данных]
* SSL-соединение с использованием TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / [пусто] / UNDEF
* ALPN: сервер принял h2
* Сертификат сервера:
*  объект: CN=example.com
*  дата начала: 25 сентября 15:40:55 2024 GMT
*  дата окончания: 24 декабря 15:40:54 2024 GMT
*  subjectAltName: хост "www.example.com" соответствует сертификату "www.example.com"
*  издатель: C=US; O=Let's Encrypt; CN=R10
*  Проверка сертификата SSL пройдена.
*   Уровень сертификата 0: Тип публичного ключа ? (3072/128 бит/сек), подписан с использованием sha256WithRSAEncryption
*   Уровень сертификата 1: Тип публичного ключа ? (2048/112 бит/сек), подписан с использованием sha256WithRSAEncryption
*   Уровень сертификата 2: Тип публичного ключа ? (4096/128 бит/сек), подписан с использованием sha256WithRSAEncryption
* Подключено к www.example.com (123.123.123.123) порт 443
* с использованием HTTP/2
* [HTTP/2] [1] ОТКРЫТО потока для https://www.example.com/js/_myfuncs.min.js?v=1
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: www.example.com]
* [HTTP/2] [1] [:path: /js/_myfuncs.min.js?v=1]
* [HTTP/2] [1] [user-agent: curl/8.10.1]
* [HTTP/2] [1] [accept: */*]
> GET /js/_myfuncs.min.js?v=1 HTTP/2
> Хост: www.example.com
> User-Agent: curl/8.10.1
> Accept: */*
>
* Запрос полностью отправлен
* HTTP/2 поток 1 не был закрыт корректно: HTTP_1_1_REQUIRED (ошибка 13)
* Понижено до HTTP/1.1
* Пустой ответ от сервера
* Соединение #0 с хостом www.example.com осталось нетронутым
* Сделать еще один запрос к этому URL: 'https://www.example.com/js/_myfuncs.min.js?v=1'
* Хост www.example.com найден в кэше DNS
*   Пытаюсь 123.123.123.123:443...
* SSL повторно использует идентификатор сессии
* ALPN: curl предлагает http/1.1
* TLSv1.2 (OUT), TLS handshake, Клиентское приветствие (1):
} [255 байт данных]
* TLSv1.2 (IN), TLS handshake, Серверное приветствие (2):
{ [100 байт данных]
* TLSv1.2 (IN), TLS handshake, Сертификат (11):
{ [3282 байта данных]
* TLSv1.2 (IN), TLS handshake, Обмен ключами сервера (12):
{ [493 байта данных]
* TLSv1.2 (IN), TLS handshake, Сервер завершил (14):
{ [4 байта данных]
* TLSv1.2 (OUT), TLS handshake, Обмен ключами клиента (16):
} [102 байта данных]
* TLSv1.2 (OUT), TLS изменение шифра, Изменить спецификацию шифра (1):
} [1 байт данных]
* TLSv1.2 (OUT), TLS handshake, Завершено (20):
} [16 байт данных]
* TLSv1.2 (IN), TLS изменение шифра, Изменить спецификацию шифра (1):
{ [1 байт данных]
* TLSv1.2 (IN), TLS handshake, Завершено (20):
{ [16 байт данных]
* SSL-соединение с использованием TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / [пусто] / UNDEF
* ALPN: сервер принял http/1.1
* Сертификат сервера:
*  объект: CN=example.com
*  дата начала: 25 сентября 15:40:55 2024 GMT
*  дата окончания: 24 декабря 15:40:54 2024 GMT
*  subjectAltName: хост "www.example.com" соответствует сертификату "www.example.com"
*  издатель: C=US; O=Let's Encrypt; CN=R10
*  Проверка сертификата SSL пройдена.
*   Уровень сертификата 0: Тип публичного ключа ? (3072/128 бит/сек), подписан с использованием sha256WithRSAEncryption
*   Уровень сертификата 1: Тип публичного ключа ? (2048/112 бит/сек), подписан с использованием sha256WithRSAEncryption
*   Уровень сертификата 2: Тип публичного ключа ? (4096/128 бит/сек), подписан с использованием sha256WithRSAEncryption
* Подключено к www.example.com (123.123.123.123) порт 443
* с использованием HTTP/1.x
> GET /js/_myfuncs.min.js?v=1 HTTP/1.1
> Хост: www.example.com
> User-Agent: curl/8.10.1
> Accept: */*
>
* Запрос полностью отправлен
* TLSv1.2 (IN), TLS handshake, Приветственный запрос (0):
{ [4 байта данных]
* TLSv1.2 (OUT), TLS handshake, Клиентское приветствие (1):
} [255 байт данных]
* TLSv1.2 (IN), TLS handshake, Серверное приветствие (2):
{ [109 байт данных]
* TLSv1.2 (IN), TLS handshake, Сертификат (11):
{ [3282 байта данных]
* TLSv1.2 (IN), TLS handshake, Обмен ключами сервера (12):
{ [493 байта данных]
* TLSv1.2 (IN), TLS handshake, Запрос CERT (13):
{ [30 байт данных]
* TLSv1.2 (IN), TLS handshake, Сервер завершил (14):
{ [4 байта данных]
* TLSv1.2 (OUT), TLS handshake, Сертификат (11):
} [7 байт данных]
* TLSv1.2 (OUT), TLS handshake, Обмен ключами клиента (16):
} [102 байта данных]
* TLSv1.2 (OUT), TLS изменение шифра, Изменить спецификацию шифра (1):
} [1 байт данных]
* TLSv1.2 (OUT), TLS handshake, Завершено (20):
} [16 байт данных]
* Запрос полностью отправлен
* TLSv1.2 (IN), TLS изменение шифра, Изменить спецификацию шифра (1):
{ [1 байт данных]
* TLSv1.2 (IN), TLS handshake, Завершено (20):
{ [16 байт данных]
* старый идентификатор SSL сессии устарел, удаление
< HTTP/1.1 200 OK
< Cache-Control: max-age=31536000
< Content-Type: application/javascript
< Last-Modified: Суб, 16 Ноя 2024 17:27:21 GMT
< Accept-Ranges: bytes
< ETag: "d3f655cb4c38db1:0"
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Content-Type
< Strict-Transport-Security: max-age=63072000; includeSubDomains
< Дата: Пт, 29 Ноя 2024 17:44:22 GMT
< Content-Length: 44307
<
{ [15999 байт данных]
* Ошибка при записи вывода в назначение, передано 15999 вернувшихся 4294967295
* Закрытие соединения
* TLSv1.2 (OUT), TLS предупреждение, закрыть уведомление (256):
} [2 байта данных]

ОБНОВЛЕНИЕ 3

Я снова запустил curl -vso /dev/null --http2 https://www.example.com/js/_myfuncs.min.js?v=1, но теперь прямо на своем VPS, это вывод:

* Хост www.example.com:443 был разрешен.
* IPv6: (нет)
* IPv4: 12.12.12.12
*   Пытаюсь 12.12.12.12:443...
* Подключено к www.example.com (12.12.12.12) порт 443
* ALPN: curl предлагает h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Клиентское приветствие (1):
} [315 байт данных]
*  CAfile: D:\Programs\cURL\curl-ca-bundle.crt
*  CApath: нет
* TLSv1.3 (IN), TLS handshake, Серверное приветствие (2):
{ [94 байта данных]
* TLSv1.2 (IN), TLS handshake, Сертификат (11):
{ [3282 байта данных]
* TLSv1.2 (IN), TLS handshake, Обмен ключами сервера (12):
{ [493 байта данных]
* TLSv1.2 (IN), TLS handshake, Сервер завершил (14):
{ [4 байта данных]
* TLSv1.2 (OUT), TLS handshake, Обмен ключами клиента (16):
} [102 байта данных]
* TLSv1.2 (OUT), TLS изменение шифра, Изменить спецификацию шифра (1):
} [1 байт данных]
* TLSv1.2 (OUT), TLS handshake, Завершено (20):
} [16 байт данных]
* TLSv1.2 (IN), TLS изменение шифра, Изменить спецификацию шифра (1):
{ [1 байт данных]
* TLSv1.2 (IN), TLS handshake, Завершено (20):
{ [16 байт данных]
* SSL-соединение с использованием TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / [пусто] / UNDEF
* ALPN: сервер принял h2
* Сертификат сервера:
*  объект: CN=example.com
*  дата начала: 25 сентября 15:40:55 2024 GMT
*  дата окончания: 24 декабря 15:40:54 2024 GMT
*  subjectAltName: хост "www.example.com" соответствует сертификату "www.example.com"
*  издатель: C=US; O=Let's Encrypt; CN=R10
*  Проверка сертификата SSL пройдена.
*   Уровень сертификата 0: Тип публичного ключа ? (3072/128 бит/сек), подписан с использованием sha256WithRSAEncryption
*   Уровень сертификата 1: Тип публичного ключа ? (2048/112 бит/сек), подписан с использованием sha256WithRSAEncryption
*   Уровень сертификата 2: Тип публичного ключа ? (4096/128 бит/сек), подписан с использованием sha256WithRSAEncryption
* с использованием HTTP/2
* [HTTP/2] [1] ОТКРЫТО потока для https://www.example.com/js/_myfuncs.min.js?v=1
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: www.example.com]
* [HTTP/2] [1] [:path: /js/_myfuncs.min.js?v=1]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /js/_myfuncs.min.js?v=1 HTTP/2
> Хост: www.example.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* HTTP/2 поток 1 не был закрыт корректно: HTTP_1_1_REQUIRED (ошибка 13)
* Понижено до HTTP/1.1
* Пустой ответ от сервера
* Соединение #0 с хостом www.example.com осталось нетронутым
* Сделать еще один запрос к этому URL: 'https://www.example.com/js/_myfuncs.min.js?v=1'
* Найден комплект для хоста: 0x27e2bc1b9b0 [можно мультиплексировать]
* Хост www.example.com найден в кэше DNS
*   Пытаюсь 12.12.12.12:443...
* Подключено к www.example.com (12.12.12.12) порт 443
* ALPN: curl предлагает http/1.1
* SSL повторно использует идентификатор сессии
* TLSv1.2 (OUT), TLS handshake, Клиентское приветствие (1):
} [255 байт данных]
* TLSv1.2 (IN), TLS handshake, Серверное приветствие (2):
{ [100 байт данных]
* TLSv1.2 (IN), TLS handshake, Сертификат (11):
{ [3282 байта данных]
* TLSv1.2 (IN), TLS handshake, Обмен ключами сервера (12):
{ [493 байта данных]
* TLSv1.2 (IN), TLS handshake, Сервер завершил (14):
{ [4 байта данных]
* TLSv1.2 (OUT), TLS handshake, Обмен ключами клиента (16):
} [102 байта данных]
* TLSv1.2 (OUT), TLS изменение шифра, Изменить спецификацию шифра (1):
} [1 байт данных]
* TLSv1.2 (OUT), TLS handshake, Завершено (20):
} [16 байт данных]
* TLSv1.2 (IN), TLS изменение шифра, Изменить спецификацию шифра (1):
{ [1 байт данных]
* TLSv1.2 (IN), TLS handshake, Завершено (20):
{ [16 байт данных]
* старый идентификатор SSL сессии устарел, удаление
< HTTP/1.1 200 OK
< Cache-Control: max-age=31536000
< Content-Type: application/javascript
< Last-Modified: Суб, 16 Ноя 2024 17:27:21 GMT
< Accept-Ranges: bytes
< ETag: "d3f655cb4c38db1:0"
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Content-Type
< Strict-Transport-Security: max-age=63072000; includeSubDomains
< Дата: Пт, 29 Ноя 2024 17:44:22 GMT
< Content-Length: 44307
<
{ [15999 байт данных]
* Ошибка при записи вывода в назначение, передано 15999 вернувшихся 4294967295
* Закрытие соединения
* TLSv1.2 (OUT), TLS предупреждение, закрыть уведомление (256):
} [2 байта данных]

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

Отвечая на ваш вопрос о том, почему HTTP/2 не работает на Windows Server 2019, я постараюсь предоставить вам детальный анализ вашей ситуации и возможные решения, основываясь на вашем описании проблемы и ваших действиях.

1. Проверка настройки HTTP/2

Во-первых, убедитесь, что HTTP/2 включён в настройках вашего сервера. Для выполнения этого действия выполните следующий PowerShell запрос:

Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\HTTP\Parameters" -Name Http2Enabled

Проверьте, что значение Http2Enabled установлено в 1. Если оно не равно 1, вы можете включить HTTP/2, изменив его значение.

2. Актуальность TLS

HTTP/2 требует поддержку TLS 1.2 или выше. Вы уже отключили поддержку TLS 1.0 и 1.1, что является правильным шагом. Убедитесь, что ваши сертификаты совместимы с TLS 1.2 и что ваш сервер действительно использует TLS 1.2 или больше. Для проверки можно использовать онлайн-сервис, такой как SSL Labs. Вы упомянули, что проверка показывает "TLS 1.2 > h2", что указывает на серьезный прогресс.

3. Настройки IIS

Ваши установки IIS, включая параметры привязки HTTPS, должны соответствовать следующим критериям:

  • Убедитесь, что опция "Disable HTTP/2" не отмечена.
  • Должен быть включен серверный имя Indication (SNI).
  • Убедитесь, что у вас есть привязка к IP-адресу "Все не назначенные".

Если вы все это сделали, проверьте сообщение об ошибке, которое возвращается при попытке запроса через HTTP/2. Например, ошибка "HTTP_1_1_REQUIRED" указывает на то, что сервер не поддерживает HTTP/2 для запрашиваемого ресурса.

4. Настройки компрессии

Ваши настройки компрессии в applicationHost.config выглядят правильно, но проверьте также, что настройка компрессии httpCompression разрешает использование всех необходимых типов MIME. Убедитесь, что ни один из мимETYPEов, которые вы обрабатываете (например, application/javascript), не блокируется.

5. Тестирование на локальном сервере

Вы упомянули, что при использовании curl из вашего VPS HTTP/2 работает, но не когда вы подключаетесь из других мест. Это может указывать на сетевые проблемы или проблемы конфигурации веб-сервера. Попробуйте выполнить следующие действия:

  • Проверьте настройки брандмауэра или межсетевого экрана, чтобы убедиться, что они не блокируют запросы HTTP/2.
  • Если у вас есть какие-либо системы защиты (например, WAF), они также могут блокировать HTTP/2.

6. Обновления и зависящие сервисы

Убедитесь, что у вас установлены все обновления для Windows Server 2019 и IIS 10. Иногда обновления могут включать исправления, которые могут улучшить совместимость с HTTP/2.

Заключение

Учитывая все вышеперечисленные шаги, если у вас всё ещё возникают проблемы с HTTP/2 на этом сервере, рекомендуется провести более глубокий анализ логов IIS и системных логов, которые могут дать больше информации о том, что именно происходит при попытке подключения. Этот процесс поможет вам диагностировать и устранить проблему.

Если вам потребуется помощь с конкретными проблемами в логах или дальнейшими шагами, не стесняйтесь обращаться за помощью.

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

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