Charles 使用

转至元数据结尾
转至元数据起始

为啥要装charles?

公司已经逐渐以MAC笔记本替换原安装WINDOWS的联想笔记本,原来在WINDOWS上,多使用fiddler做为抓包、host mapping工具搭建测试环境,在MAC OSX系统中也有一款与fiddler类似的软件叫charles,但实践上,多数同学还是觉得不好用,而不得不装一个WINDOWS虚拟机继续使用fiddler。MAC上的磁盘空间较小,而且虚机也占用内存资源,能不能使用charles完全取代fiddler,从而干掉这个虚拟机?答案是肯定的。本文分享一下自己的实践经验,和所遇到的坑,希望可以给其它同学一些帮助。

要达到的目的:

在钱包部门,开发&测试&上线过程中,经常需要切换线下&线上环境。总体诉求如下:

其中:

  1. 客户端有手机、PC浏览器。环境共有三类:线下、预览、线上。每个业务都有三个端:PC, H5, SDK。
  2. 访问客户端有两种:SDK和浏览器。SDK以APP形式发布,其demo版本可修改访问host地址,正常版本直接访问线上;浏览器则默认访问线上。

于是,我们需要 charles 做到两项功能:

    1. 抓到并能解析HTTPS请求的包。
    2. 对来自浏览器的访问,不仅要抓包,还能够做 host 映射,以切换线上&线下环境。

 

开始配置

安装&破解

本例安装的版本是 v4.0.2,不建议安装3.X版本,BUG较多。安装后,最重要的是破解,在MAC终端执行:

 

终端执行这些破解: 
charles=/Applications/Charles.app/Contents/Java/charles.jar
dir=charleshack
mkdir $dir
cd $dir
cat >> License.java <<EOF
> package com.xk72.charles;
> public final class License {
>     public static boolean a() { return true; }
>     public static String b() { return "http://www.gfzj.us"; }
>     public static String a(String name, String key) { return null; }
> }
> EOF
javac -encoding UTF-8 License.java -d .&& jar -uvf $charles com/xk72/charles/License.class
cd .. && rm -rf $dir 

 

解析HTTPS请求

charles抓HTTPS包原理

我们https的数据传输是加密的,当我们与https server通信时,charles或fiddler这类代理本身是无法解密我们的数据的,之所以还能实现解析包,是因为charles代理是以 “中间人” (man-in-the-middle) 的方式工作:client https 连接的是charles,SSL证书由charles下发,因此client到charles这一步的数据, charles是可以解密的,之后才是charles和真正的server发生连接。

我们需要配置charles,使它能够抓到本机浏览器的包,以及手机APP的包。

配置抓包本机浏览器

  1. Proxy -> SSL Proxy Settings...  确认 Enable SSL Proxying 勾选了,底下的 Location * 也勾选了:

 

2. 勾选 Proxy -> macOS Proxy, 和 Mozilla Firefox Proxy。

关于 Mozilla Firefox Proxy,本来charles和 Firefox 有定制的,FF插件中心甚至有charles插件安装,但该插件已经失效了,不过,我们还是可以使用常规的方法来达到目的,一会会讲到,这里先勾上这两个选项再说。

3. 安装 charles 根证书:

a) help->SSL Proxying->Install Charles Root Certificate

 

b) 在打开的钥匙串管理界面中,注意,默认显示的是安装到“登录”,这里需要选择安装到 “系统”
c) 在OSX的程序导航中搜 key 打开钥匙管理界面,证书 -> 找到 charles 的证书,点开并设置 “始终信任”:
4. 配置Firefox走charles代理:
a) 安装最新版的Firefox,此时是54.
b) 打开Firefox的 首选项 -> 高级 -> 网络 -> 手动配置代理: HTTP代理:127.0.0.1,端口:8888,勾选 “为所有协议使用相同代理 ”:
这里端口 8888 为charles默认的代理端口(可修改)。
此时,我们在PC机上的抓包配置完成了,可以使用 Firefox 访问一下 https://www.baifubao.com,就可以看到 charles 成功的抓取并解析了 https 请求包。
这里使用Firefox,不用chrome,主要还是因为chrome最终我也没有配置好,chrome对证书的校验太过严格,当在线下&线上环境来回切时,证书总是过不了检查。对其工作原理我也没能了解,如果有谁成功配置好了,请告诉我~ 

移动端 (以IOS为例)

这里配置IOS,以使charles抓取APP以及手机浏览器的包:

1. iphone上用safari打开 https://chls.pro/ssl安装并信任证书。
2. 设置 -> 通用 -> 关于本机 -> 证书 -> 找到 charles证书,打开信任。
3. 在iphone的设置 -> 无线局域网 -> 点开正连接的WIFI -> HTTP代理 -> 手动: 服务器填写 chareles的IP (charles的IP通过 charles菜单栏 -> help -> local ip adress),端口默认为 8888.
至此,移动端就设置好了。
至此,charles的抓包功能配置完毕。我们已经实现了 charles 抓取本机浏览器,以及移动端的HTTPS包。但还缺一项功能:host 映射。

Host映射

光有抓包,若没有host映射,是访问不了线下环境的,charles提供了 map local 和 map remote 功能,其中 map local 是将要访问的地址映射到本地文件,而map remote是将要访问的地址映射到其它地址,即我们需要的host映射,我们可以配置将 https://www.baifubao.com 映射成线下地址,以供调试。
  1. Tools -> Map remote... 配置需要映射的地址,然后勾选 “Enable Map Remote”:
2. 配置项的填写:
这里坑不少,我曾在配置这里绕了些弯,这里提几个注意项:
a) 如果需要所有 baifubao.com 相关的 URI都要映射,那么, Path, Query 项留空。
b) Host支持 * 通配二级子域名。
c) 注意 “Preserve Host header”, 需要勾选上。若不勾选,charles在做host mapping之后,会修改请求 header中的host为 Map To 的IP,比如本来该 host 为 www.baifubao.com,会被改为 10.52.180.22. 这可能会导致nginx接入层配置失效:因为nginx配置会根据这个 host 来转发请求到相应的服务器。
好了。配置全部完成,此时可以自如的线上线下环境随便切了。

其它问题

顺利的配置是比较简单的中,但整个过程还是会遇到其它问题,记录如下。

证书过期错误

在我使用Firefox访问线下或是预览机环境时,Firefox提示证书已过期,而该网站使用HSTS连接,不可添加证书例外云去,网页无法打开。
之前使用fiddler时并没有报证书错误,我一直疑惑的是:Firefox使用的是charles的证书,而charles证书好好的,为啥还会提示server本身的证书错误呢?只能权且认为charles会上报server的证书错误给浏览器吧。
anyway, 既然是线下环境,我们自己签发一个证书即可。
自签发证书
在Linux开发机上,使用openssl工具生成证书:
openssl genrsa -des3 -out ssl.key 2048
mv ssl.key xxx.key
openssl rsa -in xxx.key -out ssl.key
rm xxx.key
然后根据这个key文件生成证书请求文件
openssl req -new -key ssl.key -out ssl.csr
以上命令生成时候要填很多东西,随便填吧。最后根据这2个文件生成crt证书文件:
openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt
这里3650是证书有效期(天),随便写。最后使用到的文件是key和crt文件。
生成了证书文件后,替换nginx access层的配置,之后重启nginx:
ssl_certificate keys/ssl.crt;
ssl_certificate_key keys/ssl.key; 
此时再使用 Firefox 访问线下环境,OK了。

使用Firefox打开 https://m.baifubao.com想访问H5页面,但总是被路由到PC的主页

这个与配置本身无关,是Firefox默认上传的UA是PC格式的,后端nginx根据UA判断端信息,然后返回了PC版本的内容。

解决:打开FF的开发者工具-> 响应设计模式 -> 在 “自定义User Agent” 一栏,输入移动端的UA信息:
模拟IOS:
Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1
Android:
Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2882.4 Mobile Safari/537.36 

不可战胜的Chrome

使用chrome最主要的问题仍然在访问线下环境时,报证书错误。尝试了不少方法仍未成功(求救ing。。)。以下记录我试过的但无效的招数:
  • 自签发证书。仍报证书错误  NET::ERR_CERT_COMMON_NAME_INVALID,网上搜罗一通重签发证书,没能成功。
  • 以insecure mode启动chrome,试图让chrome忽略一切证书错误:
    • /Applications/Google\ Chrome\ 2.app/Contents/MacOS/Google\ Chrome --args --disable-web-security --allow-running-insecure-content --user-data-dir=/Users/baidu/chrome_insecure_user_data
    • 这在WINDOWS上是好用的,但OSX上,chrome仍然会报证书错误。
  • 在OSX系统钥匙串中添加线下的 baifubao.com证书。
  • 清除chrome缓存,在HSTS设置中删除 baifubao.com 相关信息。
这一切都无法阻止chrome识别出线下证书的不安全。。chrome,你安全,你牛逼。。。
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页