如何配置使用 HTTP 严格传输安全（HSTS）
HSTS https
HTTP 严格传输安全（HSTS）是一种安全功能，web 服务器通过它来告诉浏览器仅用 HTTPS 来与之通讯，而不是使用 HTTP。本文会说明如何在 Apache2、Nginx 和 Lighttpd 上如何启用 HSTS。在主流的 web 服务器上测试通过： Nginx 1.1.19、 Lighttpd 1.4.28 和 Apache 2.2.22 ，环境为 Ubuntu 12.04、 Debian 6 & 7 和 CentOS 6，只需要调整部分参数就可以工作在其它的发行版上。


![](/data/attachment/album/201504/14/142928nt90umljtulb8nte.gif)


### 什么是 HTTP 严格传输安全？


引用自 [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security)：



> 
> 如果一个 web 服务器支持 HTTP 访问，并将其重定向到 HTTPS 访问的话，那么访问者在重定向前的初始会话是非加密的。举个例子，比如访问者输入 http://www.foo.com/ 或直接输入 foo.com 时。
> 
> 
> 这就给了中间人攻击的一个机会，重定向可能会被破坏，从而定向到一个恶意站点而不是应该访问的加密页面。
> 
> 
> HTTP 严格传输安全（HSTS）功能使 Web 服务器告知浏览器绝不使用 HTTP 访问，在浏览器端自动将所有到该站点的 HTTP 访问替换为 HTTPS 访问。
> 
> 
> 


以下引自[维基百科](http://zh.wikipedia.org/wiki/HTTP%E4%B8%A5%E6%A0%BC%E4%BC%A0%E8%BE%93%E5%AE%89%E5%85%A8)：



> 
> HSTS 可以用来抵御 SSL 剥离攻击。SSL 剥离攻击是中间人攻击的一种，由 Moxie Marlinspike 于2009年发明。他在当年的黑帽大会上发表的题为 “New Tricks For Defeating SSL In Practice” 的演讲中将这种攻击方式公开。SSL剥离的实施方法是阻止浏览器与服务器创建HTTPS连接。它的前提是用户很少直接在地址栏输入https://，用户总是通过点击链接或3xx重定向，从HTTP页面进入HTTPS页面。所以攻击者可以在用户访问HTTP页面时替换所有https://开头的链接为http://，达到阻止HTTPS的目的。<sup class="reference" id="cite_ref-9"></sup>
> 
> 
> HSTS可以很大程度上解决SSL剥离攻击，因为只要浏览器曾经与服务器创建过一次安全连接，之后浏览器会强制使用HTTPS，即使链接被换成了HTTP。
> 
> 
> 另外，如果中间人使用自己的自签名证书来进行攻击，浏览器会给出警告，但是许多用户会忽略警告。HSTS解决了这一问题，一旦服务器发送了HSTS字段，用户将不再允许忽略警告。
> 
> 
> 


场景举例：



> 
> 当你通过一个无线路由器的免费 WiFi 访问你的网银时，很不幸的，这个免费 WiFi 也许就是由黑客的笔记本所提供的，他们会劫持你的原始请求，并将其重定向到克隆的网银站点，然后，你的所有的隐私数据都曝光在黑客眼下。
> 
> 
> 严格传输安全可以解决这个问题。如果你之前使用 HTTPS 访问过你的网银，而且网银的站点支持 HSTS，那么你的浏览器就知道应该只使用 HTTPS，无论你是否输入了 HTTPS。这样就防范了中间人劫持攻击。
> 
> 
> 


注意，如果你之前没有使用 HTTPS 访问过该站点，那么 HSTS 是不奏效的。网站需要通过 HTTPS 协议告诉你的浏览器它支持 HSTS。


服务器开启 HSTS 的方法是，当客户端通过HTTPS发出请求时，在服务器返回的 HTTP 响应头中包含 `Strict-Transport-Security` 字段。非加密传输时设置的HSTS字段无效。


### 在 Apache2 中设置 HSTS


编辑你的 apache 配置文件（如 `/etc/apache2/sites-enabled/website.conf` 和 `/etc/apache2/httpd.conf ），并加以下行到你的 HTTPS` VirtualHost：



```
# Optionally load the headers module:
LoadModule headers_module modules/mod_headers.so

<VirtualHost 67.89.123.45:443>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
</VirtualHost>

```

现在你的 web 站点在每次访问时都会发送该请求头，失效时间是两年（秒数）。这个失效时间每次都会设置为两年后，所以，明天你访问时，它会设置为明天的两年后。


你只能在 HTTPS 虚拟机中设置这个头，而不能设置在 HTTP 虚拟机中。


要将你的访问者重定向到对应 HTTPS 站点，可使用如下设置：



```
<VirtualHost *:80>
  [...]
  ServerName example.com
  Redirect permanent / https://example.com/
</VirtualHost>

```

如果仅仅是做重定向的话，甚至不需要设置 DocumentRoot。


你也可以使用 mod\_rewrite 来做重定向，但是上述的方式更简单更安全。不过，mod\_rewrite 可以重定向页面到对应的 HTTPS 页面，而上述配置则只重定向到“/”：



```
<VirtualHost *:80>
  [...]
  <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
  </IfModule>
</VirtualHost>

```

不要忘记重启 Apache。


### Lighttpd


对于 lighttpd 来说很简单，将下述配置增加到你的 Lighttpd 配置文件（例如：`/etc/lighttpd/lighttpd.conf）：`



```
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
    setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload")
}

```

重启 Lighttpd。失效时间也是两年。


### Nginx


Nginx 甚至更简单，将下述行添加到你的 HTTPS 配置的 server 块中：



```
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

```

不要忘记重启 Nginx。


OK
[Skip to main content](#main)

#
[Raymii.org
](https://raymii.org/s/)


Quis custodiet ipsos custodes?[Home](/s/)|

[About](/s/static/About.html)|

[All pages](/s/tags/all.html)|

[Cluster Status](/s/software/Sparkling_Network.html)|

[RSS Feed](https://raymii.org/s/feed.xml)


## HTTP Strict Transport Security for Apache, NGINX and Lighttpd

Published: 17-06-2016 | Author: Remy van Elst | [Text only version of this article](HTTP_Strict_Transport_Security_for_Apache_NGINX_and_Lighttpd.txt)

**❗ This post is over eight years old. It may no longer be up to date. Opinions may have changed.**

### Table of Contents

HTTP Strict Transport Security (often abbreviated as HSTS) is a security feature that lets a web site tell browsers that it should only be communicated with using HTTPS, instead of using HTTP. This tutorial will show you how to set up HSTS in Apache2, NGINX and Lighttpd. It is tested with all mentioned webservers, NGINX 1.1.19, Lighttpd 1.4.28 and Apache 2.2.22 on Ubuntu 12.04, Debian 6 & 7 and CentOS 6.It should work on other distro's however, these are just reference values.

**Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:**

[I'm developing an open source monitoring app called Leaf Node Monitoring, for windows, linux & android. Go check it out!](https://leafnode.nl)

[Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.](https://github.com/sponsors/RaymiiOrg/)

[You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $200 credit for 60 days. Spend $25 after your credit expires and I'll get $25!](https://www.digitalocean.com/?refcode=7435ae6b8212)


### What is HTTP Strict Transport Security?

Quoting the [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security):

```
If a web site accepts a connection through HTTP and redirects to HTTPS, the user in this case may initially talk to the non-encrypted version of the site before being redirected, if, for example, the user types http://www.foo.com/ or even just foo.com.
This opens up the potential for a man-in-the-middle attack, where the redirect could be exploited to direct a user to a malicious site instead of the secure version of the original page.
The HTTP Strict Transport Security feature lets a web site inform the browser that it should never load the site using HTTP, and should automatically convert all attempts to access the site using HTTP to HTTPS requests instead.
```


An example scenario:

```
You log into a free WiFi access point at an airport and start surfing the web, visiting your online banking service to check your balance and pay a couple of bills. Unfortunately, the access point you're using is actually a hacker's laptop, and they're intercepting your original HTTP request and redirecting you to a clone of your bank's site instead of the real thing. Now your private data is exposed to the hacker.
Strict Transport Security resolves this problem; as long as you've accessed your bank's web site once using HTTPS, and the bank's web site uses Strict Transport Security, your browser will know to automatically use only HTTPS, which prevents hackers from performing this sort of man-in-the-middle attack.
```


*Do note that HSTS does not work if you've never visited the website before.* A
website needs to tell you it is HTTPS only.

### Important regarding preload

In the below configuration the `preload`

directive was used. As requested by
Lucas Garron from Google I removed it since most people seem to do screw it up.

Please note that that ```
THE PRELOAD DIRECTIVE WILL HAVE SEMI-PERMANENT
CONSEQUENCE
```

. If you are testing, screw up or don't want to use HSTS anymore you
might be on the preload list.

It is important that you understand what you are doing and that you understand
that the preload directive means that it will end up in browsers. If your HTTPS
configuration is wrong, broken or you don't want to use HTTPS anymore, you will
experience problems. [See this page](https://hstspreload.appspot.com/) as well.

If you still want to use `preload`

, just append it to the header after the semi-
colon.

### Set up HSTS in Apache2

Edit your apache configuration file (`/etc/apache2/sites-enabled/website.conf`

and `/etc/apache2/httpd.conf`

for example) and add the following to your
VirtualHost:

```
# Optionally load the headers module:
LoadModule headers_module modules/mod_headers.so
<VirtualHost 67.89.123.45:443>
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
</VirtualHost>
```


Now your website will set the header every time someone visits, with an
expiration date of two years (in seconds). It sets it at every visit. So
tomorrow, it will say two years again.

You do have to set it on the HTTPS vhost only. It cannot be in the http vhost.

To redirect your visitors to the HTTPS version of your website, use the following configuration:

```
<VirtualHost *:80>
[...]
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
```


If you only redirect, you dont even need a document root.

You can also use mod *rewrite, however the above method is simpler and safer.
However, mod* rewrite below redirects the user to the page they were visiting
over https, the above config just redirects to /:

```
<VirtualHost *:80>
[...]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</IfModule>
</VirtualHost>
```


And don't forget to restart Apache.

### Lighttpd

The lighttpd variant is just as simple. Add it to your Lighttpd configuration
file (`/etc/lighttpd/lighttpd.conf`

for example):

```
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; ")
}
```


And restart Lighttpd. Here the time is also two years.

### NGINX

NGINX is even shorter with its config. Add this in the `server`

block for your
HTTPS configuration:

```
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; ";
```


Don't forget to restart NGINX.

### X-Frame-Options header

The last tip I'll give you is the X-Frame-Options header, which you can add to your HTTPS website to make sure it is not embedded in a frame or iframe. This avoids clickjacking, and might be helpfull for HTTPS websites. Quoting the [Mozilla Developer Network again](https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options):

```
The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a `<frame>` or `<iframe>`. Sites can use this to avoid clickjacking attacks, by ensuring that their content is not embedded into other sites.
```


You can change DENY to SAMEORIGIN or ALLOW-FROM uri, see the Mozilla link above
for more information on that. (Or the [RFC](http://tools.ietf.org/html/rfc7034).)

#### X-Frame-Options for Apache2

As above, add this to the apache config file:

```
Header always set X-Frame-Options DENY
```


### Lighttpd

This goes in the lighttpd config. Make sure you don't double the above set config, if you have that, just add the rule it to it.

```
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
setenv.add-response-header = ( "X-Frame-Options" => "DENY")
}
```


#### NGINX

Yet again, in a `server`

block:

```
add_header X-Frame-Options "DENY";
```


Tags: [apache](../tags/apache.html),

[hsts](../tags/hsts.html),

[https](../tags/https.html),

[lighttpd](../tags/lighttpd.html),

[nginx](../tags/nginx.html),

[security](../tags/security.html),

[ssl](../tags/ssl.html),

[tls](../tags/tls.html),

[tutorials](../tags/tutorials.html)