Включить HTTP Strict Transport Security (HSTS) в IIS 7

76

Каков наилучший способ включить HTTP Strict Transport Security на веб-сервере IIS 7?

Могу ли я просто через графический интерфейс и добавить правильный заголовок ответа HTTP или я должен использовать appcmd, и если да, то что переключается?

боб
источник
1
Многое зависит от того, как вы генерируете материал, который обслуживает IIS (например, вы можете установить заголовок на страницах PHP или ASP.NET из вашего приложения). Можете ли вы рассказать нам больше о вашем случае использования?
voretaq7

Ответы:

18

IIS имеет возможность добавлять пользовательские заголовки к ответам . Казалось бы, это самый простой способ сделать это.

Согласно документации на IIS.net вы можете добавить эти заголовки через IIS Manager:

  • На панели «Подключения» перейдите на сайт, приложение или каталог, для которого вы хотите установить настраиваемый заголовок HTTP.
  • На главной странице дважды щелкните заголовки ответа HTTP.
  • На панели заголовков ответа HTTP нажмите кнопку Добавить ... на панели действий.
  • В диалоговом окне «Добавление настраиваемого заголовка ответа HTTP» задайте имя и значение для настраиваемого заголовка и нажмите кнопку «ОК».
voretaq7
источник
5
Это также возможно сделать в Web.config, который вы можете предпочесть. Я разместил подробности в виде нового ответа, так как их было бы действительно трудно прочитать без форматирования исходного кода, которого нет в комментариях.
Оуэн Блэкер,
3
По словам создателей модуля IIS HTTP Strict Transport Security , простое добавление пользовательского заголовка не соответствует проекту спецификации (RFC 6797). Вам действительно нужно установить этот модуль IIS.
Крис
@ Крис Они (вроде) не правы. Не о спецификациях - они абсолютно верны там - но о том, что не существует «простого» способа соответствовать требованиям их модуля: просто создайте 2 сайта, один для SSL (с заголовком) и один для не-SSL ( без заголовка). Конечно, модуль немного более элегантен , но в этом нет необходимости (и вообще не гарантируется, если ваш сайт предназначен только для https и вы не обслуживаете простые HTTP-ответы).
voretaq7
1
@Chris Вы должны добавить ответ, ссылающийся на этот модуль, хотя - бесплатные голоса! (Я не знал о его существовании, и для многих людей это, вероятно, более простой / лучший вариант, чем пользовательские заголовки)
voretaq7
112

Это позволяет нам обрабатывать как перенаправление HTTP, так и добавлять заголовок Strict-Transport-Security к ответам HTTPS с одним сайтом IIS (необходимо установить модуль перезаписи URL):

<?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>
Дуг Уилсон
источник
7
Спасибо, это лучший ответ! Добавляет заголовок и к статическим HTML-файлам, в отличие от программного подхода. И не добавляет к HTTP, таким образом, соответствует стандарту.
Джоу Ли Хуан,
4
@ Mathemats У вас есть установленный в IIS URL Rewrite?
Дуг Уилсон
3
Нет, после дополнительных исследований я обнаружил, что тег перезаписи предоставляется расширением (d'oh). Во всех ответах, которые я смог найти, не упоминается расширение как зависимость, возможно, вы могли бы добавить один ответ в ответ, что он вам нужен.
Математики
2
hstspreload.org хочет, чтобы пользователь добавил `; includeSubDomains; preload` после значения max-age. параметры. Полная строка будет: <action type="Rewrite" value="max-age=31536000 ;includeSubDomains; preload" />чтобы получить пропуск на hstspreload.org
JP Hellemons
2
Группа перехвата R: 1 с шаблоном (. *) Соответствует всему URL, протоколу и всем, и попытка объединения {HTTP_HOST} / {R: 1} означает, что вы получаете, https://somedomain.com/https://somedomain.com/relatedpathи в результате путь отбрасывается.
AaronLS
38

Чтобы дополнить ответ voretaq7 , вы также можете сделать это с помощью файла Web.config (примечание: будет использоваться только для сайтов SSL, поскольку он добавит заголовок для ответов HTTP и HTTPS, что противоречит спецификации RFC 6797, пожалуйста, смотрите объяснение ниже) - добавьте блок следующим образом:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Strict-Transport-Security" value="max-age=31536000"/>
        </customHeaders>
    </httpProtocol>
</system.webServer>

Очевидно, у вас уже может быть system.webServerблок в вашем Web.config, так что добавьте это к этому, если так. Мы предпочитаем обрабатывать вещи в Web.config, а не в графическом интерфейсе, потому что это означает, что изменения конфигурации могут быть зафиксированы в нашем Git-репозитории.

Если вы хотите обработать перенаправление HTTP-SSL, как упомянул Грег Аскью , вам может быть проще сделать это с отдельным веб-сайтом в IIS. Вот как мы обрабатываем требование SSL для некоторых клиентских сайтов. Этот сайт содержит только перенаправление HTTP и некоторые исправления раскрытия информации , все в 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>

Это наше предпочтительное решение по нескольким причинам - мы можем легко регистрировать перенаправленный трафик отдельно (так как он находится в другом журнале IIS), он не включает больше кода в Global.asax.cs (у нас нет никакого кода там, что немного более удобно для сайта Umbraco), и, что важно, это означает, что весь конфиг все еще хранится в нашем репозитории GIT.

Отредактировано для добавления: Для ясности, чтобы соответствовать RFC 6797 , Strict-Transport-Securityпользовательский заголовок НЕ ДОЛЖЕН добавляться к запросам, сделанным по незашифрованному HTTP. Чтобы быть RFC6797-совместимым, вы ДОЛЖНЫ иметь два сайта в IIS, как я описал после первого блока кода. Как указывает Крис , RFC 6797 включает в себя:

Хост HSTS НЕ ДОЛЖЕН включать поле заголовка STS в ответы HTTP, передаваемые по незащищенному транспорту.

поэтому отправка Strict-Transport-Securityзаголовка клиента в ответ на запрос без SSL не будет соответствовать спецификации.

Оуэн Блэкер
источник
1
Чтобы добавить к ответу Оуэна Блэка, для IIS я использую URLScan 3.1 и хочу, чтобы он глобально удалил СЕРВЕР из ответа, установив RemoveServerHeader = 1, остальные параметры должны быть в каждом файле web.config сайта. Я предпочитаю это просто вычеркивать значение.
KeyOfJ
URLScan является очень распространенным решением и, я бы сказал, лучше, чем тот, который я предлагаю. Но это не всегда самое удобное решение: о)
Оуэн Блэкер
Важно отметить, что добавление этого на сайт с включенным протоколом HTTPS и HTTP (чтобы его можно было перенаправить) приведет к разрыву сайта! Вы получите 500 без информации, даже с CustomErrors Mode = "Off", без ошибок в журналах.
Крис Москини
@ChrisMoschini Я должен был прояснить, что первая строка Web.config должна относиться к сайту только для SSL.
Оуэн Блэкер
1
@ Ленн Скотт Хансельман написал более очень хорошее описание того, почему STS не принадлежит в заголовке при использовании HTTP. Подробнее здесь
Дэвид Йейтс
8

Я бы использовал пример из ссылки на Википедию, на которую вы ссылались, и выполнил действие в global.asax для сайта. Это позволяет перенаправить запрос на URL-адрес https, а затем вставить заголовок в ответ.

Это связано с тем, что заголовок HSTS должен игнорироваться, если его нет в ответе 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;
    }
}
Грег Аскью
источник
3

Кажется, это довольно надежный способ сделать это. Добавьте этот код в Global.asax - событие Application_BeginRequest запускается первым в жизненном цикле запроса Asp.net: http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest(v=vs. 110) .aspx

Согласно спецификации, http-запросы не должны отвечать заголовком, поэтому этот код добавляет его только для https-запросов. Максимальное время указывается в секундах, и, как правило, рекомендуется указывать здесь большое значение (IE - 31536000 указывает, что сайт будет использовать SSL только в течение следующих 365 дней).

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;
  }
}
erbz
источник
2

Используя пример, предоставленный Дугом Уилсоном, я создал следующие две функции PowerShell для добавления правил перезаписи URL для перенаправления в HTTPS и для добавления заголовков HSTS.

Они были протестированы в Windows 2012 и Windows 2012 R2.

Все, что вам нужно сделать, это указать название сайта. Вы можете по желанию дать правилам другое имя, если вам не нравятся значения по умолчанию.

Следует отметить, что в результате моего тестирования переменные сервера необходимо было добавить в список разрешений, прежде чем они будут включены в заголовки ответа. Функции делают это для вас.

РЕДАКТИРОВАТЬ: См. Ссылку на URL переписать для заголовков HTTP здесь: 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"

}
CarlR
источник
1

По словам создателей модуля IIS HTTP Strict Transport Security, простое добавление пользовательского заголовка не соответствует проекту спецификации (RFC 6797).

На самом деле вам нужно установить этот модуль IIS, чтобы включить HSTS на IIS 7.

Обновление 26 октября 2014 года : благодаря приведенному ниже комментарию я снова прочитал страницу модуля, в частности ту часть, которая оправдывает использование модуля вместо добавления пользовательских заголовков.

Хост HSTS НЕ ДОЛЖЕН включать поле заголовка STS в ответы HTTP, передаваемые по незащищенному транспорту.

Если вы уверены, что добавляете заголовки только в HTTPS, а НЕ в HTTP, вам не нужен этот модуль, и вы можете использовать ответ Дуга Уилсона. Не используйте ответ Оуэна Блэкера, потому что у него нет условия https.

Крис
источник
1
Так что некоторые другие ответы, которые только отправляют заголовок запросам HTTPS, также решают эту проблему? Или ваш модуль делает что-то другое / дополнительное, чего не делают другие решения?
Slolife
@slolife Я обновил свой ответ. Вы можете использовать код в ответе Дуга Уилсона. Вам не нужен этот модуль. Теперь я вижу, что это также обсуждается в комментариях к принятому ответу. Я не знаю, что этот модуль делает что-то другое, кроме других решений. Но я также не сделал исчерпывающую проверку исходного кода .
Крис
Мне следовало бы прояснить, что первый Web.config должен быть реализован на сайте только для SSL. Я отредактирую свой ответ, чтобы уточнить это.
Оуэн Блэкер
1

Это можно сделать, добавив следующий блок в Web.Config:

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name ="CustomName" value="MyCustomValue"/>
      </customHeaders>
    </httpProtocol>
</system.webServer>

Мы должны настроить IIS, который может настраивать заголовки для ответа:

  • Перейдите в диспетчер информационных служб Интернета (IIS).
  • Настройте заголовки ответа, которые добавляются к ответу от сервера.
  • Теперь добавьте свой пользовательский заголовок Name и пользовательское значение (пользовательские имя и значение заголовка должны быть такими же, как в Web.Config). Вы можете найти в блоге
Vinit
источник
0

Просто чтобы добавить, я вижу в комментариях 2 человека, говорящих о 500 ошибках, когда вы делаете это. У меня было это.

Если в IIS появляется ошибка 500, это может быть связано с тем, что вы добавили правило как на верхнем уровне, для наследуемого, так и на уровне сайта.

например

Default Web Site <- here
  Some Web Site <- here

IIS / Браузер, кажется, не дает вам никакой информации, что вы сделали это, независимо от ваших настроек обработки ошибок

Тони
источник