在看過基礎概念與性能管理後,SSL設置也隨之到來,儘管可能準備的不盡人意,但是儘量使得內容足以解惑。
SSL 和 TLS
SSL(Socket Secure Layer 縮寫)是一種通過 HTTP 提供安全連接的協議。
SSL 1.0 由 Netscape 開發,但由於嚴重的安全漏洞從未公開發布過。SSL 2.0 於 1995 年發佈,它存在一些問題,導致了最終的 SSL 3.0 在 1996 年發佈。
TLS(Transport Layer Security 縮寫)的第一個版本是作爲 SSL 3.0 的升級版而編寫的。之後 TLS 1.1 和 1.2 出來了。現在,就在不久之後,TLS 1.3 即將推出(這確實值得期待),並且已經被一些瀏覽器所支持。
從技術上講,SSL 和 TLS 是不同的(因爲每個協議都描述了協議的不同版本),但其中使用的許多名稱是可以互換的。
基本 SSL/TLS 配置
爲了處理 HTTPS 流量,你需要具有 SSL/TLS 證書。你可以通過使用 Let’s encrypt 以生成免費的證書。
當你擁有證書之後,你可以通過以下的方式輕易切換至 HTTPS:
- 開始監聽端口 443(當你輸入 https://sample.co 時瀏覽器將使用的默認端口)
- 提供證書及其密鑰
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/ssl/netguru.crt;
ssl_certificate_key /etc/nginx/ssl/netguru.key;
}
我們也想通過調整配置實現:
-
僅使用 TLS 協議。由於衆所周知的漏洞,所有的 SSL 版本都將不再使用
-
使用預定義的安全的服務器密碼(類似於協議的情況 – 那些日子只有少數密碼被認爲是安全的)
設置總在變化,時不時更新總是好的
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!MD5;
ssl_prefer_server_ciphers on;
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/ssl/netguru.crt;
ssl_certificate_key /etc/nginx/ssl/netguru.key;
}
TLS 會話恢復
使用 HTTPS,在 TCP 之上需要增加 TLS 握手。這大大增加了此前實際數據傳輸的時間。假設你從華沙請求 /image.jpg,並接入到柏林最近的服務器:
爲了在 TLS 握手期間節省一個 roundtrip 時間,以及生成新密鑰的計算開銷,我們可以重用在第一個請求期間生成的會話參數。客戶端和服務器可以將會話參數存儲在會話 ID 密鑰的後面。在接下來的 TLS 握手過程中,客戶端可以發送會話 ID,如果服務器在緩存中仍然有正確的條目,那麼會重用前一個會話所生成的參數。
server {
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;#超時時間
}
OCSP Stapling
SSL 證書可以隨時撤銷。瀏覽器爲了知道給定的證書是否不再有效,需要通過在線證書狀態協議 (Online Certificate Status Protocol ,OCSP) 執行額外的查詢。無需用戶執行指定的 OCSP 查詢,我們可以在服務器上執行此操作,緩存其結果,並在 TLS 握手期間爲客戶端提供 OCSP 響應。它被稱爲OCSP stapling
server {
ssl_stapling on;
ssl_stapling_verify on; # verify OCSP response
ssl_trusted_certificate /etc/nginx/ssl/lemonfrog.pem; # tell nginx location of all intermediate certificates,自己證書的位置
resolver 8.8.8.8 8.8.4.4 valid=86400s; # resolution of the OCSP responder hostname
resolver_timeout 5s;
}
Security headers
有一些標頭確實值得調整以提供更高的安全性。有關更多關於標頭及其詳細信息,你絕對應該查看OWASP 項目之安全標頭。
HTTP Strict-Transport-Security(HSTS)
簡稱 HSTS,強制用戶代理在向源發送請求時使用 HTTPS。
語法如下:
Strict-Transport-Security: <max-age=>[; includeSubDomains][; preload]
Strict-Transport-Security: <max-age=>[; includeSubDomains][; preload]
示例: add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
- max-age是必選參數,是一個以秒爲單位的數值,它代表着HSTS Header的過期時間,通常設置爲1年,即31536000秒。
- includeSubDomains是可選參數,如果包含它,則意味着當前域名及其子域名均開啓HSTS保護。
- preload是可選參數,只有當你申請將自己的域名加入到瀏覽器內置列表的時候才需要使用到它。關於瀏覽器內置列表,點擊上面超鏈接進入並配置。
X-Frame-Options
表示瀏覽器是否需要在一幀、一個 iframe 或一個對象標籤中渲染頁面
add_header X-Frame-Options DENY;
(1)DENY --- 表示該頁面不允許在 frame 中展示,即便是在相同域名的頁面中嵌套也不允許。
(2)SAMEORIGIN --- 表示該頁面可以在相同域名頁面的 frame 中展示。
(3)ALLOW-FROM https://example.com/ --- 表示該頁面可以在指定來源的 frame 中展示。
X-Content-Type-Options
此選項將阻止瀏覽器在判斷文件類型時嗅探文件。文件將會按照 Content-Type 頭中聲明的格式轉譯。
add_header X-Content-Type-Options nosniff;
如果服務器發送響應頭 “X-Content-Type-Options: nosniff”,則 script 和 styleSheet 元素會拒絕包含錯誤的 MIME 類型的響應。這是一種安全功能,有助於防止基於 MIME
類型混淆的攻擊。
Server tokens
另一個很好的做法是在 HTTP 響應頭字段中隱藏有關 Web 服務器的信息:不然會出現:
Server : nginx/1.18.2
我們需要如下去隱藏版本號以防安全
server_tokens off;
CORS配置
項目中額外需要配置跨站請求,先了解一下配置屬性意義:
Access-Control-Allow-Origin
(必含):允許的域名,只能填通配符或者單域名
Access-Control-Allow-Methods
(必含):允許跨域請求的 http 方法
Access-Control-Allow-Headers
:返回支持的 http 請求頭
Access-Control-Allow-Credentials
(可選):標誌着當前請求是否包含 cookies 信息,布爾值。只有一個可選值:true,如果不包含 cookies,請略去該項,而不是填 false。這一項與XmlHttpRequest2 對象當中的 withCredentials 屬性應保持一致,即 withCredentials 爲true時該項也爲 true;withCredentials爲false時,省略該項不寫。反之則導致請求失敗。
Access-Control-Max-Age
(可選):以秒爲單位的緩存時間,用於緩存預檢請求。
如下填入nginx配置即可,個性化根據個人而已稍作修改
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Accept, Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' *;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PUT, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Accept, Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}