Mac使用Charles抓取macOS/iOS/Android数据包

Mac使用Charles抓取macOS/iOS/Android数据包

Charles抓包原理

抓包的原理

要想抓一个系统(macOS/iOS/Android)的数据包(即网络请求),你必须让该系统的所有请求都经过Charles,这样Charles才能从经过自己身上的所有请求中过滤出(即抓到)你想要的请求。那怎样才能让一个系统的所有请求经过Charles呢?答案是:代理!

Charles启动后,会监听一个或两个端口,此时它就是一个“代理服务器”,我们只需要把你要抓包的系统的代理设置为Charles的ip和端口即可。

对于macOS来说,因为Charles就在本机,所以代理ip是127.0.0.1,而对于手机来说,ip就是你运行Charles的那台电脑的局域网ip(按住option键,单击macOS上的WIFI图标即可看到它的ip),端口的话,在启动Charles之前是可以设置的,下面会说到。

监听一个或两个端口

在Charles顶部菜单的proxyproxy settingshttp proxysocks proxy中设置这一个或两个端口(如下图)
image.jpg

http proxysocks proxy是两个不同层级的代理,http proxy是应用层的,它只能代理http/https/websocket请求,而socks proxy是代理传输层流量的,用到非http类协议的软件,就需要socks proxy来代理,所以一般来说需要把socks proxy勾上(HTTP Proxy前面是没有勾的,因为它是必须开启的)。

启动后我们使用lsof-i:xxx(xxx是端口号)来检测一个端口是否被占用,可以看到,8888和8889端口被Charles占用(也就是说Charles在监听这两个端口的数据)
-w716

关于科学上网

在使用Charles时请先关闭科学上网工具,否则有可能会冲突,至于既要使用Charles又要科学上网的方法,后面这里有说到。

抓取macOS(本机)的请求

在mac上安装根证书(用于支持https抓包)

点击顶部菜单栏中的helpSSL ProxyingInstall Charles Root Certificate
Xnip2018-11-11_13-47-53.png

上一步点击Install Charles Root Certificate后它会自动打开钥匙串,显示Add Certificates,不用任何修改,直接点add即可添加
image.jpg

双击证书→在弹出的窗口中点Trust(信任)左侧的三角箭头展开Trust选项→选择Always Trust(始终信任),然后直接关闭窗口(没有保存按钮,也不用点保存,直接点关闭窗口即可,关闭时它会弹出要输入系统密码以把这个更改保存到系统中,输入密码后点击Update Settings(更新设置)即可,然后就可以把钥匙串窗口关掉了)
image.jpg

ProxySSL Proxy Settings里,要把*:443加上(如果没有的话),*表示任何ip,:443表示443端口,因为443端口是https的端口,所以要允许,否则无法抓取https的包
Xnip2018-11-11_15-47-51.png
Xnip2018-11-11_14-35-28.png

设置监听端口和自动设置代理

proxyproxy settingsmacOS里,把所有都勾上,那么每次启动的时候,Charles会自动把自己的代理端口设置到系统代理设置里面去
image.jpg
当然在启动之后,你还可以通过点击proxymacOS proxy来切换系统是否走Charles代理。


其实它设置的原理,就是在系统偏好设置网络→选中当前使用的网卡→点击右下角高级代理里设置(如下图),也就是说,你也可以手动设置
image.jpg

前面说“选中当前使用的网卡”,一般是WiFi,如果你是用扩展坞(转接头)插网线上网的,那就选择对应的有线网卡即可。

开始抓包

上面全部配置好,随便刷新一个网页,在Charles里看,应该就能看到请求了(看不到请一步一步对一下,看漏了哪里,实在不行关掉Charles再开看看)
Xnip2018-11-11_15-59-32.png

抓取iPhone手机的请求

安装根证书

Xnip2018-11-11_17-57-03.png

这里说的很清楚,配置你的设备以使用Charles作为它在http://192.168.0.102:8888的代理,然后用iPhone的Safari浏览器访问这个地址chls.pro/ssl来安装证书。
Xnip2018-11-11_17-56-29.png

根据上面所说的,我们在iPhone的设置无线局域网
Xnip2018-11-11_18-18-33.png

点右边那个¡
Xnip2018-11-11_18-20-49.png

点击配置代理
Xnip2018-11-11_18-26-48.png

选择手动,然后填写Charles提示的IP和端口,注意,ip和端口不要照填我的,上面Charles弹出的那个提示框里有你自己的ip和端口。
Xnip2018-11-11_18-29-10.png

点击存储保存,保存后mac上的Charles会提示有一个链接试图连接Charles,这个就是手机的链接,这时当然要允许,即点左边的Allow(允许)按钮。如果你不小心点了Deny(即拒绝),你可以在顶部菜单proxyAccess Control Settings里自己添加
Xnip2018-11-11_18-35-14.png

允许之后,iPhone打开Safari浏览器,输入前面Charles提示的地址:chls.pro/ssl,然后根据提示一步一步安装证书。

点击允许
Xnip2018-11-11_18-46-03.png

点击右上角的安装(2020.10.16注:在iOS14中发现需要自己去设置通用描述文件里找到下载的描述文件,点击安装)
Xnip2018-11-11_18-46-15.png

输入密码
Xnip2018-11-11_18-46-39.png

点击安装
Xnip2018-11-11_18-46-29.png

点击右上角的完成
Xnip2018-11-11_18-46-57.png

开始抓包

手机随便打开一个app或网页,随便点一下,即可看到Charles抓到的请求(但是网页或app接口不能是你电脑本地的)
Xnip2018-11-11_18-38-52.png
Xnip2018-11-11_18-38-34.png

设置调试本地网站

前面说了,抓包不能抓本地网站或接口,其原因是,本地域名是直接在hosts文件中指定的,公网DNS是找不到这个域名的,所以我们要手动指定,mac可以直接在hosts文件指定,但iOS是不可能修改hosts文件的(除非越狱),那怎么办呢?还好,Charles提供了这个功能。

在Charles的ToolsSpoofing里,可以添加DNS映射(如下图),由于iPhone所有请求都代理到了Charles,所以Charles想把某个域名指向哪个ip,它就可以指向它(同样可以用于在线上的但域名还没生效的网站)
image.jpg

增加:据测试,其实直接改电脑里的/etc/hosts也是可以的,因为手机的请求代理到电脑后,网络也走电脑的,DNS解析自然也会走电脑的。

另外不使用的时候手机要关闭代理,否则会上不了网(离开你办公室后),或者很慢(因为请求被Charles抓包了,肯定比较慢)。

还有,其实不安装证书直接设置代理也是可以的,只是这样就只能抓http的包,https的就抓不了,而现在大多服务都用https了,所以还是要安装证书!

抓取Android手机的请求

安卓与iPhone完全一样,但有些浏览器可能无法安装证书,遇到这个问题可以换换浏览器。

手机使用pac

忘关代理无法上网问题

你可能遇到过这种情况:手机用WIFI怎么也上不了网,但用流量就可以。于是你怀疑WIFI是不是有问题,但是你电脑用的也是同一个WIFI,或者问其它人连的也是这个WIFI,都没有问题,那说明也不是WIFI的问题。

然后你找了好久,卧槽,原来是因为测试接口抓包的时候把手机设置代理到电脑的Charles上,忘记关掉了,于是你把它关掉就可以上网了,但是下次测试接口又得重新设置代理,搞来搞去特别麻烦。

解决忘记关代理的方法

事实上我们使用自动代理,就可以实现“即使忘了关代理也不会上不了网”。自动代理是让配置文件决定要不要代理,配置文件我们叫pac文件(pac: proxy auto config),后缀也是.pac结尾。

直接在手机的代理里选择自动代理,然后填入pac文件地址即可(如下图)
Xnip2018-11-11_18-27-11.png

现在有两个问题

  • 1.PAC文件怎么写?
  • 2.PAC文件地址如何获取?

PAC文件怎么写?

pac文件是用js写的,它有很多预定义的函数(查看),最终决定是否走代理的是下边这个函数,网络请求会根据这个函数的返回值来判断是否走代理

function FindProxyForURL(url, host) {
    return 'DIRECT';
}

返回值一定是一个字符串,它有几种值:

DIRECT 不走代理
PROXY 192.168.1.232:8888 走http或https代理
SOCKS 192.168.1.232:8889 走传输层代理
SOCKS5 192.168.1.232:8889 走传输层代理

这些代理方式可以串联起来,用分号;隔开,比如:

return "PROXY 192.168.1.232:8888; SOCKS5 192.168.1.232:8889; SOCKS 192.168.1.232:8889; DIRECT";

上边这句的意思是先走PROXY 192.168.1.232:8888;,即http(s)代理,如果这个代理不通,它会走下一个,下一个再不通,它再下一个,直至最后的DIRECT,DIRECT表示直连,不走代理。

上边的SOCKS5和SOCKS其实相当于是同一个,SOCKS5的5是指版本,现在所有的SOCKS代理都是用这个版本了(毕竟比较新),而用SOCKS的原因,是因为据说Safari浏览器是不识别SOCKS5关键字的,不过Safari一样是用SOCKS5协议的,只不过关键字要写成SOCKS而已。

PAC文件还支持其它函数,如果你需要使用,可以自己上网查,我这边目前用不到其它函数,所以就不介绍了。

下边是我自己使用的PAC文件,用于手机/pad等,把你需要走代理的域名填到下边“要走代理的域名”数组里,则手机访问这些域名时就会走你指定的代理,否则会直连(效果跟没有设置PAC代理一样)

var direct = 'DIRECT';

//代理的ip
var lan_ip = '192.168.1.232';

//代理的http(s)端口和socks端口
var http_port = 8888;
var socks_port = 8889;

//最终返回的代理字符串
var proxy = 'PROXY ' + lan_ip + ':' + http_port + '; SOCKS5 ' + lan_ip + ':' + socks_port + '; SOCKS ' + lan_ip + ':' + socks_port + '; ' + direct;
//alert(proxy)

//要走代理的域名(二级或三级域名)
var local_dev_host = [
    "www.test.com",
    "picuploader.com",
];

var local_dev_obj = {};
for (var i = 0; i < local_dev_host.length; i += 1) {
    local_dev_obj[local_dev_host[i]] = true;
}

function host2domain(host) {
    var dotpos = host.lastIndexOf(".");
    if (dotpos === -1)
        return host;
    // Find the second last dot
    dotpos = host.lastIndexOf(".", dotpos - 1);
    if (dotpos === -1)
        return host;
    return host.substring(dotpos + 1);
};

//FindProxyForURL函数用于最终返回代理字符串
function FindProxyForURL(url, host) {
    //alert(JSON.stringify(local_dev_obj));
    var level2domain = host2domain(host);
    var proxy_cmd = (local_dev_obj[host]!==undefined || local_dev_obj[level2domain]!==undefined) ? proxy : direct;
    //alert(proxy_cmd);
    return proxy_cmd;
}

PAC文件地址如何获取?

很简单,使用nginx配置一个访问地址即可,但是却分本地和线上。

如果你在本地电脑配置,最好不要用域名,而是直接用ip。因为用域名还要自己指定DNS,但由于手机不方便设置DNS(特别是iOS),所以还要使用Charles来设置,我实测在本地电脑可以直接访问到,但在手机上访问不知道为什么要输入电脑的账号密码,这样肯定是没法用的,因为我是在浏览器里测试访问需要账号密码,但是你直正设置到代理里是没有地方让你输入账号密码的,但是不输入账号密码又无法访问,所以相当于这种方法是不行的。


如果你是本地,我建议你本地设置一个默认的localhost域名,并且localhost可访问目录autoindex on;,这样只要你把前面的pac代码保存成proxy.pac文件并放到root关键字指定的目录中(我这里是/Users/bruce/www)即可用http://192.168.1.232/proxy.pac来访问(其中192.168.1.232是我电脑的ip,你换成你电脑的ip就行)

server {
    listen       80 default_server;
    server_name  localhost;

    charset utf-8;

    access_log  /usr/local/var/log/nginx/localhost.access.log;
    error_log   /usr/local/var/log/nginx/localhost.error.log;

    root   /Users/bruce/www;

    autoindex on;
    autoindex_exact_size off;
    #显示格式,默认为html,另外还可以为xml/json/jsonp
    autoindex_format html;
    #是否显示当地时间(不设置默认off,off则显示UTC时间)
    autoindex_localtime on;

    location / {
        gzip on;
        gzip_min_length 1k;
        gzip_buffers 4 16k;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        include fastcgi.conf;
    }
}

说实话我不推荐本地,因为本地经常有可能因为电脑睡眠了手机就上不了网了,国内的话其实gitee上放个proxy.pac应该也是没问题的,不一定需要有自己的服务器。


如果你有外网服务器,我建议你用外网服务器来搭一个pac文件访问地址,因为这样手机可以不依赖于电脑,一直可以获取该文件。

把前面的pac代码保存成proxy.pac文件,并放到/path/to/pac/目录下,然后使用以下nginx配置即可(把域名和root路径换成你的),浏览器访问http://pac.example.com/proxy.pac即可访问到该文件,浏览器测试访问没问题后把它填到前面说的pac代理里即可

server {
    listen 80;
    server_name pac.example.com;

    default_type application/x-ns-proxy-autoconfig;

    access_log /path/to/pac.example.com.access.log combined buffer=1k;
    error_log /path/to/pac.example.com.error.log error;

    root /path/to/pac;

    location = /proxy.pac {
        try_files $uri /proxy.pac;
    }
}

最后,要特别注意,使用pac时不要开启科学上网软件(如果你手机有的话),否则我们设置的PAC会失效。因为代理软件会把手机系统的请求全部设置成走到它上边去,我们自己设置的PAC路径就不会被使用,所以就会导致用不了。

其它参考:
PAC自动代理文件格式,教你如何写PAC文件
PAC 文件及其调试

Charles与科学上网工具同时使用

对科学上网原理稍微了解一点的童鞋,应该知道,科学上网客户端的“全局模式”、“pac模式”、“手动模式”,还有后来的什么“清除系统代理”、“自动配置系统代理”、“不改变系统代理”等等,无论它是什么名字,都只是叫法不同,其实就是一个设置代理的快捷菜单,它本质就是对系统的网络代理选项进行设置,也就是说,即使不用这些菜单,你也可以手动设置.

点击系统偏好设置网络→选择当前使用的网卡(如WIFI)→右下角高级...→选择代理选项卡(如下图所示)
image.jpg

由于Charles和科学上网工具两者都是对系统的代理进行设置,所以肯定会冲突,所以在使用Charles时,你需要先关闭你的科学上网工具(如果你有的话),否则可能会有导致你无法抓包。

当然其实是可以开着的,两者其实是相互覆盖的,比如你正在用着科学上网工具,你一打开Charles,Charles就会把系统代理设置到Charles监听的端口里,这时你肯定就无法科学上网了。如果你再调一次科学上网工具的代理模式(比如从自动模式调到全局模式),又或者关一下再开一下科学上网软件,则它会把系统的代理设置到它身上,Charles就会失效。

有些人可能会说,我既想用Charles,又想科学上网怎么办?我想用Charles抓包的接口,就是google的,就是facebook的,怎么办?其实是可以的,只需要从Charles再设置一个代理即可,用业内术语来说就是“套娃”。

首先要把科学上网工具的代理模式设置成“手动模式”或“清除系统代理”(新版本改成这个了)模式,然后在科学上网工具里找到http和socks监听端口是多少,然后取消再重新勾选一下Charles的proxymacOS proxy(为了让Charles重新接管系统的网络代理,因为前面设置科学上网软件的代理模式时,它是会覆盖Charles的代理设置的)。

Charles接管代理后,点击Charles的proxyExternal Proxy Settings,然后在弹出的窗口中勾选一下Use External Proxy Servers
image.jpg

然后勾选下边的三个代理出口,并分别填上科学上网工具对应的ip和端口,一般来说,ip肯定就是127.0.0.1了(当然如果你用路由器做科学上网的话,那么这个ip就是你路由器的ip,比如有可能是192.168.1.1,这得具体看你路由器ip)。而对于端口,HTTP和HTTPS的端口是一样的(事实上科学上网工具是不区分HTTP和HTTPS的),只有SOCKS端口不同,你在你的科学上网工具里找到对应监听的端口,把它填到下边的对应位置里即可

  • Web Proxy(HTTP)
  • Secure Web Proxy(HTTPS)
  • SOCKS Proxy

其实就相当于多加了一层,我们来对比一下使用Charles前后,科学上网的变化:

使用Charles前:浏览器→科学上网客户端→外网
使用Charles后:浏览器→Charles→科学上网客户端→外网

可以看到,使用了Charles后,浏览器的请求先给Charles,再由Charles交给科学上网客户端,浏览器的请求怎么给Charles呢?就是在系统偏好设置网络→找到对应网络(如WIFI或有线)→右下角高级代理里面设置的。而Charles再转发给科学上网工具,就是前面说的,在Charles的proxyExternal Proxy Settings里设置。


结束使用Charels时,需要把科学上网软件重新设置一次自动代理模式(或者全局模式)才能让科学上网软件重新起作用,否则有可能无法科学上网,我之所以说“有可能”,是因为目前我这里测试的情况是,我关掉Charles或者在proxymacOS里把勾去掉,它会自动切换回科学上网的代理,可以说是非常自动,我估计是Charles在设置前就保存了之前的设置吧,反正如果无法正常抓包,记得检查一下代理是否设置正确就行。


参考:Charles抓包软件使用简介

打赏
订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

Mac使用Charles抓取macOS/iOS/Android数据包