You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求助:Python在代理环境下提取网站证书信息

在代理环境下提取网站SSL证书信息(Python新手友好指南)

Hey there! I totally get how confusing sockets, SSL wrappers, and proxy setups can be when you're starting out with Python. Let's walk through two straightforward ways to pull certificate details (like issuer, expiration date) even behind a proxy—one using a high-level library (great for beginners) and another with lower-level code to help you understand the underlying concepts.


方法一:用Requests库(简单快捷)

Requests handles a lot of the proxy and SSL heavy lifting for you, so this is perfect if you want to get up and running quickly.

步骤说明:

  • Configure your proxy settings as a dictionary
  • Send a streaming request to keep the connection open without downloading the full page
  • Extract the underlying SSL socket from the response to get the certificate

代码示例:

import requests
import ssl

# 替换成你的代理地址和端口
proxies = {
    'http': 'http://your-proxy-address:port',
    'https': 'http://your-proxy-address:port'  # 多数HTTPS代理用HTTP协议连接,按需调整
}

target_url = "https://example.com"  # 替换成你要检测的网站

try:
    # 使用stream=True只建立连接,不下载完整响应
    with requests.get(target_url, proxies=proxies, stream=True) as response:
        # 获取底层socket连接(不同Requests版本可能略有差异,这个写法兼容大多数情况)
        raw_connection = response.raw._connection
        sock = raw_connection.sock

        # 获取SSL证书
        if isinstance(sock, ssl.SSLSocket):
            cert = sock.getpeercert()
        else:
            # 处理代理包装后的socket
            cert = sock.socket.getpeercert()

        # 解析并打印证书信息
        print("📜 证书签发者:")
        for issuer_entry in cert['issuer']:
            field_name, field_value = issuer_entry[0]
            print(f"  {field_name}: {field_value}")
        
        print("\n⏰ 证书有效期:")
        print(f"  生效日期: {cert['notBefore']}")
        print(f"  过期日期: {cert['notAfter']}")

except Exception as e:
    print(f"❌ 出错了: {str(e)}")

方法二:用Socket + SSL(理解底层逻辑)

If you want to wrap your head around how proxies and SSL connections work under the hood, this method breaks down each step explicitly.

核心逻辑:

  1. Connect to your proxy server first
  2. Send a CONNECT request to tell the proxy to forward your traffic to the target website's HTTPS port (443)
  3. Wrap the proxy-connected socket with SSL to establish an encrypted connection
  4. Extract the certificate from the SSL socket

代码示例:

import socket
import ssl
import base64

# 代理配置
proxy_host = "your-proxy-address"
proxy_port = 8080  # 替换成你的代理端口
proxy_username = None  # 如果代理需要认证,填写用户名
proxy_password = None  # 如果代理需要认证,填写密码

# 目标网站配置
target_host = "example.com"
target_port = 443

# 1. 连接到代理服务器
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    sock.connect((proxy_host, proxy_port))
except ConnectionRefusedError:
    print("❌ 无法连接到代理服务器,请检查地址和端口")
    sock.close()
    exit()

# 2. 发送CONNECT请求给代理
connect_headers = [
    f"CONNECT {target_host}:{target_port} HTTP/1.1",
    f"Host: {target_host}"
]

# 如果代理需要基础认证,添加Authorization头
if proxy_username and proxy_password:
    auth_creds = f"{proxy_username}:{proxy_password}"
    auth_b64 = base64.b64encode(auth_creds.encode()).decode()
    connect_headers.append(f"Proxy-Authorization: Basic {auth_b64}")

# 拼接请求并发送
connect_request = "\r\n".join(connect_headers) + "\r\n\r\n"
sock.sendall(connect_request.encode())

# 3. 检查代理的响应,确认连接成功
proxy_response = sock.recv(4096).decode()
if "200 Connection established" not in proxy_response:
    print(f"❌ 代理连接目标网站失败: {proxy_response}")
    sock.close()
    exit()

# 4. 用SSL包装socket,建立加密连接
try:
    ssl_sock = ssl.wrap_socket(sock, server_hostname=target_host)
except ssl.SSLError as e:
    print(f"❌ SSL连接失败: {str(e)}")
    sock.close()
    exit()

# 5. 获取并解析证书
cert = ssl_sock.getpeercert()

print("📜 证书签发者:")
for issuer_entry in cert['issuer']:
    field_name, field_value = issuer_entry[0]
    print(f"  {field_name}: {field_value}")

print("\n⏰ 证书有效期:")
print(f"  生效日期: {cert['notBefore']}")
print(f"  过期日期: {cert['notAfter']}")

# 关闭连接
ssl_sock.close()

关键注意事项:

  • 代理认证: 如果你的代理需要用户名/密码,记得在代码中添加Proxy-Authorization头(两个方法都有对应的示例)
  • 代理类型: 有些代理是HTTPS代理,这时候你需要先建立SSL连接到代理的端口(比如443)再发送CONNECT请求
  • SSL版本: 如果遇到SSL握手错误,可以尝试指定SSL版本,比如ssl.wrap_socket(..., ssl_version=ssl.PROTOCOL_TLS_CLIENT)

Hope this clears things up and gets you extracting those cert details smoothly!

内容的提问来源于stack exchange,提问作者Virtual Penman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:55:51