怎样实现SSL证书检测脚本

wen 实用脚本 31

本文目录导读:

怎样实现SSL证书检测脚本

  1. Python版本(推荐)
  2. Bash脚本版本
  3. 批量检测脚本(Python)
  4. 安装依赖
  5. 使用示例
  6. 主机列表文件格式

我来提供几个不同语言的SSL证书检测脚本实现方案:

Python版本(推荐)

#!/usr/bin/env python3
"""
SSL证书检测脚本
支持检测:证书有效期、颁发者、主题、SAN、证书链等
"""
import ssl
import socket
import datetime
import argparse
import json
from urllib.parse import urlparse
def get_certificate_info(hostname, port=443, timeout=5):
    """获取SSL证书信息"""
    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE
    try:
        with socket.create_connection((hostname, port), timeout=timeout) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                cert = ssock.getpeercert()
                # 解析证书信息
                cert_info = {
                    'hostname': hostname,
                    'port': port,
                    'checked_at': datetime.datetime.now().isoformat(),
                    'subject': dict(x[0] for x in cert['subject']),
                    'issuer': dict(x[0] for x in cert['issuer']),
                    'version': cert.get('version'),
                    'serial_number': cert.get('serialNumber'),
                }
                # 有效期
                not_before = datetime.datetime.strptime(
                    cert['notBefore'], '%b %d %H:%M:%S %Y %Z'
                )
                not_after = datetime.datetime.strptime(
                    cert['notAfter'], '%b %d %H:%M:%S %Y %Z'
                )
                cert_info['valid_from'] = not_before.isoformat()
                cert_info['valid_until'] = not_after.isoformat()
                cert_info['days_remaining'] = (not_after - datetime.datetime.now()).days
                cert_info['is_expired'] = datetime.datetime.now() > not_after
                # SAN (Subject Alternative Names)
                san = []
                for ext in cert.get('subjectAltName', []):
                    san.append(ext[1])
                cert_info['san'] = san
                # 加密算法和密钥
                cert_info['cipher'] = ssock.cipher()
                return cert_info
    except Exception as e:
        return {'error': str(e), 'hostname': hostname, 'port': port}
def check_certificate_chain(hostname, port=443):
    """检查SSL证书链"""
    import OpenSSL
    try:
        context = ssl.create_default_context()
        with socket.create_connection((hostname, port)) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                # 获取证书链
                cert_chain = []
                for cert in ssock.get_peer_cert_chain():
                    cert_chain.append({
                        'subject': cert.get_subject().get_components(),
                        'issuer': cert.get_issuer().get_components(),
                        'serial_number': cert.get_serial_number(),
                        'not_before': cert.get_notBefore().decode(),
                        'not_after': cert.get_notAfter().decode(),
                    })
                return cert_chain
    except Exception as e:
        return {'error': str(e)}
def format_output(cert_info, format_type='text'):
    """格式化输出"""
    if 'error' in cert_info:
        return f"错误: {cert_info['error']}"
    if format_type == 'json':
        return json.dumps(cert_info, indent=2)
    # 文本格式
    output = []
    output.append(f"=== SSL证书检测报告 ===")
    output.append(f"主机: {cert_info['hostname']}:{cert_info['port']}")
    output.append(f"检测时间: {cert_info['checked_at']}")
    output.append("")
    output.append(f"主题 (Subject):")
    for key, value in cert_info['subject'].items():
        output.append(f"  {key}: {value}")
    output.append("")
    output.append(f"颁发者 (Issuer):")
    for key, value in cert_info['issuer'].items():
        output.append(f"  {key}: {value}")
    output.append("")
    output.append(f"有效期:")
    output.append(f"  开始: {cert_info['valid_from']}")
    output.append(f"  结束: {cert_info['valid_until']}")
    output.append(f"  剩余天数: {cert_info['days_remaining']}")
    output.append(f"  已过期: {'是' if cert_info['is_expired'] else '否'}")
    output.append("")
    output.append(f"SAN (Subject Alternative Names):")
    for san in cert_info['san']:
        output.append(f"  - {san}")
    output.append("")
    output.append(f"证书版本: {cert_info['version']}")
    output.append(f"序列号: {cert_info['serial_number']}")
    return '\n'.join(output)
def main():
    parser = argparse.ArgumentParser(description='SSL证书检测工具')
    parser.add_argument('hostname', help='要检测的主机名或URL')
    parser.add_argument('-p', '--port', type=int, default=443, help='端口号 (默认: 443)')
    parser.add_argument('-t', '--timeout', type=int, default=5, help='超时时间 (秒)')
    parser.add_argument('-o', '--output', choices=['text', 'json'], default='text', help='输出格式')
    parser.add_argument('--check-chain', action='store_true', help='检查证书链')
    args = parser.parse_args()
    # 从URL中提取主机名
    hostname = args.hostname
    if hostname.startswith('http'):
        hostname = urlparse(hostname).hostname
    # 获取证书信息
    cert_info = get_certificate_info(hostname, args.port, args.timeout)
    # 输出结果
    print(format_output(cert_info, args.output))
    # 检查证书链
    if args.check_chain:
        print("\n=== 证书链检查 ===")
        chain = check_certificate_chain(hostname, args.port)
        if isinstance(chain, list):
            for i, cert in enumerate(chain):
                print(f"\n证书 {i+1}:")
                print(f"  颁发者: {cert['issuer']}")
                print(f"  有效期至: {cert['not_after']}")
        else:
            print(f"错误: {chain['error']}")
if __name__ == '__main__':
    main()

Bash脚本版本

#!/bin/bash
# SSL证书检测脚本
usage() {
    echo "用法: $0 [-h 主机] [-p 端口] [-t 超时秒]"
    echo "示例: $0 -h google.com -p 443"
    exit 1
}
HOST=""
PORT=443
TIMEOUT=5
while getopts "h:p:t:" opt; do
    case $opt in
        h) HOST="$OPTARG" ;;
        p) PORT="$OPTARG" ;;
        t) TIMEOUT="$OPTARG" ;;
        *) usage ;;
    esac
done
if [ -z "$HOST" ]; then
    usage
fi
echo "========================================"
echo "SSL证书检测报告"
echo "主机: $HOST:$PORT"
echo "检测时间: $(date)"
echo "========================================"
# 获取证书信息
cert_info=$(echo | openssl s_client -connect $HOST:$PORT -servername $HOST 2>/dev/null | openssl x509 -text -noout)
if [ $? -ne 0 ]; then
    echo "错误: 无法连接到 $HOST:$PORT"
    exit 1
fi
# 提取证书信息
subject=$(echo "$cert_info" | grep "Subject:" | head -1)
issuer=$(echo "$cert_info" | grep "Issuer:" | head -1)
valid_from=$(echo "$cert_info" | grep "Not Before" | head -1)
valid_until=$(echo "$cert_info" | grep "Not After" | head -1)
serial=$(echo "$cert_info" | grep "Serial Number:" | head -1)
# 计算剩余天数
if command -v date &> /dev/null; then
    expiry_date=$(echo "$valid_until" | sed 's/Not Before: //' | sed 's/Not After : //')
    expiry_epoch=$(date -d "$expiry_date" +%s 2>/dev/null)
    now_epoch=$(date +%s)
    if [ ! -z "$expiry_epoch" ]; then
        remaining_days=$(( ($expiry_epoch - $now_epoch) / 86400 ))
        echo ""
        echo "剩余天数: $remaining_days 天"
        if [ $remaining_days -le 30 ]; then
            echo "⚠️  警告: 证书即将过期!"
        elif [ $remaining_days -le 0 ]; then
            echo "❌ 证书已过期!"
        fi
    fi
fi
# 提取SAN
echo ""
echo "证书详细信息:"
echo "$cert_info" | grep -A 1 "Subject Alternative Name" | head -2
echo ""
echo "主题 (Subject):"
echo "$subject"
echo ""
echo "颁发者 (Issuer):"
echo "$issuer"
echo ""
echo "有效期:"
echo "$valid_from"
echo "$valid_until"
echo ""
echo "序列号:"
echo "$serial"

批量检测脚本(Python)

#!/usr/bin/env python3
"""
批量SSL证书检测脚本
支持从文件读取主机列表
"""
import json
import sys
import concurrent.futures
from ssl_cert_checker import get_certificate_info, format_output
def load_hosts_from_file(filename):
    """从文件加载主机列表"""
    hosts = []
    with open(filename, 'r') as f:
        for line in f:
            line = line.strip()
            if line and not line.startswith('#'):
                parts = line.split(':')
                host = parts[0]
                port = int(parts[1]) if len(parts) > 1 else 443
                hosts.append((host, port))
    return hosts
def check_multiple_hosts(hosts, max_workers=10):
    """并发检测多个主机"""
    results = []
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        future_to_host = {
            executor.submit(get_certificate_info, host, port): (host, port)
            for host, port in hosts
        }
        for future in concurrent.futures.as_completed(future_to_host):
            host, port = future_to_host[future]
            try:
                result = future.result()
                results.append(result)
            except Exception as e:
                results.append({
                    'hostname': host,
                    'port': port,
                    'error': str(e)
                })
    return results
def main():
    if len(sys.argv) < 2:
        print("用法: python batch_check.py <主机列表文件> [输出格式]")
        print("主机列表文件格式: 每行一个主机名或 host:port")
        print("输出格式: text (默认) 或 json")
        sys.exit(1)
    filename = sys.argv[1]
    output_format = sys.argv[2] if len(sys.argv) > 2 else 'text'
    hosts = load_hosts_from_file(filename)
    if not hosts:
        print("错误: 没有找到有效的主机")
        sys.exit(1)
    print(f"开始检测 {len(hosts)} 个主机...")
    results = check_multiple_hosts(hosts)
    # 按剩余天数排序
    results.sort(key=lambda x: x.get('days_remaining', 999), reverse=True)
    # 输出汇总
    if output_format == 'json':
        print(json.dumps(results, indent=2))
    else:
        print("\n" + "="*60)
        print("SSL证书检测汇总报告")
        print("="*60)
        for result in results:
            print("\n" + format_output(result))
            print("-"*40)
if __name__ == '__main__':
    main()

安装依赖

# Python依赖
pip install pyOpenSSL
# 或者使用requirements.txt
# pip install -r requirements.txt
# requirements.txt内容:
# pyOpenSSL>=21.0.0

使用示例

# 基础用法
python ssl_checker.py example.com
# 指定端口
python ssl_checker.py example.com -p 8443
# JSON输出
python ssl_checker.py example.com -o json
# 检查证书链
python ssl_checker.py example.com --check-chain
# Bash脚本
./ssl_check.sh -h example.com -p 443
# 批量检测
python batch_check.py hosts.txt

主机列表文件格式

# hosts.txt 格式
example.com
google.com:443
github.com:443
api.example.com:8443

这个脚本集提供了完整的SSL证书检测功能,包括:

  • 单个主机检测
  • 批量检测
  • 证书详情查看
  • 有效期监控
  • 证书链检查
  • 多种输出格式

抱歉,评论功能暂时关闭!