[HTTPS][mTLS] Two-way SSL – SSL雙向驗證 on Nginx

Intro

Two-way SSL 即 Server 端也要求 Client 端提供 certificate 做驗證


圖片來源:web-service-principles - HTTP


Client 端憑證

Client 端需配置憑證及對應 Private Key,用於在 CertificateRequest 階段提供終端憑證並生成簽章;
Server 端需配置信任的 CA 列表(包括 intermediate 與 root CA),用於驗證 Client 提供的憑證鏈。

[Server] TLS/SSL憑證(Certificate)常用指令 – 製作CSR


Server 端範例

Server 端需指定信任的 client CA 憑證,若需要支援多個 client 或完整憑證鏈,可將多張 CA 憑證合併至同一個 PEM 檔案。
(需包含信任的 root CA,否則 client 即使帶完整憑證鏈也會驗證失敗)

Nginx 設定

Nginx 可以在 Server block 上啟用驗證 Client 端 certificate:

server {
   listen 443 ssl;

   ssl_certificate /etc/nginx/ssl/public.crt;
   ssl_certificate_key /etc/nginx/ssl/private.rsa;

   # Client certificate verification
   ssl_client_certificate /etc/nginx/ssl/client_ca_fullchain.pem;
   ssl_verify_client on;

   server_name api.my_domain.com;

   location / {
      # Additional configuration here
   }
}

Nginx 在 mTLS 驗證上,不會直接於 TLS handshake 階段拒絕,而是預設回覆 HTTP code 400,描述如:no required SSL certificate was sent)

Apache 設定

<VirtualHost *:443>
    ServerName example.com

    # Enable SSL
    SSLEngine on

    # SSL server settings (for server authentication)
    SSLCertificateFile /path/to/server.crt
    SSLCertificateKeyFile /path/to/server.key

    # Two-way SSL settings (for client authentication)
    SSLCACertificateFile /path/to/combined_ca.crt
    SSLVerifyClient require
    SSLVerifyDepth 2
</VirtualHost>

Client 端範例

CURL

$ curl https://two-way-ssl.local --cert client.crt --key client.key [--pass passPhrase]

# Key也可以bundle至CRT
$ curl https://two-way-ssl.local --cert crt-with-key.crt

# PKCS#12 方法
$ curl https://two-way-ssl.local --cert-type P12 --cert cert.p12:password

PHP Guzzle

$response = $client->get('/', [
        'cert' => '/path/client.crt',
        'ssl_key' => '/path/client.key',     
    ]
);

Pass Phrase情況:

    'cert' => ['/path/client.crt', 'password'],
    'ssl_key' => ['/path/client.key', 'password'],

JAVA (KeyStore)

JAVA 一般使用包含憑證與私鑰的 PKCS#12 格式或者轉成 JKS 載入 java.security.KeyStore

import java.security.KeyStore;
// ...
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(getClass().getResourceAsStream("/path/to/keystore.p12"), "p12_password".toCharArray());

// Build SSL configuration by keyStore

References

One thought on “[HTTPS][mTLS] Two-way SSL – SSL雙向驗證 on Nginx

Leave a Reply

Your email address will not be published. Required fields are marked *