细说 Charles 配置 HTTPS 代理的乱码问题

本文详细介绍了使用Charles工具配置HTTPS代理的过程及原理,包括SSL代理设置与客户端证书安装步骤,并解释了HTTPS请求为何呈现为乱码及Charles如何破解加密。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

细说 Charles 配置 HTTPS 代理的乱码问题

  2017-02-26       计算机网络       HTTPS· SSL· TLS· Charles

最近因工作需要,要用 Charles 来监听 HTTPS 的请求,然而好不容易按照网上的文章配置完成之后,却发现监听的内容居然是一坨乱码。随后进行了一个 SSL 代理配置,和手机证书的安装,才终于获取到了明文。虽然之前有了解 HTTPS 是使用大素数收到进行加密,也知道有一次非对称加密和对称加密,但是经过这次的配置发现对它的根本原理还不是很了解,于是专门研究了一下,才搞明白它的原委。

Charles HTTPS 代理配置

我们先开宗明义,把问题解决一下:要进行 HTTPS 代理配置,其实只需要两个步骤:

  1. 在代理端进行 SSL 代理设置;
  2. 在客户端进行证书安装。

SSL 代理设置

在 Charles 设置 SSL 代理,步骤为:

Proxy –> SSL Proxying Setting –> Enable SSL Proxying

之后便会看到下面的选框:

设置SSL代理

点击 Add,编辑 Loction,按照如下填写:

编辑Location

一路点 OK,这第一步就这样成了。

客户端证书安装

PC 端证书安装

假如代理的是 PC 端的 HTTPS 请求,需要在 PC 上信任 Charles 的证书,步骤为:

Help –> SSL Proxying –> Install Charles Root Certificate

选择 Charles 的证书,并信任此证书:

信任证书

手机端证书安装

在移动端安装证书,步骤为:

Help –> SSL Proxying –>Install Charles Root Certificate on a Mobile Device

之后会弹出这样一个对话框:

安装证书

按照上面的要求,在手机上配置好端口为 8888 的代理之后,访问 http://chls.pro/ssl就可以下载证书并安装了。

实际上做完这两部,就可以在你的 PC 和移动设备上愉快的进行 HTTPS 的代理,并获取明文内容了(具体如何解决问题,也可以参考这篇文章);尽管到这一步就已经达到了实际使用的效果,但我还是产生了这样的疑问:为何进行 HTTPS 代理的配置需要配置 SSL,以及在客户端安装证书呢?之前截获的内容又为什么是乱码呢?

乱码的缘由 —— SSL 加密

其实稍微对 HTTPS 有点认知的童鞋,一开始就不应该对 HTTPS 截取的内容是乱码而感动吃惊:喵的这可是 HTTPS 啊,一个代理就能窃听到获明文内容,那也毫无安全性可言了吧。

那 HTTPS 到底是利用什么原理进行加密的呢?我们可以看到,上面的步骤中,配置 Charles 的第一步就是先配置一个 SSL 代理,实际上 HTTPS 的那个 S 也可以翻译为 HTTP over SSL/TLS,这个 SSL 正是 HTTP 加密依赖的基础协议。

SSL/TLS 是传输层安全协议,与其他应用层协议(如 HTTP/FTP 等)独立无关,也就是说,在应用层协议开始通信之前,SSL/TLS 协议就已经完成了相关的加密工作,后续协议传输的内容已经是加密数据了。所以其实 HTTP 还是那个 HTTP,但传输的内容早已变成天书,这也就是我们在用 Charles 进行代理的时候,看到一堆乱码的原因。

不过快播的审判员说的好:『文件加密了,你为什么不解密呢?』是啊,为什么经过 SSL/TLS 协议处理过的内容,不能够被解密呢?这里就涉及到 SSL 协议的基本原理,我们用写信,来模拟一下这个加密的过程:

  1. 小明和小王是一对好基友,但是远隔万水千山,只能通过写信来传递消息。俩人每天的信件都是通过邮递员小红来传递的,这俩人每天纸条上明文写着信息,小红也天天看的不亦乐乎,这就是 HTTP。
  2. 时间久了,两人发现不行,比如有时候会传递一些不和谐的内容,不希望小红这样的腐女看到;于是小明灵机一动,换成葬爱家族的杀马特火星文来进行通信;小王看后,心领神会。由于转换方式两人都知道,这就是对称加密技术
  3. 然而好景不长,小红勤学苦练,终于练成了火星文十级,又能看懂俩人加密的内容了。俩人必须要更换加密方式,但是更换的加密方式也只能通过小红来传递,所以这个加密的手段很难瞒住小红,这就是 HTTP 的不安全性。
  4. 正好小明是一位博学的哲♂学家,他立刻写了封信给小王:把你家储物间箱子的上那把挂锁寄过来!小王看后立刻拿出了那把 82 年的挂锁,把它打开并寄给了小明。这个锁大家都能看到,但只有小王有钥匙,这就是传说中的非对称加密,锁就是公钥,小王的钥匙就是私钥。
  5. 小明收到后,仔细研究了那把锁,上面烫着『隔壁老王』四个鎏金大字,正是王家祖传的锁,这就是验证服务端的数字证书
  6. 于是小明放心的把新的加密方式写在信中,放到盒子里,然后用锁锁上。由于小红没有钥匙,没法查看盒子里到底写了啥,只能原样送过去。小王收到后,用自己的钥匙打开了锁,获得了新的加密方式。这就完成了 SSL 协议的握手

当然,上面的过程描述的非常粗糙,小明和小王在互相寄锁的时候,还需传递随机数来辅助生产最终的加密方式(也是一个随机数,称之为 Premaster secret);有兴趣的兄贵们可以看看文末的参考文章。

Charles 的破解之道

那么问题就来了:Charles 作为一只小红,是怎么破解上述加密通信的呢?莫非她大力出奇迹,直接砸了锁?我们知道,要砸锁是不太现实的,这等于要对大素数的乘积进行因式分解,现阶段下还做不到;因此 Charles 就做了一件最简单的事情:伪装成小明(也就是中间人攻击)。

Charles 的官网上是这么说的:

Charles 作为一个中间人来进行 HTTPS 的代理,让我们检测到浏览器和 SSL web 服务端之间的明文通信。
Charles 把自己变成一个中间人来达到这一目的。你的浏览器是收不到服务端证书的,Charles 会用自己的根证书动态签发一张证书,然后 Charles 来接受服务端的证书,你的浏览器接受 Charles 的证书。

Charles 仍然通过 SSL 与服务端进行通信,但通信是通过浏览器到 Charles,然后在从 Charles 到服务器。

那么上文所说的根证书动态签发证书,指的是什么意思呢?这里就说到了证书的信任链体系,这是一个树状的结构,全球有为数不多的根证书颁发机构,授权二级证书颁发机构进行证书颁发;而只要用户信任了根证书,就会对其下属二级机构颁发的所有证书都予以信任。

证书颁发体系

上图可以看到 VeriSign 就是根证书颁发机构,而知乎的证书是由其二级证书颁发机构颁发的。由于操作系统里内置了对 VeriSign 的授信,因此知乎的地址栏才能有一把绿色的小锁。

因此 Charles 如果想对所有的域名颁发证书,必须要有一个根证书;用户信任了这个根证书,所有走 Charles 代理的 HTTPS 就都能被窃听了。

我们在用小红为例,复现一下这个场景:

  1. 小红拿到锁以后,先扣着不发,然后掏出了自己的锁寄给小明,这就是 Charles 签发了自己根证书;
  2. 小明一看这把锁不是正宗王家的,但是小红家的锁,似乎也可以相信,这就是信任了 Charles 的根证书
  3. 小明把加密方式写进去,然后用小红的锁锁起来了,小红打开之后研究了加密方式,发现两人是在用水星文进行交流,瞬间水星文也达到了十级,然后在换上小王的锁锁上了盒子,还给了小王;
  4. 小王毫不知情,之后俩人用水星文进行交流,但内容已经全被小红捕获到了。

搞明白这些之后,我们再来看一下,为什么要进行 Charles 的那两个配置呢?

  1. 设置 SSL 代理:因为默认 HTTP 请求走的是 80 端口,HTTPS 请求走的是 443 端口,不设置的话 Charles 仅会默认更改系统的 HTTP 代理,只有 HTTP 流量会走 Charles,而设置这个 HTTPS 的流量才会从这儿走;
  2. 安装 Charles 的根证书:根据信任链,只要安装一下 Charles 的根证书,之后 Charles 颁发的所有域名的证书都能被自动信任,因此 HTTPS 就都能被窃听了。

把证书的信任链翻译到锁上,等于小明会预先信任几个大厂生产的锁,比如只要是老王牌的锁,那我都相信,其他人也可以用这类锁来跟我要加密方式;Charles 等于创造了一个小红五金厂,把所有代理的请求都挂上了小红锁。那么 12306 其实跟小红一样,由于某些原因没有大厂申请一个锁,而是自己开了一个老铁五金厂,然后跟用户说:『相信我铁道部的老铁五金厂的锁吧,不然你就憋想回家!』

用户还能怎么办?只能含着泪点确认:『老铁,没毛病!』

## 代码概述 你希望了解如何配置 CORS(跨域资源共享),这是在 Web 开发中处理跨域请求的关键步骤。CORS 的配置方式取决于后端所使用的框架或服务器类型,常见的 Java 后端框架如 Spring Boot 提供了灵活的配置方法。 --- ## 代码解析 ### 在 Spring Boot 中配置 CORS 的常见方法: #### 方法一:使用 `@CrossOrigin` 注解(适用于单个接口) ```java @RestController @RequestMapping("/api") public class MyController { @CrossOrigin(origins = "http://127.0.0.1:8888") // 允许指定源访问 @GetMapping("/data") public ResponseEntity<String> getData() { return ResponseEntity.ok("Hello, CORS!"); } } ``` - **作用**:这个注解可以加在类或方法上,控制特定接口的跨域策略。 - **适用场景**:适用于对个别接口进行跨域控制。 --- #### 方法二:全局配置 CORS(推荐) 创建一个配置类,通过实现 `WebMvcConfigurer` 接口来设置全局的 CORS 策略。 ```java @Configuration @EnableWebMvc public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 匹配所有以 /api 开头的路径 .allowedOrigins("http://127.0.0.1:8888") // 指定允许的来源 .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法 .allowedHeaders("*") // 允许所有头部 .exposedHeaders("Authorization") // 暴露给前端的头部 .allowCredentials(true); // 是否允许携带凭据(如 Cookie) } } ``` - **作用**:该配置为整个应用中的某些 API 路径统一设置跨域规则。 - **适用场景**:适合多个接口需要相同 CORS 设置的情况,便于统一管理。 --- #### 方法三:使用过滤器手动添加响应头(更底层) ```java @Component public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8888"); response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); response.setHeader("Access-Control-Allow-Credentials", "true"); if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } } ``` - **作用**:直接操作 HTTP 响应头,实现跨域支持。 - **适用场景**:适用于不使用 Spring MVC 或需要高度定制化 CORS 行为的项目。 --- ## 知识点 - **HTTP响应头** HTTP 响应头用于传输服务器与客户端通信时的元数据信息,CORS 依赖于其中的 `Access-Control-Allow-*` 头部字段。 - **Spring Boot 配置机制** Spring Boot 支持通过注解和配置类实现功能定制,是现代 Java Web 开发中最常用的框架之一。 - **跨域资源共享(CORS)** CORS 是浏览器的安全策略机制,用于解决跨域请求问题,需服务器返回正确响应头才能成功。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值