目录
- 一、需求背景
- 二、操作步骤
- 2.1 jSSLKeyLog 工具下载
- 2.2 jSSLKeyLog工具使用
- 2.3 将sslkeylog导入Wireshark
- 2.4 测试Demo
- 2.5 测试结果
- 1)使用工具解密HTTPS前:
- 2)实用工具解密HTTPS后:
- 三、补充:如果出现未解密成功的情况

一、需求背景
在上一篇文章中,我们介绍了 Wireshark 抓包工具的基本使用:抓包工具(二)Wireshark 的下载、安装、使用、快捷键。
我们先回顾下:Wireshark
和其他抓包软件相比,优势在于直接在网络传输的物理层 进行抓包,对于本地开发调试程序发送的请求不需要代理也可以抓到。但是缺点就是 无法进行 HTTPS 请求包进行解密。
我在网上找了很多篇文章,其实使用 Wireshark 进行 HTTPS 的 TLS流
进行解密 无非以下两种方式</:
-
方法一:拿到服务器的
.p12
证书文件(含私钥信息),导入 Wireshark。这种方式除非是服务器的维护人员,否则一般情况下是拿不到的,而且拿出来之后的证书可以直接伪造网站信息,非常不安全。
-
方法二:通过设置浏览器的启动参数,或者添加
SSLKEYLOGFILE
环境变量,记录到 HTTPS 加解密过程的日志文件,导入 Wireshark。这种方式一般仅适用于浏览器请求抓包。
今天,小编遇到了一个 JDK 小版本的请求问题,想抓包一下不同 JDK 版本的请求内容,以上两种方法都不适用,那怎么办呢?先看效果:
(注意:只有 TLS流 和 HTTP流 是可以解密出来的,TCP流 则是无法解密的,不要追踪错了流类型。)
补充: 如果让 Java 程序走 Fiddler4 的代理也可以成功抓包,但是小编的情况比较特殊,走了 Fiddler4 的代理之后,问题就无法复现了。推测是 Fiddler4 对于请求内容进行了兼容调整,所以还得是 Wireshark 出马。
二、操作步骤
2.1 jSSLKeyLog 工具下载
我们都知道,一个完整的 HTTP 请求过程中会经历 三次握手
和 四次挥手
。
上面我们介绍过的方法二其实就是通过收集 “三次握手” 过程中生成的 sslkeylog 密钥进行解密。这里我们同样也需要使用工具获取用来解密的密钥,如下所示:
- jSSLKeyLog: https://github.com/jsslkeylog/jsslkeylog
官方介绍如下:
jSSLKeyLog
是一个 Java Agent 库,它可以将 Java 应用程序创建的 SSL 会话密钥记录到 Wireshark 可识别的日志文件中,从而可以通过 “跟踪 SSL 数据流” 功能调试 SSL 连接问题,就像连接未加密一样。它既适用于 Java 服务器软件,也适用于客户端软件。
(注意:jSSLKeyLog 工具要求环境在 JDK 7 及以上)
- 官网下载: https://github.com/jsslkeylog/jsslkeylog/releases
如果是 JDK8 可以直接使用下面这个文件,小编亲测好用。
- JDK8版本jSSLKeyLog下载: https://share.weiyun.com/h2i2oVns
文件如下所示:
2.2 jSSLKeyLog工具使用
使用时,我们只需要在启动命令加上如下参数即可:
-javaagent:D:\java\jSSLKeyLog.jar=D:\sslkeylog.txt
D:\java\jSSLKeyLog.jar
:工具包位置。D:\sslkeylog.txt
:希望生成的SSL密钥文件位置。
如果是在 IDEA 中启动 Java 程序,可以在启动配置中先选择 Add VM options
。
然后添加启动参数,如下所示:

自动生成的 sslkeylog.txt 日志文件内容如下所示:
2.3 将sslkeylog导入Wireshark
打开 Wireshark,点击 编辑
,再点击 首选项
。

在 Protocols
中选择 TLS
协议,再选择我们刚才生成的 sslkeylog.txt 文件,点击确定即可。

随后选择需要进行抓包的网卡,即可进行抓包。
2.4 测试Demo
这里我们以一个HTTPS测试网站 httpbin
为例进行请求,地址如下:
- 页面地址: https://httpbin.org/#/Anything/post_anything
- 接口地址: https://httpbin.org/anything
Wireshark筛选规则:
src or dst host httpbin.org
代码示例:
- 启动参数:
-javaagent:D:\java\jSSLKeyLog.jar=D:\sslkeylog.txt
package com.demo.example;import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;/*** <p> @Title Test* <p> @Description Wireshark抓包工具Demo** @author ACGkaka* @date 2025/2/22 21:56*/
public class Test {public static void main(String[] args) {String url = "https://httpbin.org/anything";String param = "{\"appKey\":\"7844ed27528aa2e1b7a6a2878484ad4c\",\"userPhone\":\"155****8888\"}";System.out.println("===> 请求地址:" + url + ",请求内容:" + param);String result = doPostByJson(url, param);System.out.println("<== 响应结果:" + result);}/*** POST请求,JSON传参*/public static String doPostByJson(String urlPath, String json) {OutputStream outputStream = null;BufferedReader reader = null;try {// 信任所有Hosts(HTTPS专用)trustAllHosts();// 1、建立连接HttpURLConnection conn;URL url = new URL(urlPath);if (url.getProtocol().equalsIgnoreCase("https")) {HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();httpsConn.setHostnameVerifier(DO_NOT_VERIFY);conn = httpsConn;} else {conn = (HttpURLConnection) url.openConnection();}conn.setRequestMethod("POST");conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);conn.setRequestProperty("Connection", "Keep-Alive");conn.setRequestProperty("Charset", "UTF-8");conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");conn.setRequestProperty("accept", "application/json");// 2、写入请求体byte[] writebytes = json.getBytes();conn.setRequestProperty("Content-Length", String.valueOf(writebytes.length));outputStream = conn.getOutputStream();outputStream.write(json.getBytes());outputStream.flush();outputStream.close();// 3、读取响应InputStream inputStream = conn.getInputStream();reader = new BufferedReader(new InputStreamReader(inputStream));String line = reader.readLine();StringBuffer response = new StringBuffer();while (line != null) {response.append(line);line = reader.readLine();if (line != null) {response.append("\n");}}reader.close();return response.toString();} catch (Exception e) {e.printStackTrace();} finally {if (outputStream != null) {try {outputStream.close();} catch (IOException e) {System.out.println("输出流关闭失败");}}if (reader != null) {try {reader.close();} catch (IOException e) {System.out.println("输入流关闭失败");}}}return null;}// --------------------------------------------------------------------------------------------------------------// 私有方法// --------------------------------------------------------------------------------------------------------------/*** 信任所有Hosts(HTTPS专用)** (补充:如果服务器使用的SSL证书不是由Java默认信任的证书颁发机构(CA)签发的,例如自签名证书,就会报错:* SunCertPathBuilderException: unable to find valid certification path to requested target。)*/private static void trustAllHosts() {TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}}};try {SSLContext sc = SSLContext.getInstance("TLS");sc.init(null, trustAllCerts, new SecureRandom());HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());} catch (Exception e) {e.printStackTrace();}}/*** HostnameVerifier 接口用于验证HTTPS连接的主机名是否与证书中的主机名匹配。** (补充:当Java应用程序尝试建立HTTPS连接时,它会检查服务器的SSL证书以确保其有效性,* 并且还会检查证书中的主机名是否与正在连接的实际主机名相匹配。如果主机名不匹配,* 默认情况下连接会被拒绝,从而保护应用程序不受潜在的安全威胁。)*/private final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {public boolean verify(String arg0, SSLSession arg1) {return true;}};
}
2.5 测试结果
1)使用工具解密HTTPS前:
如下图所示:
- 完全看不到HTTP流信息。
Application Data
请求内容为密文乱码,无法查看。
在 Application Data 右键,点击 追踪流
,选择 TLS Stream
,看到的也是一团密文乱码,如下所示:


2)实用工具解密HTTPS后:
如下图所示,解析后的 HTTP流 显示出来了,而且内容为明文可见。
在 Application Data 右键,点击 追踪流
,选择 TLS Stream
,看到的也是清晰的明文,如下所示:

三、补充:如果出现未解密成功的情况
如下图所示,如果出现 [TCP Retransmission]
、TCP Previous segment not captured]
、[TCP Out-Of-Order]
这种情况,我们只需要清掉已经抓包内容,重启 Wireshark 程序进行重新抓包即可恢复:
整理完毕,完结撒花~🌻
参考地址:
1.wireshark分析https之javaagent获取jsslkeylog进行解码,https://blog.csdn.net/zhaikaiyun/article/details/125366481