¿Cuál es la mejor manera de activar HTTP Strict Transport Security en un servidor web IIS 7?
¿Puedo simplemente a través de la GUI y agregar el encabezado de respuesta HTTP adecuado o debería usar appcmd y, de ser así, qué cambia?
¿Cuál es la mejor manera de activar HTTP Strict Transport Security en un servidor web IIS 7?
¿Puedo simplemente a través de la GUI y agregar el encabezado de respuesta HTTP adecuado o debería usar appcmd y, de ser así, qué cambia?
Respuestas:
IIS tiene la capacidad de agregar encabezados personalizados a las respuestas . Esta parece ser la forma más fácil de hacerlo.
De acuerdo con la documentación en IIS.net , puede agregar estos encabezados a través del Administrador de IIS:
- En el panel Conexiones, vaya al sitio, la aplicación o el directorio para el que desea establecer un encabezado HTTP personalizado.
- En el panel de inicio, haga doble clic en Encabezados de respuesta HTTP.
- En el panel Encabezados de respuesta HTTP, haga clic en Agregar ... en el panel Acciones.
- En el cuadro de diálogo Agregar encabezado de respuesta HTTP personalizado, establezca el nombre y el valor de su encabezado personalizado y luego haga clic en Aceptar.
Esto nos permite manejar la redirección HTTP y agregar el encabezado Strict-Transport-Security a las respuestas HTTPS con un solo sitio IIS (el módulo URL Rewrite debe estar instalado):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"
redirectType="Permanent" />
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security"
pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000; includeSubDomains; preload" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
<action type="Rewrite" value="max-age=31536000 ;includeSubDomains; preload" />
para obtener un pase en hstspreload.org
https://somedomain.com/https://somedomain.com/relatedpath
y el resultado es que la ruta se descartó.
Para complementar la respuesta de voretaq7 , también puede hacerlo utilizando el archivo Web.config (NB: para ser utilizado solo en sitios SSL, ya que agregará el encabezado para las respuestas HTTP y HTTPS, lo que va en contra de la especificación RFC 6797, consulte la explicación a continuación): agregue un bloque de la siguiente manera:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Obviamente, es posible que ya tenga un system.webServer
bloqueo en su Web.config, así que agregue esto a eso, si es así. Preferimos manejar cosas en Web.config en lugar de la GUI, porque significa que los cambios de configuración pueden confirmarse en nuestro repositorio Git.
Si desea manejar la redirección de HTTP a SSL, como mencionó Greg Askew , puede que le resulte más fácil hacerlo con un sitio web separado en IIS. Así es como manejamos la necesidad de SSL para algunos sitios de clientes. Ese sitio contiene solo un redireccionamiento HTTP y algunas correcciones de divulgación de información , todo en la Web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpRuntime requestValidationMode="2.0" enableVersionHeader="false" />
</system.web>
<system.webServer>
<httpRedirect enabled="true" destination="https://www.domain.co.uk/"
httpResponseStatus="Permanent" />
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
<rewrite>
<outboundRules>
<rule name="Remove RESPONSE_Server">
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
Esta es nuestra solución preferida por un par de razones: podemos registrar fácilmente el tráfico redirigido por separado (ya que está en un registro IIS diferente), no involucra más código en Global.asax.cs (no tenemos ningún código allí, que es un poco más conveniente para un sitio de Umbraco) y, lo que es más importante, significa que toda la configuración todavía se mantiene en nuestro repositorio de GIT.
Editado para agregar: Para ser claros, para cumplir con RFC 6797 , el Strict-Transport-Security
encabezado personalizado NO DEBE agregarse a las solicitudes realizadas por HTTP no encriptado. Para cumplir con RFC6797, DEBE tener dos sitios en IIS, como lo describí después del primer bloque de código. Como Chris señala, RFC 6797 incluye:
Un host HSTS NO DEBE incluir el campo de encabezado STS en las respuestas HTTP transmitidas a través del transporte no seguro.
por lo que enviar el Strict-Transport-Security
encabezado del cliente en respuesta a una solicitud que no sea SSL no cumpliría con la especificación
Usaría el ejemplo del enlace de Wikipedia al que hizo referencia y realizaría la actividad en global.asax para el sitio. Esto permite redirigir la solicitud a una URL https y luego insertar el encabezado en la respuesta.
Esto se debe a que el encabezado HSTS debe ignorarse si no está en una respuesta https.
protected void Application_BeginRequest()
{
switch (Request.Url.Scheme)
{
case "https":
Response.AddHeader("Strict-Transport-Security", "max-age=31536000");
break;
case "http":
var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", path);
break;
}
}
Esto parece ser una manera bastante segura de hacer esto. Agregue este código en Global.asax: el evento Application_BeginRequest se dispara primero en el ciclo de vida de la solicitud Asp.net: http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest(v=vs. 110) .aspx
Según la especificación, las solicitudes http no deben responder con el encabezado, por lo que este código solo lo agrega para las solicitudes https. La edad máxima es en número de segundos, y generalmente es una buena idea poner un valor grande aquí (IE - 31536000 indica que el sitio ejecutará SSL solo durante los próximos 365 días)
protected void Application_BeginRequest(Object sender, EventArgs e)
{
switch (Request.Url.Scheme)
{
case "https":
Response.AddHeader("Strict-Transport-Security", "max-age=31536000");
break;
case "http":
var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", path);
break;
}
}
Utilizando el ejemplo proporcionado por Doug Wilson, he creado las siguientes dos funciones de PowerShell para agregar reglas de reescritura de URL para redireccionar a HTTPS y para agregar encabezados HSTS.
Estos han sido probados en Windows 2012 y Windows 2012 R2.
Todo lo que necesita hacer es proporcionar el nombre del sitio web. Opcionalmente, puede asignar un nombre diferente a las reglas si no le gustan los valores predeterminados.
Una cosa a tener en cuenta es que, a partir de mis pruebas, las variables del servidor deben agregarse a la lista de permisos antes de estar en los encabezados de respuesta. Las funciones hacen esto por ti.
EDITAR: consulte la referencia sobre Reescritura de URL para encabezados HTTP aquí: http://www.iis.net/learn/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables
Function Add-HTTPSRedirectRewriteRule()
{
<#
.SYNOPSIS
This function is used to create a URL Rewrite Rule that redirects HTTP requests to HTTPS using a 301
RuleName is optional and will default to "Redirect to HTTPS"
.SYNTAX
Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com"
.EXAMPLES
Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com"
Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com" -RuleName "my rule name"
#>
[cmdletbinding(positionalbinding=$false)]
Param
(
[parameter(mandatory=$true)][String] [ValidateNotNullOrEmpty()] $WebsiteName,
[parameter(mandatory=$false)][String] $RuleName="Redirect to HTTPS"
)
Write-Verbose -Message "Creating the Url Rewrite rule ""$RuleName"" in website ""$WebsiteName"""
Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/rules" -name "." -AtElement @{name="$RuleName"} -ErrorAction SilentlyContinue
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules" -name "." -value @{name="$RuleName";stopProcessing='True'}
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/match" -name "url" -value "(.*)"
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/conditions" -name "." -value @{input='{HTTPS}';pattern='off'}
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "type" -value "Redirect"
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "url" -value "https://{HTTP_HOST}/{R:1}"
}
Function Add-HSTSHeaderRewriteRule()
{
<#
.SYNOPSIS
This function is used to create a URL Rewrite Rule that sets an HTTP Response Header for Strict-Transport-Security
when the protocol requested is HTTPS
RuleName is optional and will default to "Add Strict-Transport-Security header when request is HTTPS"
.SYNTAX
Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com"
.EXAMPLES
Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com"
Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com" -RuleName "my rule name"
#>
[cmdletbinding(positionalbinding=$false)]
Param
(
[parameter(mandatory=$true)][String] [ValidateNotNullOrEmpty()] $WebsiteName,
[parameter(mandatory=$false)][String]$RuleName="Add Strict-Transport-Security header when request is HTTPS"
)
$serverVariable = "RESPONSE_Strict_Transport_Security"
Write-Verbose -Message "Creating the HSTS Header rule ""$RuleName"" in website ""$WebsiteName"""
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/allowedServerVariables" -name "." -AtElement @{name="$serverVariable"} -ErrorAction SilentlyContinue
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/allowedServerVariables" -name "." -value @{name="$serverVariable"}
Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -name "." -filter "system.webServer/rewrite/outboundRules" -AtElement @{name="$RuleName"} -ErrorAction SilentlyContinue
Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules" -name "." -value @{name="$RuleName"}
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/match" -name "serverVariable" -value $serverVariable
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/match" -name "pattern" -value ".*"
Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/conditions" -name "." -value @{input='{HTTPS}';pattern='on'}
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/action" -name "type" -value "Rewrite"
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/action" -name "value" -value "max-age=31536000"
}
De acuerdo con los creadores del módulo HTTP Strict Transport Security IIS, solo agregar el encabezado personalizado no cumple con el borrador de la especificación (RFC 6797).
En realidad, necesitaría instalar este módulo IIS para activar HSTS en IIS 7.
Actualización 26 de octubre de 2014 : Gracias al comentarista a continuación, leí la página del módulo nuevamente y específicamente la parte que justifica el uso del módulo sobre la adición de encabezados personalizados.
Un host HSTS NO DEBE incluir el campo de encabezado STS en las respuestas HTTP transmitidas a través del transporte no seguro.
Si se asegura de agregar los encabezados solo en HTTPS y NO en HTTP, no necesita este módulo y puede usar la respuesta de Doug Wilson. No use la respuesta de Owen Blacker porque no tiene la condición https.
Esto se puede hacer agregando el siguiente bloque en Web.Config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name ="CustomName" value="MyCustomValue"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Tenemos que configurar en IIS que tenga la capacidad de personalizar los encabezados para responder:
Solo para agregar, veo en los comentarios a 2 personas hablando de 500 errores cuando haces esto. Tuve esto
Si obtiene un error 500 en IIS puede ser porque ha agregado la regla tanto en el nivel superior, configurado como heredado y en el nivel del sitio.
p.ej
Default Web Site <- here
Some Web Site <- here
IIS / The Browser no parece darle ninguna información de que haya hecho esto, independientemente de la configuración de manejo de errores