NGINX的SSL TLS與Security Header的安全性強化
前一篇,在取得 NGINX 可用的憑證格式與套用後,就開始以 HTTPS 來連線與測試。但 nginx.conf
裡還有許多安全性設定值可以調整。
- NGINX HTTP Server 組態
- SSL/TLS 組態
- Security Header 組態
以下是我目前與安全性有關的設定值:
http {
server_tokens off;
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name kkbruce.net;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_dhparam dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_session_tickets off;
ssl_stapling off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Cross-Origin-Opener-Policy same-origin;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
location / {
root html;
index index.html index.htm;
}
}
}
注意,請依你的使用環境進行細部調整。
NGINX http 安全性強化
http {
# 隱藏 nginx 版本資訊,防止洩漏攻擊資訊
server_tokens off;
}
原本會帶版本號的 HTTP Header,變成只會帶伺服器名稱,例如:
server: nginx
SSL/TLS 組態安全性強化
server {
// 省略
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
ssl_dhparam dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_session_tickets off;
ssl_stapling off;
}
詳細說明可以參考上面兩篇官方文件。以下是簡單說明。
啟用NGINX的HTTP/2
都已經上到 HTTPS 了,不用 HTTP/2 實在太可借了。
listen 443 ssl http2;
在網路上,大多數會查詢到以上語法,當 nginx reload
組態時會看到以下 warn
,但不影響 HTTP/2 的啟用。
[warn] 14564#31588: the "listen ... http2" directive is deprecated, use the "http2" directive instead in C:\Tools\nginx/conf/nginx.conf:466
NGINX 1.25.1 之後提供新的 http2 on;
指令,因此就改為以下設定方式:
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
啟用NGINX的HTTP/3
注意:HTTP/3 僅支援 TLSv1.3。
listen 443 quic reuseport;
location / {
add_header Alt-Svc 'h3=":443"; ma=86400';
root html;
index index.html index.htm;
}
如果你在 NGINX for Windows 套用會得到以下錯誤:「[emerg] 28092#37880: the "quic" parameter requires ngx_http_v3_module in C:\nginx/conf/nginx.conf:472」,官方文件有說:「Support for QUIC and HTTP/3 protocols is available since 1.25.0. Also, since 1.25.0, the QUIC and HTTP/3 support is available in Linux binary packages.」只好再等等,等我回到 NGINX (Linux)的那一天(苦笑)。
ssl_
組態安全性強化
# Diffie-Hellman(DH)金鑰交換機制提供額外的安全性
ssl_dhparam dhparam.pem;
# 啟用快取,提高 TLS 效能
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# 停用 TLS 1.0 / 1.1,提高安全性
ssl_protocols TLSv1.2 TLSv1.3;
# 使用安全的加密演算法
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# 禁用 Session Tickets,防止密鑰重複使用
ssl_session_tickets off;
# 停用 OCSP Stapling,啟用需要額外設定與憑證供應商的支援,僅影響驗證效能,不影響安全性。
# 內網環境不需要可停用。
ssl_stapling off;
注意,dhparam
可以利用 WSL 的 OpenSSL 來手動產生,產生後複製到 NGINX 的 conf
目錄下。
openssl dhparam -out dhparam.pem 4096
另外,ssl_ciphers
我是參考在 Linux 上使用 Nginx 裝載 ASP.NET Core文件裡面的設定值,請依你的需要調整。
Security Header 安全性強化
Security Header 主要防禦來自 Web 攻擊。以下有兩個很好的參考資料:
# 指示文件是否能夠透過 <frame>、<iframe> 以及 <object> 載入。
# SAMEORIGIN 唯有當符合同源政策下,才能被嵌入到 frame 中。
add_header X-Frame-Options SAMEORIGIN;
# 當瀏覽器偵測到 XSS 攻擊時,會阻擋頁面載入。
add_header X-XSS-Protection "1; mode=block";
# 當瀏覽器偵測到 MIME 類型不正確時,會阻擋頁面載入。
add_header X-Content-Type-Options nosniff;
### https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Guides/Cross-Origin_Resource_Policy
# same-origin: 只有來自相同來源(即方案 + 主機 + 通訊埠)的請求可以讀取資源。
add_header Cross-Origin-Opener-Policy same-origin;
#add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://apis.example.com";
# Strict-Transport-Security (HSTS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
可以注意到 Content-Security-Policy
我是註解掉的,因為它的設定與測試比較麻煩與複雜。一樣請讀者自行評估。
這些選項值不是絕對值,例如,X-Frame-Options
與 X-XSS-Protection
都還有其他選項值,每種選項值作用不同,因此請自行評估那組選項值符合你的需求。
補充一份找到不錯的參考資料:https://docsaid.org/docs/nginx-notes/security/
小結:注意 TLS 1.2
目前測起來只有 ssl_protocols TLSv1.2 TLSv1.3;
這組設定比較可能讓你的應用程式壞掉,但關閉 TLS 1.0 與 TLS 1.1 是趨勢,要修正其實也不難,以 ASP.NET Core 應用程式為例,可以在 Program.cs
為 Kestrel
加上以下組態,讓 HTTPS 之間走 TLS 1.2 協定。
// Setup Kestrel to use TLS 1.2
builder.WebHost.UseKestrel(kestrelOptions =>
{
kestrelOptions.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.SslProtocols = SslProtocols.Tls12;
});
});
一般 .NET 應用程式,可能要在適當的地方加上以下組態:
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
其他程式語言應該都有對應 TLS 1.2 的設定,大家在伺服器端導入 TLS 1.2 組態後,記的用戶端也要進行對應的設定。
沒有留言:
張貼留言
感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。