SSL/TLS 現代化設定指南

在建置現代網站與 API 伺服器時,HTTPS(SSL/TLS 加密傳輸)早已不是選配,而是現代網路通訊的絕對標配。未啟用 HTTPS 的網站不僅會被主流瀏覽器標記為「不安全」,還會嚴重影響搜尋引擎排名(SEO)並將使用者機敏資料暴露於中間人攻擊(MITM)的風險中。

無論你是要申請企業級商業憑證(OV/EV)、搭建內網服務、測試環境自簽憑證,還是使用自動化憑證,掌握 OpenSSL 的底層原理 以及 Nginx、Apache 的現代化設定,都是每位系統工程師不可或缺的基礎功。


一、SSL/TLS 憑證核心三要素

在開始操作前,必須先搞清楚三個核心檔案的職責與關係:

  1. 私鑰(Private Key,.key):伺服器的最高機密。用於解密客戶端傳送的對稱金鑰與數位簽章,絕對不能外流。
  2. 憑證簽署請求(CSR, Certificate Signing Request,.csr):包含你的公鑰以及組織資訊(網域名稱、公司、國家)。這是送交給憑證授權單位(CA, Certificate Authority)用來申請憑證的申請表。
  3. 數位憑證(Certificate,.crt 或 .pem):由 CA 驗證你的 CSR 後,用 CA 自身的私鑰簽署發給你的身分證明文件,包含你的公鑰與有效期限。

二、使用 OpenSSL 產生金鑰、CSR 與自簽憑證

1. 產生 RSA 私鑰

在終端機執行以下指令產生 2048 位元的 RSA 私鑰:

openssl genrsa -out example.com.key 2048

注意:為什麼不要對私鑰設密碼(Passphrase)? 如果在產生時加上 -des3 設定了密碼,未來每次伺服器重新啟動或 reload Nginx/Apache 時,終端機都會卡住要求輸入密碼,導致無人值守的伺服器重啟失敗。 若私鑰原本有加密,可用以下指令解除密碼保護:

openssl rsa -in example.com_secure.key -out example.com.key

2. 設定嚴格的私鑰存取權限

私鑰必須只允許伺服器擁有者(通常是 root)讀取,避免伺服器上其他受限程式存取:

sudo chown root:root example.com.key
sudo chmod 600 example.com.key

3. 產生憑證簽署請求(CSR)

拿著私鑰生成 CSR,準備提交給商業 CA 審核:

openssl req -new -key example.com.key -out example.com.csr

系統會詢問國家(Country)、省份、城市、組織名稱,其中最關鍵的是 Common Name (e.g. server FQDN),必須填入你的完整網域名稱(例如 example.com 或 *.example.com)。

4. (本地開發/測試用)產生自簽憑證(Self-Signed Certificate)

如果是開發測試環境或內部私有網路,不需要花錢購買 CA 憑證,可直接用一行指令同時產生私鑰與自簽憑證(有效期限 365 天):

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout example.com.key \
  -out example.com.crt \
  -subj "/CN=example.com"

三、Nginx 現代化 HTTPS 設定

在早期的 Nginx 教學中,常看到 ssl on; 這種寫法。請注意:ssl on; 在現代 Nginx 中已被廢棄並移除!

1. 現代 Nginx 標準設定檔

在 /etc/nginx/sites-available/example.com 中加入以下設定:

# 1. 將所有 HTTP (Port 80) 流量強制轉址至 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

# 2. HTTPS (Port 443) 伺服器區塊
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    # 若支援 HTTP/2,Nginx 1.25.1+ 可使用: http2 on; 
    # 舊版則在 listen 後加上 http2: listen 443 ssl http2;

    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html index.php;

    # 憑證與私鑰路徑
    ssl_certificate /etc/ssl/certs/example.com_bundle.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    # 現代化 SSL/TLS 安全通訊協定設定
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # 憑證快取加速
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    location / {
        try_files $uri $uri/ =404;
    }
}

關鍵防坑點:中繼憑證鏈(Certificate Chain / Bundle)

當你向商業 CA 購買憑證時,CA 通常會提供兩個檔案:你的網域憑證(domain.crt)與中繼憑證(intermediate.crt)。 Nginx 的 ssl_certificate 必須包含完整的憑證鏈! 若只放網域憑證,Android、手機瀏覽器或 curl 會報錯 unable to get local issuer certificate。

  • 正確做法:將網域憑證與中繼憑證合併為一個 bundle 檔(順序:自己的憑證在最上方,中繼憑證在下方):
    cat example.com.crt intermediate.crt > example.com_bundle.crt

四、Apache 現代化 HTTPS 設定

在 Apache 伺服器上,需先確認已啟用 SSL 模組:

sudo a2enmod ssl
sudo a2enmod headers

1. Apache VirtualHost 設定

編輯 /etc/apache2/sites-available/example.com-ssl.conf:

# 1. HTTP 自動 301 轉址到 HTTPS
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com

    Redirect permanent / https://example.com/
</VirtualHost>

# 2. HTTPS 主機設定
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com

    SSLEngine on

    # 憑證與私鑰路徑(Apache 2.4.8+ 中,SSLCertificateFile 已支援包含中繼鏈的 fullchain 檔案)
    SSLCertificateFile /etc/ssl/certs/example.com_bundle.crt
    SSLCertificateKeyFile /etc/ssl/private/example.com.key

    # 舊版 Apache (2.4.7 以前) 若分開提供中繼憑證,才需要以下設定:
    # SSLCertificateChainFile /etc/ssl/certs/intermediate.crt

    # 停用老舊不安全的協定(僅允許 TLS 1.2 與 1.3)
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLHonorCipherOrder on

    <Directory /var/www/example.com>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

五、現代公開網站的首選:Let’s Encrypt 自動化

如果你架設的是公開對外的正式網站,且不需要特定組織驗證(OV/EV)的企業認證,目前全球業界最普遍的標準是使用 Let’s Encrypt 搭配 Certbot。

它能將上述產生金鑰、申請憑證、設定 Nginx/Apache 以及自動續約(每 90 天)全部一鍵自動化:

# Ubuntu / Debian 安裝 Certbot
sudo apt update && sudo apt install -y certbot python3-certbot-nginx

# 一鍵為 Nginx 申請並自動配置憑證
sudo certbot --nginx -d example.com -d www.example.com

# 測試自動續約排程(systemd timer 會自動處理)
sudo certbot renew --dry-run

六、檢驗與除錯指令

完成配置後,記得先驗證設定檔語法,再重啟 Web 服務:

  • Nginx 語法檢查與重啟:
    sudo nginx -t
    sudo systemctl reload nginx
  • Apache 語法檢查與重啟:
    sudo apache2ctl configtest
    sudo systemctl reload apache2
  • 本機驗證 TLS 握手與證書鏈:
    openssl s_client -connect example.com:443 -servername example.com
  • 線上專業安全性測試: 可透過著名的 Qualys SSL Labs SSL Test 輸入網址檢測,確認伺服器評分達到最高等級的 A+。