1. 程式人生 > 實用技巧 >nginx 配置HTTPS併兼容HTTP(強制轉發)

nginx 配置HTTPS併兼容HTTP(強制轉發)

使用 OpenSSL 生成 SSL Key 和 CSR 檔案

配置 HTTPS 要用到私鑰 example.key 檔案和 example.crt 證書檔案,申請證書檔案的時候要用到 example.csr 檔案,OpenSSL命令可以生成 example.key 檔案和 example.csr 證書檔案。

  • CSR:Cerificate Signing Request,證書籤署請求檔案,裡面包含申請者的 DN(Distinguished Name,標識名)和公鑰資訊,在第三方證書頒發機構簽署證書的時候需要提供。證書頒發機構拿到 CSR 後使用其根證書私鑰對證書進行加密並生成 CRT 證書檔案,裡面包含證書加密資訊以及申請者的 DN 及公鑰資訊
  • Key:證書申請者私鑰檔案,和證書裡面的公鑰配對使用,在 HTTPS 『握手』通訊過程需要使用私鑰去解密客戶端發來的經過證書公鑰加密的隨機數資訊,是 HTTPS 加密通訊過程非常重要的檔案,在配置 HTTPS 的時候要用到

使用OpenSSl命令可以在系統當前目錄生成example.key和example.csr檔案:

1
openssl req -new -newkey rsa:2048 -sha256 -nodes -out example_com.csr -keyout example_com.key -subj "/C=CN/ST=ShenZhen/L=ShenZhen/O=Example Inc./OU=Web Security/CN=example.com"

下面是上述命令相關欄位含義:

  • C:Country ,單位所在國家,為兩位數的國家縮寫,如: CN 就是中國
  • ST 欄位: State/Province ,單位所在州或省
  • L 欄位: Locality ,單位所在城市 / 或縣區
  • O 欄位: Organization ,此網站的單位名稱;
  • OU 欄位: Organization Unit,下屬部門名稱;也常常用於顯示其他證書相關資訊,如證書型別,證書產品名稱或身份驗證型別或驗證內容等;
  • CN 欄位: Common Name ,網站的域名;

生成 csr 檔案後,提供給 CA 機構,簽署成功後,就會得到一個example.crt證書檔案,SSL 證書檔案獲得後,就可以在 Nginx 配置檔案裡配置 HTTPS 了。

配置 HTTPS

基礎配置

要開啟 HTTPS 服務,在配置檔案資訊塊(server block),必須使用監聽命令listen的 ssl 引數和定義伺服器證書檔案和私鑰檔案,如下所示:

server {
#ssl引數
listen 443 ssl;
server_name example.com;
#證書檔案
ssl_certificate example.com.crt;
#私鑰檔案
ssl_certificate_key example.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
#...
}

證書檔案會作為公用實體傳送到每臺連線到伺服器的客戶端,私鑰檔案作為安全實體,應該被存放在具有一定許可權限制的目錄檔案,並保證 Nginx 主程序有存取許可權。

私鑰檔案也有可能會和證書檔案同放在一個檔案中,如下面情況:

ssl_certificate     www.example.com.cert;
ssl_certificate_key www.example.com.cert;

這種情況下,證書檔案的的讀取許可權也應該加以限制,僅管證書和私鑰存放在同一個檔案裡,但是隻有證書會被髮送到客戶端

命令ssl_protocolsssl_ciphers可以用來限制連線只包含 SSL/TLS 的加強版本和演算法,預設值如下:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;

由於這兩個命令的預設值已經好幾次發生了改變,因此不建議顯性定義,除非有需要額外定義的值,如定義 D-H 演算法:

#使用DH檔案
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#定義演算法
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
#...

HTTP強制轉HTTPS

另外配置一個server塊,監聽80埠,再加上rewrite。

server {  
    listen  80;
    server_name 伺服器ip;      
    rewrite ^(.*)$  https://$host$1 permanent; #http強制轉https
}

server配置參考

server {  
    listen  80;
    server_name 伺服器ip;      
    rewrite ^(.*)$  https://$host$1 permanent; #http強制轉https
}
server {
    charset utf-8;              #伺服器編碼
    listen 443;            #監聽地址
    server_name 伺服器ip;   #證書繫結的網站域名
    server_tokens off;          #隱藏nginx版本號
   
    #ssl配置
    ssl on;
    ssl_certificate   /etc/ssl/certs/nginx-selfsigned.crt;  #證書公鑰
    ssl_certificate_key  /etc/ssl/private/nginx-selfsigned.key;    #證書私鑰
    ssl_session_timeout 5m;
    ssl_ciphers  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;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers off;
    ssl_dhparam /etc/nginx/dhparams.pem;   

    #請求頭
    add_header Strict‐Transport‐Security max‐age=63072000;
    add_header X-Frame-Options SAMEORIGIN;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
    add_header Set-Cookie "HttpOnly";
    add_header Set-Cookie "Secure";
   
    #請求方法限制
    ## Only allow these request methods ##
     if ($request_method !~ ^(GET|POST|DELETE|PUT|PATCH)$ ) {
         return 444;
     }
    
    #訪問路徑匹配
    location / {
        root /usr/share/nginx/html; #站點目錄
           index index.html index.htm;
    }
   location /test/ {
          proxy_pass http://127.0.0.1:8100/; #轉發本地埠8100
   }
 
   #禁止訪問路徑
   # location /dirdeny {
   #     deny all;
   #     return 403;
   #}

   #錯誤頁面配置
   error_page    502 503 504  /error502.html;
       location = /error502.html{
        root /usr/share/nginx/html;
    }
   error_page    500 /error.html;
     location = /error.html{
            root /usr/share/nginx/html;
        }
   error_page    404 /notfind.html;
     location = /notfind.html{
            root /usr/share/nginx/html;
        }
}