在 Python WSGI/ASGI 框架中如何读取客户端请求的 TLS 指纹
在 python 生态系统中,尤其是使用 wsgi/asgi 框架时,读取客户端请求的 tls 指纹是一个常见但相对复杂的问题。许多开发者尝试使用 request.scope.get('ssl') 来获取 tls 相关信息,但经常发现这个方法并不可靠。下面我们将详细探讨如何在 python 的 uvicorn 和 fastapi 环境中以及使用纯 socket 编程的方式获取客户端的 tls 指纹。
使用 Uvicorn 和 FastAPI
首先,让我们来看一下在 uvicorn 和 fastapi 环境中如何尝试获取 TLS 指纹。以下是示例代码:
import uvicornfrom loggers import loggerfrom fastapi import FastAPI, Requestfrom fastapi.middleware.cors import CORSMiddlewarefrom middleware.loggers import RequestLogMiddlewarefrom middleware.correlations import CorrelationIdMiddlewarefrom starlette.middleware.base import BaseHTTPMiddlewareapp = FastAPI()
app.add_middleware(CORSMiddleware,allow_origins=[''],allow_credentials=True,allow_methods=[""],allow_headers=["*"],)app.add_middleware(BaseHTTPMiddleware, dispatch=RequestLogMiddleware())app.add_middleware(BaseHTTPMiddleware, dispatch=CorrelationIdMiddleware())
@app.get('/')@logger.catchasync def root(request: Request):ssl_info = request.scope.get('ssl')if ssl_info:
尝试获取 TLS 指纹,不同的 Python 版本和环境可能有所不同
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
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 信息。
使用纯 socket 编程
考虑到在 FastAPI 中获取 TLS 指纹的困难,我们尝试使用纯 socket 编程来直接处理客户端的 TLS 握手过程。以下是示例代码:
立即学习“Python免费学习笔记(深入)”;
import sslimport socketfrom loguru import loggerfrom pyja3 import extract_ja3_from_client_hellofrom threading import ThreadCERT_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"
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()
def main():context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
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()
if name == "main":main()
在上述代码中,我们使用 ssl 和 socket 模块来设置 TLS 服务器,并且使用 pyja3 库尝试提取 JA3 指纹。然而,实际操作中,我们可能仍然无法读取到客户端请求中的 TLS 指纹。
解决方案和讨论
在当前的 Python WSGI/ASGI 生态系统中,读取 TLS 指纹并不直接支持。无论是使用 FastAPI 还是纯 socket 编程,都遇到了困难。这主要是因为 TLS 信息通常在底层网络层处理,应用层无法直接访问这些信息。
要解决这个问题,可以考虑以下方法:
使用中间件:某些 Web 服务器(如 Nginx)可以作为反向代理,并通过中间件或插件来捕获和记录 TLS 信息。然后,这些信息可以通过 HTTP 头或其他方式传输给应用服务器。使用专用库:某些专门用于 TLS 指纹分析的库可能会提供更直接的方法来提取所需信息。调整服务器配置:在某些情况下,调整服务器的配置文件(例如 Nginx 配置)以记录 TLS 信息可能是一个可行的解决方案。
总之,读取客户端请求的 TLS 指纹在 Python 的 WSGI/ASGI 框架中需要更深入的网络层处理或借助外部工具和配置来实现。

以上就是在 Python 的 WSGI/ASGI 框架中如何读取客户端请求的 TLS 指纹?的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1360768.html
微信扫一扫
支付宝扫一扫