在 python 生态系统中,尤其是使用 wsgi/asgi 框架时,读取客户端请求的 tls 指纹是一个常见但相对复杂的问题。许多开发者尝试使用 request.scope.get('ssl') 来获取 tls 相关信息,但经常发现这个方法并不可靠。下面我们将详细探讨如何在 python 的 uvicorn 和 fastapi 环境中以及使用纯 socket 编程的方式获取客户端的 tls 指纹。
首先,让我们来看一下在 uvicorn 和 fastapi 环境中如何尝试获取 TLS 指纹。以下是示例代码:
<code>import uvicorn
from loggers import logger
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from middleware.loggers import RequestLogMiddleware
from middleware.correlations import CorrelationIdMiddleware
from starlette.middleware.base import BaseHTTPMiddleware
<p>app = FastAPI()</p><p>app.add_middleware(
CORSMiddleware,
allow_origins=['<em>'],
allow_credentials=True,
allow_methods=["</em>"],
allow_headers=["*"],
)
app.add_middleware(BaseHTTPMiddleware, dispatch=RequestLogMiddleware())
app.add_middleware(BaseHTTPMiddleware, dispatch=CorrelationIdMiddleware())</p><p>@app.get('/')
@logger.catch
async def root(request: Request):
ssl_info = request.scope.get('ssl')
if ssl_info:</p><h1>尝试获取 TLS 指纹,不同的 Python 版本和环境可能有所不同</h1><pre class="brush:php;toolbar:false;"><code> tls_fingerprint = ssl_info.get('peer_cert_fingerprint')
if tls_fingerprint:
logger.info(f"Client TLS fingerprint: {tls_fingerprint}")
else:
logger.info("Could not get client TLS fingerprint.")
else:
logger.info("No SSL information available.")
response_body = {
"ip": request.client.host
}
logger.debug(response_body)
return response_body</code>if name == "main": uvicorn.run( app, host="0.0.0.0", port=8086, workers=1, ssl_keyfile="/Users/ponponon/Downloads/xxxx.cn_nginx/xxxx.cn.key", ssl_certfile="/Users/ponponon/Downloads/xxxx.cn_nginx/xxxx.cn.pem" )
如上所述,尝试通过 request.scope.get('ssl') 访问 TLS 信息,但发现该方法在许多情况下返回的是 None。这可能是因为 FastAPI 并不直接暴露 TLS 信息。
考虑到在 FastAPI 中获取 TLS 指纹的困难,我们尝试使用纯 socket 编程来直接处理客户端的 TLS 握手过程。以下是示例代码:
立即学习“Python免费学习笔记(深入)”;
<code>import ssl
import socket
from loguru import logger
from pyja3 import extract_ja3_from_client_hello
from threading import Thread</p><p>CERT_FILE = "/home/pon/code/me/ssl/xxxx.cn_nginx/xxxx.cn.pem"
KEY_FILE = "/home/pon/code/me/ssl/xxxx.cn_nginx/xxxx.cn.key"</p><p>def handle_client(client_socket, addr):
try:
raw_data = client_socket.recv(4096, socket.MSG_PEEK)
ja3_str, ja3_hash = extract_ja3_from_client_hello(raw_data)
logger.info(f"[{addr}] JA3: {ja3_str}, MD5: {ja3_hash}")
except Exception as e:
logger.warning(f"[{addr}] Failed to get JA3: {e}")
finally:
client_socket.close()</p><p>def main():
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)</p><pre class="brush:php;toolbar:false;"><code>bindsocket = socket.socket()
bindsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
bindsocket.bind(("0.0.0.0", 8086))
bindsocket.listen(5)
logger.info("Server listening on 0.0.0.0:8086")
while True:
client_socket, fromaddr = bindsocket.accept()
Thread(target=handle_client, args=(client_socket, fromaddr)).start()</code>if name == "main": main()
在上述代码中,我们使用 ssl 和 socket 模块来设置 TLS 服务器,并且使用 pyja3 库尝试提取 JA3 指纹。然而,实际操作中,我们可能仍然无法读取到客户端请求中的 TLS 指纹。
在当前的 Python WSGI/ASGI 生态系统中,读取 TLS 指纹并不直接支持。无论是使用 FastAPI 还是纯 socket 编程,都遇到了困难。这主要是因为 TLS 信息通常在底层网络层处理,应用层无法直接访问这些信息。
要解决这个问题,可以考虑以下方法:
总之,读取客户端请求的 TLS 指纹在 Python 的 WSGI/ASGI 框架中需要更深入的网络层处理或借助外部工具和配置来实现。

以上就是在 Python 的 WSGI/ASGI 框架中如何读取客户端请求的 TLS 指纹?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号