SSL

Posted by Adam on August 24, 2022
當我們談論到「IP地址是否擁有CA可信任的憑證」時,實際上我們多半是在談論與該IP地址綁定的伺服器是否提供了經過CA(證書授權機構)認證的SSL/TLS憑證。SSL/TLS憑證是用來加密網路上的資料傳輸,並確認服務方的身份。現在我來逐步說明如何查詢: ### 步驟1: 使用SSL檢測工具 這是檢查IP地址是否有有效SSL/TLS憑證的最直接方法。您可以使用一些網絡工具,如SSL Labs的SSL Test、Digicert的憑證檢查工具等。 #### 範例操作: 使用SSL Labs的SSL Test 1. 開啟網頁瀏覽器。 2. 訪問 [SSL Labs' SSL Test](https://www.ssllabs.com/ssltest/)。 3. 輸入您欲檢測的伺服器IP地址或域名,然後點擊「Submit」。 4. 系統將分析該伺服器的SSL/TLS設定和憑證。 5. 查看報告中的「憑證路徑」部分,確認是否有CA根憑證鏈結。 ### 步驟2: 手動檢查憑證 如果您有訪問伺服器的權限,您也可以手動檢查安裝在伺服器上的憑證。 #### 範例操作: 使用OpenSSL 1. 打開命令列工具。 2. 使用以下openssl指令來查看SSL憑證資訊: ```bash openssl s_client -connect IP地址:443 -showcerts ``` 將「IP地址」替換為您要檢查的實際IP的地址,例如:`192.168.1.1`。 3. 此命令會顯示SSL連線的詳細過程,包括使用的憑證。 4. 仔細查看輸出結果中的憑證訊息,確認是否彼此綁定並由受信任的CA簽發。 ### 步驟3: 查詢憑證的CA 確認獲得的憑證是否由一個受信任的CA簽發,您可以查看憑證中的「發行者」欄位,其會列出簽發憑證的CA的資訊。 這些方法可以幫助您確定某個特定IP地址的伺服器是否配置了有效且被信任的SSL/TLS憑證。当然,确保安全的通信不僅僅是查看憑證,還需確保伺服器的其它安全配置亦最优化。 ## TLS 1.3 握手流程(客戶端、伺服器、CA) #### 流程圖 ``` sequenceDiagram participant C as 客戶端 participant S as 伺服器 participant CA as 憑證機構 Note over C: 準備TLS 1.3、加密套件、X25519 C->>S: ClientHello (TLS 1.3, Random, Cipher Suites, X25519, SNI) Note over S: 選擇TLS_AES_256_GCM_SHA384、X25519 S->>C: ServerHello (TLS 1.3, Random, Cipher Suite, X25519) S->>C: Certificate (X.509證書) S->>C: CertificateVerify (簽署握手) Note over C: 驗證證書(比對CA根證書) C->>CA: 檢查證書有效性(信任鏈) CA-->>C: 提供根證書或OCSP回應 C->>S: ECDH密鑰交換,生成會話密鑰 S->>C: ECDH密鑰交換,生成會話密鑰 C->>S: Finished (HMAC驗證) S->>C: Finished (HMAC驗證) Note over C,S: 開始加密通訊 (AES-256-GCM) C->>S: 加密的應用資料 (如HTTP請求) S->>C: 加密的回應 (如HTML) ``` #### 角色職責 - 客戶端:發起連線,驗證伺服器身份,生成會話密鑰。 - 伺服器:提供證書,證明身份,生成會話密鑰。 - CA:頒發證書,確保信任鏈,間接參與驗證。 #### 關鍵參數 - 加密套件:TLS_AES_256_GCM_SHA384(AES-256-GCM, SHA-384 for HKDF)。 - 密鑰交換:X25519(ECDH)。 - 隨機數:32位元組,確保密鑰唯一性。 - 擴展:SNI、Supported Groups。 ## 檔案憑證的指紋及到期日 ```bash openssl x509 \ -in your-cert-file.crt \ -noout \ -dates \ -fingerprint \ -sha256 ``` ## 遠端主機憑證的指紋及到期日 ```bash echo | openssl s_client \ -servername google.com \ -connect google.com:443 2>/dev/null \ | openssl x509 -noout -dates -fingerprint -sha256 ``` ### 指令邏輯與欄位說明(供參考) * **`echo |`**:輸入空白字元讓 `openssl` 抓完憑證後自動結束,不會卡在連線狀態。 * **`openssl s_client`**:負責建立 TLS 網路連線。 * `-servername your-domain.com`:指定 SNI 域名(避免拿錯同 IP 上其他網域的憑證)。 * `-connect your-domain.com:443`:指定遠端主機與 Port。 * `2>/dev/null`:過濾掉握手過程的雜訊。 * **`openssl x509`**:負責解析憑證資料。 * `-noout`:不顯示 Base64 原始字串。 * `-dates`:印出起訖到期日。 * `-fingerprint -sha256`:印出 SHA-256 憑證指紋。 ## 確認 JVM 憑證信任庫路徑 ```bash # 透過 readlink 找到目前使用的 java 執行檔真實位置 JAVA_BIN=$(readlink -f $(which java)) JAVA_BASE=$(dirname $(dirname $JAVA_BIN)) # 自動尋找 conf/security/cacerts 或 lib/security/cacerts if [ -f "$JAVA_BASE/conf/security/cacerts" ]; then CACERTS_PATH="$JAVA_BASE/conf/security/cacerts" elif [ -f "$JAVA_BASE/lib/security/cacerts" ]; then CACERTS_PATH="$JAVA_BASE/lib/security/cacerts" elif [ -f "$JAVA_BASE/jre/lib/security/cacerts" ]; then CACERTS_PATH="$JAVA_BASE/jre/lib/security/cacerts" fi echo "找到的 cacerts 檔案路徑為: $CACERTS_PATH" ``` ## 檢視憑證信任庫內所有憑證內容 ```bash keytool -list -v \ -keystore $CACERTS_PATH \ -storepass changeit ``` ## 將檔案憑證匯入 JVM 憑證信任庫中 ```bash sudo keytool -importcert \ -alias target-server-cert \ -file target-server.crt \ -keystore $CACERTS_PATH \ -storepass changeit -noprompt ``` ### 指令選項詳細說明 這行指令的作用是**將指定的憑證檔案匯入到 Java 信任庫(`cacerts`)中**。各個選項的用途如下: * **`sudo`**:以系統管理員(Root)權限執行。因為 Java 的 `cacerts` 檔案通常存放在系統保護目錄(如 `/usr/lib/jvm/`),必須有管理員權限才能寫入修改。 * **`keytool`**:Java SDK 內建的金鑰與憑證管理工具。 * **`-importcert`**:告訴 `keytool` 要執行的動作是「匯入憑證(Certificate)」。 * **`-alias target-server-cert`**:為這張匯入的憑證設定一個**自訂別名(Alias)**。別名在該憑證庫中必須是唯一的,方便日後搜尋、更新或刪除這張憑證。 * **`-file target-server.crt`**:指定你要匯入的憑證檔案路徑(在這裡是 `target-server.crt`)。 * **`-keystore $CACERTS_PATH`**:指定目標憑證庫的檔案路徑(即 Java 的 `cacerts` 檔案位置)。 * **`-storepass changeit`**:提供存取憑證庫所需的密碼(Java 預設的 `cacerts` 密碼為 `changeit`)。 * **`-noprompt`**:靜默模式。跳過 keytool 詢問「是否信任此憑證? (yes/no)」的互動提示,直接強制信任並完成匯入(非常適合寫在自動化部署腳本中)。 ## 透過別名查詢該憑證詳細資訊 ```bash keytool -list -v \ -keystore $CACERTS_PATH \ -storepass changeit \ -alias target-server-cert ``` ## 透過別名刪除憑證 有了別名,未來如果對方更換憑證,你也可以直接指定別名將舊憑證刪除: ```bash sudo keytool -delete \ -alias target-server-cert \ -keystore $CACERTS_PATH \ -storepass changeit ```