Windows Server 2022: Deshabilitar TLS 1.3 por sitio en IIS con PowerShell para resolver mTLS

Guía completa y práctica para desactivar TLS trece en un sitio específico de IIS sobre Windows Server dos mil veintidós con PowerShell o AppCmd, y alternativas para mantener mTLS sin deshabilitar el protocolo. Incluye verificación, reversión y notas de operación segura en entornos de producción.

Índice

Panorama y motivo

En entornos que usan autenticación por certificado de cliente (mTLS), la adopción de TLS trece puede provocar fallos cuando la aplicación o la configuración del servidor intentan solicitar el certificado del cliente tras el intercambio inicial. En TLS doce esto se resolvía frecuentemente mediante renegociación; sin embargo, TLS trece limita este mecanismo. En Windows Server dos mil veintidós (IIS diez), existen tres caminos claros:

  • Desactivar TLS trece solo en el binding HTTPS del sitio afectado, sin tocar el resto del servidor.
  • Conservar TLS trece y ajustar HTTP.sys para que el certificado del cliente se negocie durante el primer handshake (workaround).
  • Desactivar TLS trece globalmente en Schannel para todo el sistema.

La recomendación principal para minimizar el impacto es actuar por binding del sitio en IIS.

Lo esencial

  • IIS permite controlar características TLS por binding mediante el atributo sslFlags. Un solo bit desactiva TLS trece sobre TCP para ese binding, sin afectar a otros sitios.
  • El bit correspondiente a “Disable TLS trece over TCP” se añade con una operación OR a los sslFlags existentes para no perder otras opciones como SNI, desactivar HTTP dos o desactivar QUIC.
  • Si necesitas mantener TLS trece con mTLS, puedes activar “Negotiate Client Certificate” en HTTP.sys para que el certificado se solicite en el primer handshake.
  • También es posible desactivar TLS trece de forma global mediante el Registro del sistema (Schannel), lo cual impacta a todos los servicios que usen ese proveedor.

Recomendación principal por sitio en IIS

Esta opción evita el riesgo de deshabilitar TLS trece para todo el servidor y mantiene el control granular por aplicación o dominio.

PowerShell con el módulo WebAdministration

El siguiente script añade el bit de “Disable TLS trece over TCP” al sslFlags del binding HTTPS indicado, preservando cualquier otro valor ya configurado (por ejemplo, SNI o deshabilitar HTTP dos o QUIC):

Import-Module WebAdministration

\$site        = "Default Web Site"   # <-- cámbialo por tu sitio
\$bindingInfo = "\*:443:"             # <-- IP\:PUERTO\:HOSTHEADER (vacío = sin host header)

Ruta al binding HTTPS del sitio

\$filter = "system.applicationHost/sites/site\[@name='\$site']/bindings/binding\[@protocol='https' and @bindingInformation='\$bindingInfo']"

Lee flags actuales y añade el bit 32 (Disable TLS 1.3 over TCP)

\$current = (Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter \$filter -Name 'sslFlags').Value
\$new     = (\[int]\$current) -bor 32

Aplica el nuevo valor

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter \$filter -Name 'sslFlags' -Value \$new

Opcional: recicla el pool o reinicia el sitio para cortar conexiones persistentes

Restart-WebAppPool -Name 'NombreDelPool'

iisreset /noforce

Notas clave

  • sslFlags es un campo por bits. No sobrescribas valores existentes: usa OR para añadir solo el bit deseado. Ejemplo: si ya tienes SNI (bit uno) y desactivar QUIC (bit dieciséis), añadir “Disable TLS trece over TCP” implica OR con treinta y dos. Resultado: uno + dieciséis + treinta y dos = cuarenta y nueve.
  • El cambio afecta a nuevas conexiones. Para que sea inmediato en todos los clientes, recicla el App Pool o reinicia el sitio.
  • Si el sitio ofrece HTTP tres (QUIC), recuerda que TLS trece se usa siempre sobre QUIC. Si tu objetivo es evitar TLS trece por completo, además desactiva QUIC en el binding (bit por desactivar QUIC) o a nivel del servidor.

AppCmd como alternativa directa

Si ya conoces el valor final de sslFlags que necesitas (por ejemplo, SNI + Disable TLS trece = treinta y tres):

%windir%\system32\inetsrv\appcmd.exe set site /site.name:"Default Web Site" ^
/bindings.[protocol='https',bindingInformation='*:443:'].sslFlags:33

Para confirmar el resultado con PowerShell:

Get-WebBinding -Name "Default Web Site" -Protocol https | 
  Select-Object protocol,bindingInformation,sslFlags | Format-Table -AutoSize

Consideraciones de operación

  • Certificados y SNI: si usas SNI, asegúrate de que bindingInformation incluye el host y que el certificado correcto está asociado a ese binding.
  • HTTP dos y HTTP tres: deshabilitar TLS trece sobre TCP no afecta a QUIC. Para eliminar cualquier ruta de TLS trece, desactiva también QUIC en el binding o a nivel global.
  • Pruebas: valida desde un equipo cliente con herramientas de línea de comandos antes de poner en producción.

Solución con certificados de cliente sin deshabilitar el protocolo

Si debes conservar TLS trece y a la vez usar mTLS, puedes indicarle a HTTP.sys que negocie el certificado en el primer intercambio. Esto evita la dependencia de renegociación posterior.

Registro en HTTP.sys

Ejemplo de clave para un binding de todo el sistema en la dirección cero punto cero punto cero punto cero y puerto cuatrocientos cuarenta y tres. El valor “DefaultFlags = dos” habilita negociar certificado de cliente:

HKLM\SYSTEM\ControlSet001\Services\HTTP\Parameters\SslBindingInfo\0.0.0.0:443
DWORD DefaultFlags = 2

Después de ajustar el registro, reinicia el servicio HTTP o el servidor según tus políticas de cambio para garantizar que la configuración se aplique a todas las conexiones.

Uso de netsh

También puedes gestionar el binding SSL de HTTP.sys con netsh. El parámetro relevante es clientcertnegotiation=enable. La sintaxis exacta depende de tu entorno, pero la idea es agregar o actualizar el certificado asociado a la IP y puerto con la negociación de certificado habilitada:

netsh http show sslcert

REM Basado en la salida anterior, vuelve a agregar o actualiza el binding
REM con clientcertnegotiation habilitado
netsh http add sslcert ipport=0.0.0.0:443 certhash=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX appid={00000000-0000-0000-0000-000000000000} certstorename=MY clientcertnegotiation=enable 

Advertencia: aunque este enfoque resuelve la mayoría de escenarios prácticos, puede no ajustarse estrictamente a ciertas interpretaciones del estándar. Úsalo bajo tu criterio y documenta la excepción para auditoría.

Ventajas y límites

  • Ventaja: conservas TLS trece para clientes que no usan mTLS y evitas tocar otros sitios.
  • Límite: añade complejidad en HTTP.sys; requiere gobierno de cambios claro y pruebas de compatibilidad.

Desactivar en todo el servidor con Schannel

Si tu política requiere eliminar TLS trece de forma global, puedes hacerlo con las claves de Schannel en el Registro. Impacta a todas las aplicaciones que usen Schannel, no solo IIS.

PowerShell para el Registro de Schannel

# Desactivar TLS 1.3 en modo servidor (inbound)
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Name 'Enabled' -Value 0 -PropertyType DWord -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server' -Name 'DisabledByDefault' -Value 1 -PropertyType DWord -Force | Out-Null

(Opcional) Desactivar TLS 1.3 como cliente (outbound)

New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client' -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client' -Name 'Enabled' -Value 0 -PropertyType DWord -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client' -Name 'DisabledByDefault' -Value 1 -PropertyType DWord -Force | Out-Null 

Buenas prácticas: programa una ventana de mantenimiento y un reinicio controlado. Aunque algunos servicios toman el cambio tras reciclar procesos, un reinicio evita estados ambiguos en sesiones TLS persistentes.

Verificación y pruebas

Valida el resultado desde el servidor y desde un host externo.

Comprobación en IIS

Get-WebBinding -Name "MiSitio" -Protocol https |
  Format-Table protocol,bindingInformation,sslFlags -AutoSize

Confirma que sslFlags incluye el bit correspondiente a “Disable TLS trece over TCP”.

Pruebas remotas con OpenSSL

# Prueba forzando TLS 1.3 (debe fallar cuando está deshabilitado en el binding)
openssl sclient -connect dominio:443 -tls13

Prueba forzando TLS 1.2 (debe funcionar)

openssl s\client -connect dominio:443 -tls1\2 

Pruebas con curl

# Falla si TLS trece está deshabilitado sobre TCP
curl -vk --tlsv1.3 https://dominio/

Debe funcionar con TLS doce

curl -vk --tlsv1.2 [https://dominio/](https://dominio/) 

Comprobación de HTTP.sys para mTLS

netsh http show sslcert
REM Busca "Negotiate Client Certificate : Enabled" en la IP:puerto correspondiente

Tabla de opciones de sslFlags

Referencia rápida de los bits más habituales en sslFlags para bindings HTTPS de IIS. Usa OR para combinarlos según tu escenario:

BitValorSignificadoCuándo usar
uno1Indica SNI (Server Name Indication).Hosting múltiple por nombre con certificados por host.
dos2Uso de certificados centralizados.Cuando empleas almacén central de certificados.
cuatro4Desactivar HTTP dos en HTTPS.Diagnóstico o compatibilidad con clientes antiguos.
dieciséis16Desactivar QUIC (HTTP tres) en el binding.Evitar ruta de QUIC cuando necesitas control solo por TCP.
treinta y dos32Desactivar TLS trece sobre TCP en el binding.Solucionar problemas de mTLS en ese sitio sin tocar el resto.

Nota: la lista anterior se centra en las opciones relevantes para este artículo.

Escenarios de uso

  • Aplicación con mTLS roto tras migración: añade el bit de “Disable TLS trece over TCP” en el binding del sitio afectado. Si además usas HTTP tres, desactívalo para evitar rutas alternativas.
  • Plataforma multisitio: aplica el cambio solo a los sitios que lo requieran. Mantén TLS trece en sitios que no usan mTLS para conservar beneficios de seguridad y rendimiento.
  • Requisitos normativos específicos: si el cliente exige TLS doce por contrato, aplica la política por binding y documenta la excepción.

Ejemplos listos para copiar

Función idempotente para un solo sitio

function Disable-Tls13OnHttpsBinding {
  param(
    [Parameter(Mandatory=$true)][string]$SiteName,
    [Parameter(Mandatory=$true)][string]$BindingInformation # Ej: ":443:" o "0.0.0.0:443:" o ":443:dominio.com"
  )
  Import-Module WebAdministration
  $filter = "system.applicationHost/sites/site[@name='$SiteName']/bindings/binding[@protocol='https' and @bindingInformation='$BindingInformation']"
  $prop = Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter $filter -Name 'sslFlags'
  if (-not $prop) { throw "Binding HTTPS no encontrado para $SiteName con $BindingInformation" }
  $current = [int]$prop.Value
  $desired = $current -bor 32
  if ($desired -ne $current) {
    Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter $filter -Name 'sslFlags' -Value $desired | Out-Null
    Write-Host "Actualizado sslFlags de $current a $desired"
  } else {
    Write-Host "Sin cambios: TLS trece ya estaba deshabilitado sobre TCP (sslFlags=$current)"
  }
}
Ejemplo:
Disable-Tls13OnHttpsBinding -SiteName "Default Web Site" -BindingInformation "*:443:"

Aplicar a múltiples sitios automáticamente

Import-Module WebAdministration
$bindings = Get-WebBinding | Where-Object { $_.protocol -eq 'https' }
foreach ($b in $bindings) {
  $filter = "system.applicationHost/sites/site[@name='$($b.itemXPath.Split(\"'\")[1])']/bindings/binding[@protocol='https' and @bindingInformation='$($b.bindingInformation)']"
  $current = (Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter $filter -Name 'sslFlags').Value
  $new     = ([int]$current) -bor 32
  if ($new -ne $current) {
    Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter $filter -Name 'sslFlags' -Value $new | Out-Null
    Write-Host "Binding $($b.bindingInformation): sslFlags $current -&gt; $new"
  } else {
    Write-Host "Binding $($b.bindingInformation): sin cambios"
  }
}

Reversión limpia por sitio

Para revertir, elimina el bit de “Disable TLS trece” conservando el resto:

Import-Module WebAdministration
$site        = "Default Web Site"
$bindingInfo = "*:443:"
$filter = "system.applicationHost/sites/site[@name='$site']/bindings/binding[@protocol='https' and @bindingInformation='$bindingInfo']"

\$current = (Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter \$filter -Name 'sslFlags').Value

Quita el bit 32 con AND sobre el complemento

\$new = (\[int]\$current) -band (-bnot 32)
Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter \$filter -Name 'sslFlags' -Value \$new 

Preguntas frecuentes

¿Desactivar TLS trece en el binding afecta a otros sitios del servidor?
No. El cambio es específico del binding HTTPS sobre el que se aplica.

¿Qué pasa si el cliente intenta usar HTTP tres?
HTTP tres usa QUIC y TLS trece por diseño. Si no desactivas QUIC, el cliente podría seguir negociando TLS trece por esa vía. Si deseas evitarlo, añade el bit de “desactivar QUIC” en el binding o desactívalo globalmente.

¿Es necesario reiniciar el servidor tras modificar sslFlags?
No suele ser necesario. Los cambios aplican a nuevas conexiones. Para acelerar la adopción en clientes con conexiones persistentes, recicla el App Pool o reinicia el sitio.

¿Cuándo conviene la solución de HTTP.sys?
Cuando debas conservar TLS trece por razones de seguridad o compatibilidad, pero tu aplicación depende de solicitar el certificado de cliente en el primer intercambio. Documenta el cambio y pruébalo a conciencia.

¿Cómo verifico rápidamente desde un Linux o macOS?
Con openssl s_client o curl forzando la versión del protocolo, tal como se muestra en la sección de verificación.

Riesgos y recomendaciones de seguridad

  • Reducción de superficie moderna: desactivar TLS trece te priva de mejoras de seguridad y rendimiento. Mantén un plan para volver a habilitarlo cuando sea viable.
  • Telemetría y alertas: monitoriza errores de negociación TLS, códigos de estado y quejas de clientes. Revisa logs de IIS y del sistema.
  • Cobertura de pruebas: valida navegadores, SDKs y agentes automatizados. Determina si existen clientes que solo negocian HTTP tres.
  • Política de certificados: asegúrate de que la cadena de confianza, EKUs y revocación están al día; muchos problemas atribuidos a TLS trece en realidad son fallos de la PKI.

Reversión y plan de salida

  • Por binding: elimina el bit correspondiente en sslFlags y recicla el proceso de trabajo.
  • Global: establece Enabled=1 y DisabledByDefault=0 en las claves de Server y Client para TLS trece de Schannel y reinicia durante una ventana de mantenimiento.
  • Documentación: registra quién, cuándo y por qué se aplicaron los cambios; adjunta evidencias de pruebas.

Notas para operación diaria

  • Incluye la comprobación de sslFlags en tus auditorías de configuración.
  • Automatiza con scripts idempotentes para evitar errores manuales.
  • Versiona los archivos de configuración de IIS (applicationHost.config) o usa desired state con tu herramienta de automatización favorita.

Resumen ejecutivo

  • Es posible y seguro desactivar TLS trece por sitio en IIS ajustando sslFlags del binding HTTPS mediante PowerShell o AppCmd.
  • Si necesitas mantener TLS trece junto con mTLS, habilita la negociación de certificado en HTTP.sys para forzar la solicitud en el primer intercambio.
  • Como última opción, deshabilita TLS trece globalmente en Schannel, planificando reinicio y comunicando el cambio.
  • Verifica con herramientas de línea de comandos y documenta el estado de cada binding.

Apéndice de comandos rápidos

ObjetivoComandoResultado esperado
Ver bindings y sslFlagsGet-WebBinding -Protocol https | ft protocol,bindingInformation,sslFlagsLista todos los bindings HTTPS con sus flags actuales.
Desactivar TLS trece por sitioSet-WebConfigurationProperty ... -Name 'sslFlags' -Value ($current -bor 32)El binding niega TLS trece sobre TCP en nuevas conexiones.
Forzar prueba con TLS treceopenssl sclient -connect dominio:443 -tls13Falla la negociación si el sitio lo tiene deshabilitado.
Forzar prueba con TLS doceopenssl sclient -connect dominio:443 -tls12Se establece la conexión exitosamente si TLS doce está habilitado.
Ver estado de HTTP.sysnetsh http show sslcertIndica si “Negotiate Client Certificate” está habilitado por IP:puerto.

Seguridad: desactivar protocolos modernos debe ser una medida temporal mientras resuelves incompatibilidades. Planifica volver a TLS trece una vez que la aplicación o el proxy frontal negocien el certificado de cliente en el primer intercambio.


Conclusión
Con los mecanismos disponibles en IIS y HTTP.sys puedes corregir de forma quirúrgica los fallos de mTLS relacionados con TLS trece sin comprometer la postura de seguridad del resto de tu plataforma. Empieza por el ajuste por binding, valida con pruebas controladas y documenta tanto el cambio como la ruta de reversión.

Índice