After upgrading to Windows 10 with IIS 10, Chrome started blocking my local HTTPS development environment with ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY
. The issue stems from Chrome's strict HTTP/2 security requirements conflicting with my self-signed certificate configuration.
// Fiddler capture of failed handshake
Version: 3.3 (TLS/1.2)
Cipher: TLS_RSA_WITH_AES_128_GCM_SHA256 [0x009C]
Extensions:
ALPN h2 // HTTP/2 negotiation attempt
server_name empty // Missing proper SNI
The original certificate lacked modern cipher requirements. Here's the improved PowerShell command:
# Generate compliant self-signed cert
New-SelfSignedCertificate
-Subject "CN=myapp.local"
-KeyAlgorithm RSA
-KeyLength 4096
-HashAlgorithm SHA384
-KeyExportPolicy Exportable
-KeyUsage DigitalSignature, KeyEncipherment
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")
-CertStoreLocation "Cert:\LocalMachine\My"
-NotAfter (Get-Date).AddYears(5)
Critical cipher suite priorities for Chrome HTTP/2 compatibility:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Add this to applicationHost.config for proper HTTP/2 handling:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Alt-Svc" value="h2=http/:443; ma=86400" />
</customHeaders>
</httpProtocol>
<webSocket enabled="false" /> <!-- Required for some HTTP/2 scenarios -->
</system.webServer>
Use this OpenSSL command to verify cipher compatibility:
openssl s_client -connect myapp.local:443 -servername myapp.local -tls1_2 -status
Look for these indicators in the output:
- Protocol: TLSv1.2
- Cipher: ECDHE-RSA-AES256-GCM-SHA384
- OCSP Response: None (acceptable for development)
For legacy compatibility, add this registry setting:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters]
"EnableHttp2Tls"=dword:00000000
"EnableHttp2Cleartext"=dword:00000000
Component | Requirement |
---|---|
Certificate | RSA 4096-bit, SHA384, KeyUsage=Digital Signature |
Cipher Order | ECDHE suites prioritized |
Protocols | TLS 1.2 only (for strict mode) |
HTTP/2 | ALPN extension present |
When Windows 10 upgraded my IIS to version 10, Chrome suddenly started rejecting my perfectly valid local development setup with ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY. The root cause? IIS 10 defaults to HTTP/2 (which Chrome implements via SPDY) with stricter cipher requirements than HTTP/1.1.
The original makecert commands need adjustment for HTTP/2 compatibility. Here's my updated certificate generation script:
# Generate root CA (run as Admin)
makecert.exe -pe -n "CN=DevRootCA" -ss Root -sr LocalMachine -a sha256 -len 2048 -cy authority -r
# Generate server cert (adjust myapp.local to your domain)
makecert.exe -pe -n "CN=myapp.local" -ss My -sr LocalMachine -a sha256 -len 2048 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in "DevRootCA" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
Through Fiddler analysis, I discovered Chrome's HTTP/2 implementation rejects certain cipher suites that were perfectly fine for HTTP/1.1. Here's the working configuration through IIS Crypto CLI:
IISCrypto.exe /reboot /protocols @All=0 @TLS1.2=1 @TLS1.1=1 @TLS1.0=1
IISCrypto.exe /cipherSuites "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
The site binding in IIS needs explicit HTTP/2 configuration. Add this to your applicationHost.config:
<site name="myapp.local" id="2">
<bindings>
<binding protocol="https" bindingInformation="*:443:myapp.local"
sslFlags="1" />
</bindings>
<applicationDefaults enabledProtocols="http/1.1,http/2" />
</site>
If you don't need HTTP/2 features for local development, the simplest solution is to disable it:
# Via registry
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters" /v EnableHttp2Tls /t REG_DWORD /d 0 /f
After applying these changes:
- Run
netsh http show sslcert
to verify your certificate is properly bound - Check
Test-NetConnection -ComputerName myapp.local -Port 443
in PowerShell - Use Chrome DevTools (Security tab) to inspect the connection details
Remember to restart both IIS (iisreset
) and Chrome after making these changes.