Вопрос или проблема
Мой веб-сайт обслуживает файлы (например, изображения, js и т.д.), он не использует http/2, он обрабатывает запросы с помощью http/1.
Что я пробовал:
-
Использовал IIS Crypto, я установил это и отключил tls1.0 и tls1.1:
-
Отключил поддержку tls1.0 и tls1.1 в настройках Internet Explorer: https://markcz.wordpress.com/2014/10/26/full-http2-support-in-windows-10/
-
Принудил 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>
-
Выдал группе IIS_IUSRS права на чтение в корневом каталоге
-
Включил анонимную аутентификацию для моего веб-сайта
-
У меня есть https привязки для моего веб-сайта: снял отметку “Отключить HTTP/2”, отметил “Требовать указание имени сервера”, привязан к порту 443, IP-адрес установлен на “Все не назначенные”
ОБНОВЛЕНИЕ 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> -
IIS Application Request Routing не установлен на моем сервере
-
Я проверил настройки SSL/TLS и совместимость сертификата с HTTP/2 через SSL Labs. Там указано “TLS 1.2 > h2”, “TLS 1.2” для современных браузеров. Только старые браузеры показывают “TLS 1.2 > http/1.1”
-
Я не использую никакие CDN или обратные прокси
-
Мой 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>
- мой web.config выглядит так:
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" /> <!-- 365 дней -->
</staticContent>
- мой www.example.com и example.com правильно привязаны в IIS
- “Get-ItemProperty -Path “HKLM:\System\CurrentControlSet\Services\HTTP\Parameters” -Name Http2Enabled” указывает, что Http2Enabled установлен в 1
- Я попробовал
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 и системных логов, которые могут дать больше информации о том, что именно происходит при попытке подключения. Этот процесс поможет вам диагностировать и устранить проблему.
Если вам потребуется помощь с конкретными проблемами в логах или дальнейшими шагами, не стесняйтесь обращаться за помощью.