#!/usr/bin/env bash # check_ssl.sh — 檢查 tpesupporter.tpech.gov.tw SSL 憑證狀態 # # 用法:./check_ssl.sh [domain] [port] # 預設 domain=tpesupporter.tpech.gov.tw, port=443 # # 備註:憑證由 GCA G3(政府憑證管理中心)簽發,根憑證不在 Linux 預設 # 信任庫。openssl verify 會回 code 20,屬**正常現象**,瀏覽器端可正常 # 驗證。此腳本不把 verify code 當成失敗條件,只看期限與主機名匹配。 # # 結束碼: # 0 — 憑證正常 # 1 — 連線失敗或無法取得憑證 # 2 — 憑證已過期 # 3 — 憑證將於 WARN_DAYS 天內到期 # 4 — 憑證主體與目標網域不符 set -u DOMAIN="${1:-tpesupporter.tpech.gov.tw}" PORT="${2:-443}" WARN_DAYS="${WARN_DAYS:-30}" echo "== SSL 憑證檢查:${DOMAIN}:${PORT} ==" echo # --- 1. 取得憑證 --- RAW=$(echo | openssl s_client -connect "${DOMAIN}:${PORT}" -servername "${DOMAIN}" 2>/dev/null /dev/null) ISSUER=$(openssl x509 -noout -issuer <<<"$PEM" 2>/dev/null) DATES=$(openssl x509 -noout -dates <<<"$PEM" 2>/dev/null) SAN=$(openssl x509 -noout -ext subjectAltName <<<"$PEM" 2>/dev/null | sed -n "2p" | sed "s/^[ \t]*//") END_DATE=$(openssl x509 -noout -enddate <<<"$PEM" | sed "s/notAfter=//") echo "$SUBJECT" echo "$ISSUER" echo "$DATES" echo "SAN: ${SAN:-(無)}" echo # --- 3. 計算到期天數 --- END_EPOCH=$(date -d "$END_DATE" +%s 2>/dev/null || echo 0) NOW_EPOCH=$(date +%s) if [ "$END_EPOCH" -eq 0 ]; then echo "[WARN] 無法解析到期日:$END_DATE" DAYS_LEFT="?" else DAYS_LEFT=$(( (END_EPOCH - NOW_EPOCH) / 86400 )) fi echo "到期日:${END_DATE}" echo "剩餘天數:${DAYS_LEFT}" # --- 4. 驗證 Code(僅資訊性) --- VCODE=$(grep -oE "Verify return code: [0-9]+" <<<"$RAW" | tail -1 | awk "{print \$NF}") echo "openssl verify code:${VCODE:-?}(GCA G3 根憑證不在 Linux 預設信任庫,回 20 屬正常)" # --- 5. 主機名匹配(CN / SAN) --- if grep -qi "DNS:${DOMAIN}" <<<"$SAN" || grep -qi "CN[[:space:]]*=[[:space:]]*${DOMAIN}" <<<"$SUBJECT"; then HOST_MATCH=1 else HOST_MATCH=0 fi echo # --- 6. 判定 --- if [ "$HOST_MATCH" -eq 0 ]; then echo "[FAIL] 憑證 CN/SAN 不包含 ${DOMAIN}" exit 4 fi if [ "$DAYS_LEFT" = "?" ]; then echo "[WARN] 憑證期限無法解析" exit 3 fi if [ "$DAYS_LEFT" -lt 0 ]; then echo "[FAIL] 憑證已過期 $((-DAYS_LEFT)) 天" exit 2 elif [ "$DAYS_LEFT" -lt "$WARN_DAYS" ]; then echo "[WARN] 憑證將於 ${DAYS_LEFT} 天內到期(閾值 ${WARN_DAYS} 天)" exit 3 else echo "[OK] 憑證狀態正常(剩 ${DAYS_LEFT} 天)" exit 0 fi