如何用Pyshark从QUIC初始包提取TLS握手的SNI信息?
从QUIC数据包中提取TLS握手SNI的Pyshark解决方案
你的问题核心是Pyshark默认仅返回QUIC数据包的第一个帧,而SNI所在的Crypto帧属于同一数据包中的后续帧;同时需确保Pyshark使用与Wireshark一致的解密配置,才能解析出明文TLS握手信息。
1. 配置Pyshark解密参数(与Wireshark对齐)
如果你的Wireshark通过密钥日志文件(如ssl_keys.log)解密QUIC,需在Pyshark中指定该文件,保证解析器能解密数据包:
pcap_data = pyshark.FileCapture(pcap_file, override_prefs={'ssl.keylog_file': '/path/to/your/ssl_keys.log'})
若直接使用QUIC会话密钥,可改为:
pcap_data = pyshark.FileCapture(pcap_file, decryption_key='your_quic_session_key', encryption_type='quic')
2. 遍历所有QUIC帧,定位Crypto帧提取SNI
修改代码遍历数据包内的所有QUIC帧,筛选出存储TLS握手数据的Crypto帧,从中提取SNI:
def snie_quic_one(pcap_file, index): import pyshark # 替换为你的解密配置 pcap_data = pyshark.FileCapture( pcap_file, override_prefs={'ssl.keylog_file': '/path/to/ssl_keys.log'} # 或者使用直接密钥:decryption_key='your_key', encryption_type='quic' ) packet = pcap_data[index] if 'quic' in packet: # 遍历当前数据包内的所有QUIC帧 for frame in packet.quic.frame: # 检查是否为存储TLS握手数据的Crypto帧 if hasattr(frame, 'crypto_frame'): crypto_frame = frame.crypto_frame if hasattr(crypto_frame, 'tls_handshake'): tls_handshake = crypto_frame.tls_handshake # 提取SNI(server_name扩展字段) if hasattr(tls_handshake, 'extensions_server_name'): print(f"提取到SNI: {tls_handshake.extensions_server_name}") # 可选:打印完整TLS握手详情 # print(f"TLS握手内容: {tls_handshake}") else: print("未找到QUIC数据包") if __name__ == '__main__': pcap_file = './cap2.pcapng' snie_quic_one(pcap_file, 12)
关键说明
- QUIC数据包可包含多帧(如PADDING、Crypto等),原代码仅读取第一个帧,因此无法获取后续Crypto帧中的SNI。
- 必须保证Pyshark的解密配置与Wireshark完全一致,否则无法解析出明文TLS握手内容。
- 若Wireshark已能正常解密,只需将对应的密钥日志路径或密钥传入Pyshark即可。
内容的提问来源于stack exchange,提问作者hari19
相关产品推荐
相关产品推荐

