Qual é a melhor maneira de ativar o HTTP Strict Transport Security em um servidor Web IIS 7?
Posso apenas através da GUI e adicionar o cabeçalho de resposta HTTP adequado ou devo usar o appcmd e, em caso afirmativo, o que muda?
Qual é a melhor maneira de ativar o HTTP Strict Transport Security em um servidor Web IIS 7?
Posso apenas através da GUI e adicionar o cabeçalho de resposta HTTP adequado ou devo usar o appcmd e, em caso afirmativo, o que muda?
Respostas:
O IIS tem a capacidade de adicionar cabeçalhos personalizados às respostas . Essa seria a maneira mais fácil de fazer isso.
De acordo com a documentação no IIS.net, você pode adicionar esses cabeçalhos através do Gerenciador do IIS:
- No painel Conexões, acesse o site, aplicativo ou diretório para o qual você deseja definir um cabeçalho HTTP personalizado.
- No painel Inicial, clique duas vezes em Cabeçalhos de Resposta HTTP.
- No painel Cabeçalhos de resposta HTTP, clique em Adicionar ... no painel Ações.
- Na caixa de diálogo Adicionar cabeçalho de resposta HTTP personalizado, defina o nome e o valor do seu cabeçalho personalizado e clique em OK.
Isso nos permite manipular o redirecionamento HTTP e adicionar o cabeçalho Strict-Transport-Security às respostas HTTPS com um único site IIS (o módulo URL Rewrite deve ser 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 obter um passe em hstspreload.org
https://somedomain.com/https://somedomain.com/relatedpath
e o resultado é que o caminho foi interrompido.
Para complementar a resposta do voretaq7 , você também pode fazer isso usando o arquivo Web.config (NB: Para ser usado apenas em sites SSL, pois ele adicionará o cabeçalho das respostas HTTP e HTTPS, que é contra a especificação RFC 6797, veja a explicação abaixo) - adicione um bloco da seguinte maneira:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Obviamente, você já pode ter um system.webServer
bloco no seu Web.config, então adicione isso a isso, se houver. Preferimos manipular as coisas no Web.config do que na GUI, porque isso significa que as alterações na configuração podem ser confirmadas em nosso repositório Git.
Se você deseja lidar com o redirecionamento HTTP para SSL, como Greg Askew mencionou, talvez seja mais fácil fazer isso com um site separado no IIS. É assim que lidamos com a exigência de SSL para alguns sites clientes. Esse site contém apenas um redirecionamento HTTP e algumas correções de divulgação de informações , todas no 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 é a nossa solução preferida por alguns motivos - podemos registrar facilmente o tráfego redirecionado separadamente (como em um log do IIS diferente), não envolve mais código no Global.asax.cs (não temos nenhum código lá, o que é um pouco mais conveniente para um site da Umbraco) e, o que é mais importante, significa que toda a configuração ainda é realizada em nosso repositório GIT.
Editado para adicionar: Para ficar claro, para cumprir a RFC 6797 , o Strict-Transport-Security
cabeçalho personalizado NÃO DEVE ser adicionado a solicitações feitas por HTTP não criptografado. Para ser compatível com RFC6797, você DEVE ter dois sites no IIS, como descrevi após o primeiro bloco de código. Como Chris aponta, o RFC 6797 inclui:
Um host HSTS NÃO DEVE incluir o campo de cabeçalho STS nas respostas HTTP transmitidas por transporte não seguro.
portanto, o envio do Strict-Transport-Security
cabeçalho do cliente em resposta a uma solicitação não SSL não estaria em conformidade com a especificação.
Eu usaria o exemplo do link da Wikipedia que você referenciou e executaria a atividade em global.asax para o site. Isso permite redirecionar a solicitação para uma URL https e, em seguida, insira o cabeçalho na resposta.
Isso ocorre porque o cabeçalho do HSTS deve ser ignorado se não estiver em uma resposta 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;
}
}
Esta parece ser uma maneira bastante segura de fazer isso. Adicione esse código ao Global.asax - o evento Application_BeginRequest é acionado primeiro no ciclo de vida da solicitação do Asp.net: http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest(v=vs. 110) .aspx
De acordo com a especificação, as solicitações HTTP não devem responder com o cabeçalho - portanto, esse código o adiciona apenas para solicitações https. A idade máxima é de alguns segundos e geralmente é uma boa ideia colocar um valor grande aqui (IE - 31536000 indica que o site executará SSL apenas pelos próximos 365 dias)
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;
}
}
Usando o exemplo fornecido por Doug Wilson, criei as duas funções do PowerShell a seguir para adicionar regras de reescrita de URL para redirecionamento para HTTPS e para adicionar cabeçalhos HSTS.
Estes foram testados no Windows 2012 e Windows 2012 R2.
Tudo que você precisa fazer é fornecer o nome do site. Você pode opcionalmente dar um nome diferente às regras se não gostar dos padrões.
Um ponto a ser observado é que, nos meus testes, as variáveis de servidor precisam ser adicionadas à lista de permissões antes de estar nos cabeçalhos de resposta. As funções fazem isso por você.
EDIT: Consulte a referência na reescrita de URL para cabeçalhos HTTP aqui: 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 acordo com os fabricantes do módulo IIS de segurança estrita de transporte HTTP, apenas adicionar o cabeçalho personalizado não é compatível com a especificação preliminar (RFC 6797).
Você realmente precisaria instalar este módulo IIS para ativar o HSTS no IIS 7.
Atualização 26 de outubro de 2014 : Graças ao comentarista abaixo, li a página do módulo novamente e, especificamente, a parte que justifica o uso do módulo ao adicionar cabeçalhos personalizados.
Um host HSTS NÃO DEVE incluir o campo de cabeçalho STS nas respostas HTTP transmitidas por transporte não seguro.
Se você adicionar os cabeçalhos apenas em HTTPS e NÃO em HTTP, não precisará deste módulo e poderá usar a resposta de Doug Wilson. Não use a resposta de Owen Blacker, pois ela não possui a condição https.
Isso pode ser feito adicionando o seguinte bloco no Web.Config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name ="CustomName" value="MyCustomValue"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Temos que configurar no IIS que tem a capacidade de personalizar cabeçalhos de resposta:
Só para adicionar, vejo nos comentários 2 pessoas falando sobre 500 erros quando você faz isso. Eu tive isso.
Se você receber um erro 500 no IIS, talvez seja porque você adicionou a regra no nível superior, definido como herdado e no nível do site.
por exemplo
Default Web Site <- here
Some Web Site <- here
IIS / O Navegador não parece fornecer nenhuma informação que você tenha feito, independentemente das suas configurações de tratamento de erros