当前位置: 首页 > news >正文

Qt6开发自签名证书的https代理服务器

目标:制作一个具备类似Fiddler、Burpsuit、Wireshark的https协议代理抓包功能,但是集成到自己的app内,这样无需修改系统代理设置,使用QWebengineview通过自建的代理服务器,即可实现https包的实时监测、注入等自定义功能。

实现:

一、https代理服务器

1.使用QSslSocket类收发https包;使用多线程,提升代理服务器的性能。

ProxyClientThread.h

#ifndef PROXYCLIENTTHREAD_H
#define PROXYCLIENTTHREAD_H#include <QObject>
#include <QTcpSocket>
#include <QNetworkProxy>
#include <QThread>
#include <QDebug>
#include <QSslSocket>
#include <QSslConfiguration>
#include <QFile>
#include <QSslKey>
#include <QByteArray>
#include <QtZlib/zlib.h>
#include <QRegularExpression>struct HTTPHDR{QString host;quint16 port;bool newReq;
};struct HTTPHDR2{quint8 CMD;QString CMDi;QString HOST;quint16 PORT;bool status;
};enum ClientConnectionState {InitialRequest,TlsHandshake,DataTransfer
};class ProxyClientThread : public QThread
{Q_OBJECTpublic:ProxyClientThread(qintptr  sockDesc, QObject *parent = 0);~ProxyClientThread();void run();QByteArray LastResquest;private:QSslSocket clientSocket;QSslSocket serverSocket;QSslConfiguration sslConfig;int m_client_state=0;bool m_serverSocketConnected=false;QByteArray cNewReqData;QByteArray clientSockData;QByteArray serverSockData;void processClient();HTTPHDR2 processHeader(QByteArray hdr);bool loadCertificateAndKey();//HTTPHDR getHostInfo(QByteArray httpHeaderPartial);int pid;bool targetFound=false;//是否找到要注入的目标bool istargetHeader=true;//是否头部bool finishInject=false;//已完成注入QString cachedStr="";//缓存的内容;private slots:void clientSockReadyRead();void serverSockConnected();void clientSockDisconnected();void serverSockDisconnected();void serverSockReadyRead();void clientTlsHandOk();void serverSockError(QAbstractSocket::SocketError errorMsg);void clientSockError(QAbstractSocket::SocketError errorMsg);signals:void complete();
};#endif // PROXYCLIENTTHREAD_H

ProxyClientThread.cpp部分代码

#include "proxyclientthread.h"//#define DEBUG 1
QString keyFile="9291.0d30ab5b.js";
QString keyStr="}else e=await V.ImSdk.sendMessage({text:r,textExtra:a,referenceMessage:eQ";
QString injectStr=",window.MySendMsg=e";
ProxyClientThread::ProxyClientThread(qintptr sockDesc, QObject *parent) : QThread(parent)
{this->pid = sockDesc;//服务端连接connect (&this->serverSocket,SIGNAL(disconnected()),this,SLOT(serverSockDisconnected()));connect (&this->serverSocket,SIGNAL(readyRead()),this,SLOT(serverSockReadyRead()));connect (&this->serverSocket,SIGNAL(errorOccurred(QAbstractSocket::SocketError)),this,SLOT(serverSockError(QAbstractSocket::SocketError)));connect (&this->serverSocket,SIGNAL(connected()),this,SLOT(serverSockConnected()));this->serverSocket.setProxy(QNetworkProxy::NoProxy);//客户端m_client_state=InitialRequest;//客户端状态为初始化状态this->clientSocket.setSocketDescriptor(sockDesc);connect(&this->clientSocket, SIGNAL(disconnected()),this,SLOT(clientSockDisconnected()));connect(&this->clientSocket, SIGNAL(readyRead()),this,SLOT(clientSockReadyRead()),Qt::DirectConnection);connect(&this->clientSocket, SIGNAL(encrypted()), this, SLOT(clientTlsHandOk()));connect(&this->clientSocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(clientSockError(QAbstractSocket::SocketError)));
}void ProxyClientThread::clientSockReadyRead()
{this->processClient();return;
}
void ProxyClientThread::processClient()
{HTTPHDR2 pHead;//recieved incoming client packetthis->clientSockData.clear();this->clientSockData = this->clientSocket.readAll();#ifdef DEBUGqDebug()<<this->pid<<"**收到客户端数据"<<this->clientSockData;#endif//查找匹配文件请求QString reqStr=QString(clientSockData);if(reqStr.contains("GET") and reqStr.contains(keyFile)){targetFound=true;qDebug()<<"找到要注入的文件--------------"<<reqStr;//修改请求头,不压缩reqStr.replace("Accept-Encoding: gzip, deflate, br","Accept-Encoding: identity");clientSockData=reqStr.toLocal8Bit();}if (this->serverSocket.state() == QAbstractSocket::ConnectedState){#ifdef DEBUGqDebug() <<this->pid<<": 4.2.向服务器发送请求:";//<<this->clientSockData;#endifserverSocket.write(clientSockData);return;}//处理 headerpHead = this->processHeader(clientSockData.mid(0,100));if (!pHead.status){this->LastResquest = this->clientSockData;return;}//process SSL/TLS Connection;if (pHead.CMD == 3){    //CONNECT类型if (serverSocket.state() == QAbstractSocket::UnconnectedState){#ifdef DEBUGqDebug() <<this->pid<<": 1.收到客户发起CONNECT连接" << pHead.CMD << pHead.HOST << pHead.PORT;#endifm_client_state=TlsHandshake;//握手状态serverSocket.connectToHostEncrypted(pHead.HOST, pHead.PORT);return;}}if (serverSocket.state() == QAbstractSocket::UnconnectedState){#ifdef DEBUGqDebug()<<"***连接服务器";#endifLastResquest=clientSockData;serverSocket.connectToHostEncrypted(pHead.HOST,pHead.PORT);return;}return;
}void ProxyClientThread::clientTlsHandOk(){//clientSockData = clientSocket.readAll();//读取客户端请求#ifdef DEBUGqDebug()<<this->pid<<": 4.<-- 已经和客户端ssl握手成功:"<<LastResquest;#endifserverSocket.write(LastResquest);}...}/** 加载自签名证书
*/
bool ProxyClientThread::loadCertificateAndKey() {QFile certFile(":/certs/server.crt");if (!certFile.open(QIODevice::ReadOnly)) {qWarning() << "Certificate file not found!";return false;}QSslCertificate cert(&certFile);QFile keyFile(":/certs/server.key");if (!keyFile.open(QIODevice::ReadOnly)) {qWarning() << "Private key file not found!";return false;}QSslKey key(&keyFile, QSsl::Rsa);sslConfig.setLocalCertificate(cert);sslConfig.setPrivateKey(key);sslConfig.setProtocol(QSsl::TlsV1_2);return true;
}

3.proxyserver.h

#ifndef PROXYSERVER_H
#define PROXYSERVER_H#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
#include <QTcpServer>
//#include <proxyclient.h>
#include <proxyclientthread.h>class proxyServer : public QTcpServer {Q_OBJECTpublic:explicit proxyServer(QObject* parent = nullptr) : QTcpServer(parent) {}protected:void incomingConnection(qintptr socketDescriptor) override {// 创建子线程并传递 socket 描述符ProxyClientThread* workerThread = new ProxyClientThread(socketDescriptor, this);// 启动子线程workerThread->run();}
};#endif // PROXYSERVER_H

代码的逻辑其实不难,按照代理服务器的连接过程补全相关代码就可以了。

二、QWebengineView部分

使用代理服务连接,该设置仅在app内有效,不影响其他应用。

设置QWebengineView的page忽略证书错误(因为是自签名证书),不处理的话无法访问https页面。

// 配置 QWebEngineView 使用代理
QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", 8787);
QNetworkProxy::setApplicationProxy(proxy);//忽略证书错误
connect(webPage,SIGNAL(certificateError(QWebEngineCertificateError)),this,SLOT(on_certerror(QWebEngineCertificateError)));void xxxx::on_certerror(QWebEngineCertificateError certerror){auto mutableError = const_cast<QWebEngineCertificateError&>(certerror);mutableError.acceptCertificate();qDebug()<<"忽略证书错误。";if(certerror.type()==QWebEngineCertificateError::CertificateAuthorityInvalid){auto error=const_cast<QWebEngineCertificateError&>(certerror);qDebug()<<"忽略证书错误。";error.acceptCertificate();}
}

经过验证,这个方案可行,可以在代理服务器端修改客户端发起的请求,也可以修改服务器端返回的任何数据(已解密过的)后再返回给客户端,但是前提是要做好对应的处理工作,比如Content-length记得要修改。

相关文章:

Qt6开发自签名证书的https代理服务器

目标&#xff1a;制作一个具备类似Fiddler、Burpsuit、Wireshark的https协议代理抓包功能&#xff0c;但是集成到自己的app内&#xff0c;这样无需修改系统代理设置&#xff0c;使用QWebengineview通过自建的代理服务器&#xff0c;即可实现https包的实时监测、注入等自定义功能…...

HarmonyOS:多线程并发-Worker

Worker主要作用是为应用程序提供一个多线程的运行环境&#xff0c;可满足应用程序在执行过程中与宿主线程分离&#xff0c;在后台线程中运行一个脚本进行耗时操作&#xff0c;极大避免类似于计算密集型或高延迟的任务阻塞宿主线程的运行。具体接口信息及使用方法详情请见Worker…...

小程序IOS安全区域优化:safe-area-inset-bottom

ios下边有一个小黑线&#xff0c;位于底部的元素会被黑线阻挡 safe-area-inset-bottom 一 用法及作用&#xff1a; IOS全面屏底部有小黑线&#xff0c;位于底部的元素会被黑线阻挡&#xff0c;可以使用以下样式&#xff1a; .model{padding-bottom: constant(safe-area-ins…...

C++ 中多态性在实际项目中的应用场景

C中的多态性是面向对象编程中的一个核心概念&#xff0c;它允许我们在使用基类指针或引用的情况下&#xff0c;调用派生类对象的特定方法。这种特性在实际项目中有着广泛的应用场景&#xff0c;具体包括但不限于以下几个方面&#xff1a; 1.图形图像处理&#xff1a; 在图形图…...

prettier配置

配置 Prettier 在 VSCode 中自动格式化代码的教程 1. 安装 Prettier VSCode 插件 打开 VSCode。点击左侧活动栏的扩展市场图标(或按 Ctrl+Shift+X)。在搜索栏中输入 Prettier - Code formatter。找到插件并点击 Install 安装它。2. 配置 VSCode 设置 确保 VSCode 配置正确,…...

【基于OpenEuler国产操作系统大数据实验环境搭建】

大数据实验环境搭建 一、实验简介1.1 实验内容1.2 环境及其资源规划 二、实验目的三、实验过程3.1 安装虚拟机软件及操作系统3.2 创建安装目录&#xff08;在主节点上操作&#xff09;3.2 安装JDK及基本设置&#xff08;所有节点都需要操作&#xff09;3.3 安装Hadoop3.4 安装Z…...

期末软件经济学

文章目录 前言复习策略复习名词解释简答题第一章 ppt后记 前言 最近白天都在忙正事&#xff0c;晚上锻炼一下&#xff0c;然后处理一些杂事&#xff0c;现在是晚上十点多&#xff0c;还有一些时间复习一下期末考试。复习到十一点。 复习策略 感觉比较简单&#xff0c;直接刷…...

滑动窗口算法专题

滑动窗口简介 滑动窗口就是利用单调性&#xff0c;配合同向双指针来优化暴力枚举的一种算法。 该算法主要有四个步骤 1. 先进进窗口 2. 判断条件&#xff0c;后续根据条件来判断是出窗口还是进窗口 3. 出窗口 4.更新结果&#xff0c;更新结果这个步骤是不确定的&#xff0c…...

基于Java的世界时区自动计算及时间生成方法

目录 前言 一、zoneinfo简介 1、zoneinfo是什么 2、zoneinfo有什么 二、在Java中进行时区转换 1、Java与zoneInfo 2、Java展示zoneInfo实例 3、Java获取时区ID 三、Java通过经纬度获取时区 1、通过经度求解偏移 2、通过偏移量计算时间 3、统一的处理算法 四、总结 …...

Excel + Notepad + CMD 命令行批量修改文件名

注意&#xff1a;该方式为直接修改原文件的文件名&#xff0c;不会生成新文件 新建Excel文件 A列&#xff1a;固定为 renB列&#xff1a;原文件名称C列&#xff1a;修改后保存的名称B列、C列&#xff0c;需要带文件后缀&#xff0c;为txt文件就是.txt结尾&#xff0c;为png图片…...

OpenGL 几何着色器高级应用

几何着色器高级应用 概念回顾 几何着色器(Geometry Shader)是 OpenGL 管线中的可选着色器阶段,位于顶点着色器(Vertex Shader) 和光栅化阶段 之间。 其核心功能是基于输入的图元(如点、线或三角形),生成新的图元,或对输入的图元进行修改。 几何着色器的执行是以图元…...

【Unity基础】Unity 2D实现拖拽功能的10种方法

方法1. 基于 Update 循环的拖拽方法 (DragDrop2D) 代码概述 using System.Collections; using System.Collections.Generic; using UnityEngine;public class DragDrop2D : MonoBehaviour {bool isDraggable;bool isDragging;Collider2D objectCollider;void Start(){objectC…...

duxapp中兼容多端的 BoxShadow 阴影组件

由于RN 安卓端对阴影的支持不太完善&#xff0c;使用这个组件可以实现阴影效果 在RN端是使用 react-native-fast-shadow 实现的 示例 import { BoxShadow, Text } from /duxui<BoxShadow><Text>这是内容</Text> </BoxShadow>Props 继承自Taro的View…...

服务器---centos上安装docker并使用docker配置jenkins

要在 Docker 中安装 Jenkins 并进行管理,可以按照以下步骤操作: 1. 安装 Docker 首先,确保你的系统已经安装了 Docker。如果尚未安装,可以使用以下命令进行安装: 在 CentOS 上安装 Docker sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://…...

Linux系统操作03|chmod、vim

上文&#xff1a; Linux系统操作02|基本命令-CSDN博客 目录 六、chmod&#xff1a;给文件设置权限 1、字母法 2、数字法&#xff08;用的最多&#xff09; 七、vim&#xff1a;代码编写和文本编辑 1、启动和退出 1️⃣启动 2️⃣退出 2、vim基本操作 六、chmod&#x…...

数据库同步中间件DBSyncer安装配置及使用

1、介绍 DBSyncer&#xff08;英[dbsɪŋkɜː]&#xff0c;美[dbsɪŋkɜː 简称dbs&#xff09;是一款开源的数据同步中间件&#xff0c;提供MySQL、Oracle、SqlServer、PostgreSQL、Elasticsearch(ES)、Kafka、File、SQL等同步场景。支持上传插件自定义同步转换业务&#xf…...

虚幻5描边轮廓材质

很多游戏内都有这种描边效果&#xff0c;挺实用也挺好看的&#xff0c;简单复刻一下 效果演示&#xff1a; Linethickness可以控制轮廓线条的粗细 这样连完&#xff0c;然后放到网格体细节的覆层材质上即可 可以自己更改粗细大小和颜色...

ISP帳戶會記錄什麼資訊?

許多用戶並不知道ISP會記錄有關線上活動的大量資訊。從流覽歷史記錄到數據使用情況&#xff0c;ISP經常收集和保留用戶數據&#xff0c;引發一系列隱私問題。 ISP 記錄哪些數據&#xff1f; ISP可以根據其隱私政策記錄各種類型的資訊。常見的記錄數據包括&#xff1a; 1.流覽…...

Facebook如何避免因IP变动而封号?实用指南

随着Facebook在个人社交与商业推广中的广泛应用&#xff0c;越来越多的用户面临因“IP变动”而被封号的问题。尤其是跨境电商、广告运营者和多账号管理用户&#xff0c;这种情况可能严重影响正常使用和业务发展。那么&#xff0c;如何避免因IP变动导致的封号问题&#xff1f;本…...

EXCEL数据清洗的几个功能总结备忘

目录 0 参考教材 1 用EXCEL进行数据清洗的几个功能 2 删除重复值&#xff1a; 3 找到缺失值等 4 大小写转换 5 类型转化 6 识别空格 0 参考教材 精通EXCEL数据统计与分析&#xff0c;中国&#xff0c;李宗璋用EXCEL学统计学&#xff0c;日EXCEL统计分析与决策&#x…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...