Netcraft 公司最近公布了他們檢測SSL/TLS網站的研究,並指出只有僅僅5%的用戶正確執行了HTTP嚴格傳輸安全HSTS。本文介紹nginx如何配置HSTS。
什麼是HSTSHTTPS(SSL和TLS)確保用戶和網站通訊過程中安全,使攻擊者難於攔截、修改和假冒。當用戶手動輸入域名或http://連結,該網站的第一個請求是未加密的,使用普通的http。最安全的網站立即發送回一個重定向使用戶引向到https連接,然而,中間人攻擊者可能會攻擊攔截初始的http請求,從而控制用戶後續的回話。
自然而然HSTS應運而生為了解決這一潛在的安全問題。即時用戶輸入域名或http連接,瀏覽器將嚴格的升級到https連接。
HSTS如何工作的HSTS策略是從安全的HTTPS站點發送的HTTP響應頭部發布的。
1
Strict-Transport-Security: max-age=31536000
當瀏覽器從HTTPS站點看到這個頭部,就知道該域名只能通過HTTPS(SSL 或者 TLS)訪問了。並將此信息緩存到31536000,也就是1年。
可選的參數includeSubDomains告訴瀏覽器該策略適用於當前域下的所有子域。
1
Strict-Transport-Security: max-age=31536000; includeSubDomains
nginx配置HSTS在nginx配置文件上設置HSTS響應頭部。
1
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
always 參數確保所有的響應設置該頭部,包括內部產生的錯誤響應。nginx版本早於1.7.5不支持該always參數和內部產生的錯誤響應不設置該頭部信息。
add_header指令繼承規則:
nginx配置塊繼承add_header指令所在的封裝塊,因此只需將add_header指令放在頂級的server塊。此外還有個重要的例外,如果一個塊包含了add_header指令本身,它不會從封裝塊繼承該頭部,你需要重新定義所有的add_header指令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 443 ssl;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# This 'location' block inherits the STS header
location / {
root /usr/share/nginx/html;
}
# Because this 'location' block contains another 'add_header' directive,
# we must redeclare the STS header
location /servlet {
add_header X-Served-By "My Servlet Handler";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
proxy_pass http://localhost:8080;
}
}
測試HTTP嚴格傳輸安全:
一旦用戶提出HSTS策略,它的緩存信息期由max-age指定。在此期間,瀏覽器將會拒絕通過未加密的HTTP訪問web服務,並拒絕給予例外證書錯誤(如果該網站以前提交了一個有效可信的證書)。如果指定了一個includeSubDomanis參數,這些限制也同樣適用於當前域下的所有子域。
當你測試HSTS時,max-age時間設置短點。
是否每個HTTPS響應需要有一個STS頭部:
我們的目標是當用戶開始HTTPS回話時,儘可能快的呈現HSTS策略。如果他們在回話期間接收到HSTS策略,他們仍然容易受到HTTP劫持攻擊的。瀏覽器只需查看一次STS頭部,因此它不是嚴格必要將它添加到每個位置塊和每個響應。然而,只在主頁或者登陸頁面添加它可能是不夠的,如果你只添加到緩存的響應,客戶端可能無法看到它。確保儘可能多的合理的覆蓋到你的URL,特別注意動態的內容。
HTTP和HTTPS並行有時網站需要同時運行在HTTP和HTTPS下
1
2
3
4
5
server {
listen 80;
listen 443 ssl;
...
}
有時,需要將http請求重定向到https
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Discourage deep links by using a permanent redirect to home page of HTTPS site
return 301 https://$host;
# Alternatively, redirect all HTTP links to the matching HTTPS page
# return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name www.ttlsa.com;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
加強HSTS保護客戶端從HTTP攔截,從它看到STS頭部到聲明的max-age的期間內。然而,HSTS並不是HTTP回話劫持的完美解決方案。用戶仍然容易受到攻擊,如果他們通過HTTP訪問HSTS保護的網站時:
以前從未訪問過該網站
最近重新安裝了其作業系統
最近重新安裝了其瀏覽器
切換到新的瀏覽器
切換到一個新的設備如行動電話
刪除瀏覽器的緩存
最近沒訪問過該站並且max-age過期了
為了解決這個問題,google堅持維護了一個「HSTS preload list」的站點域名和子域名,並通過https://hstspreload.appspot.com/提交其域名。該域名列表被分發和硬編碼到主流的web瀏覽器。客戶端訪問此列表中的域名將主動的使用HTTPS,並拒絕使用HTTP訪問該站點。
一旦設置了STS頭部或者提交了你的域名到HSTS預加載列表,這是不可能將其刪除的。這是一個單向的決定使你的域名通過HTTPS可用的。