ここでは、GUIを一切使用せずにCharles Proxyを使用して暗号化通信(HTTPS)のログをキャプチャする方法を紹介します。WindowsやMacなどGUIが使用できる環境ではCharles ProxyのGUIを使用して行えばいいのですが、LinuxサーバーなどGUIが使用できずCLIオンリーの環境で、通信のデバッグを行いたいという需要があったためリサーチしてこの方法にたどり着きました。
※ちなみに別の方法として、環境変数SSLKEYLOGFILE
を定義し、pre-master-secretをファイルへと出力しながらtcpdump
を採取するという手段もあると思います。
利用環境
- OS:
Ubuntu 20.04.4 LTS (GNU/Linux 4.4.0-19041-Microsoft x86_64)
本稿では、Debian系のLinuxディストリビューションを使用してます(ちなみに上記バージョン情報の"Microsoft"からわかる通り、WSLのUbuntuです)が、Red hat系のディストリビューションでも(一部コマンドは異なるものの)同様の手順が実施可能な想定です。
Charles Proxyのインストール
Charles Proxyの公式サイトに記載の手順に従ってCharles Proxyのインストールを行います(その記事に、各コマンドの解説も記載されてます)。
$ sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 1AD28806
$ sudo sh -c 'echo deb https://www.charlesproxy.com/packages/apt/ charles-proxy main > /etc/apt/sources.list.d/charles.list'
$ sudo apt-get update
$ sudo apt-get install charles-proxy
インストール後、以下のコマンドを実行しバージョン情報が取得できればOKです。執筆時点ではバージョン4.6.3になりました。
$ charles -version
Charles Proxy 4.6.3
Charles Proxyのルート証明書のインストール
HTTPS通信の中身を確認するにあたり、Charles Proxyのルート証明書をエクスポートし、そのCAを信頼済みにする必要があります。
エクスポートはcharles ssl export <file_name>
で行えます。
Ref: https://www.charlesproxy.com/documentation/tools/command-line-tools/
この例ではcharles.crtという名前で証明書をエクスポートします。
$ charles ssl export charles.crt
その後、その証明書を信頼済みCAとして登録します。まず証明書ファイル"charles.crt"をCAストアにコピーします。なんとなく/usr/local/share/ca-certificates/
の直下に置くのは憚られたので"mycert"などサブディレクトリを作成して作業しました。
$ sudo mkdir /usr/local/share/ca-certificates/mycert
そこに証明書ファイルをコピーします。
$ sudo cp charles.crt /usr/local/share/ca-certificates/mycert/charles.crt
その後、CAストアをアップデートします。
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
すると、上記のように証明書が追加されたと標準出力に表示されます。
Charles Proxyの設定
Charles Proxyの設定を行います。が、ここで悲報です。Charles ProxyではCommand-line Toolsの資料を見る限り、設定を行うためのコマンドが用意されてないようです。
ただ、どうやら他のプラットフォームの設定ファイルと互換があるようで、Windows版やMac版のCharles Proxyで使用した設定ファイルをそのままLinux版で使用することができました。なので、他のOS上でCharles ProxyのGUIから必要な設定を行い、その設定ファイルをLinux環境上にコピーして使用します。
各プラットフォームにおける設定ファイルの保存場所は以下の通りです:
- Windows:
%APPDATA%\Charles\charles.config
- Mac OS X:
~/Library/Preferences/com.xk72.charles.config
- Linux:
~/.charles.config
Ref: https://www.charlesproxy.com/documentation/faqs/deploying-license-keys-during-installation/
私が使用した設定ファイルをここに記載させていただきます。
設定ファイルをLinux上のホームディレクトリ~/.charles.config
に保存する、もしくはCharles Proxy起動時に引数として指定する(以下のコマンド)ことで、その設定ファイルを読み込むことが可能です。
$ charles -config <config_file_name>
重要な設定項目
ここではデフォ値と異なるであろう設定項目についていくつかピックアップします。
SSL proxyingの対象ホスト・ポート
<sslLocations>
<locationPatterns>
<locationMatch>
<location>
<host>*</host>
<port>*</port>
</location>
<enabled>true</enabled>
</locationMatch>
</locationPatterns>
</sslLocations>
Web interfaceの有効化
<remoteControlConfiguration>
<enabled>true</enabled>
<allowAnonymous>true</allowAnonymous>
<users/>
</remoteControlConfiguration>
Charles Proxyの基本操作
設定ができたらCharles Proxyを起動してみましょう。以下のコマンドでプロセスを起動します。
$ charles
ライセンスを購入してない場合は、以下のように起動後10秒ほど待機時間が発生するので、Readyになるまで待ちます。
$ charles
INFO com.xk72.charles.CharlesContext Loading Configuration
INFO com.xk72.charles.CharlesContext Version 4.6.3
INFO com.xk72.charles.CharlesContext Loading Preferences
Charles is shareware. If you continue using Charles you must pay the shareware fee.
Charles will wait for 10 seconds before starting...
INFO com.xk72.charles.CharlesContext Configuring Access Control List
INFO com.xk72.charles.CharlesContext Starting Proxy Server
INFO com.xk72.charles.CharlesContext Loading Tools
INFO com.xk72.charles.CharlesContext Starting Tools
INFO com.xk72.charles.CharlesContext Configuring Proxies
INFO com.xk72.charles.CharlesContext Ready
Readyなったら起動完了です。
そしたら、もう一つターミナル画面を開きます。Web interfaceを有効化していれば、以下のようにcurlでCharlesのWeb interface(http://contorl.charles/
)にCharles Proxy(http://127.0.0.1:8888
)をプロキシとしてアクセスすることで、Charles Proxyの様々な操作をすることが可能です。
$ curl -x http://127.0.0.1:8888 http://control.charles/
レスポンスとして、Charles ProxyのメニューがHTMLで返ってきます。
<html>
<head>
<title>Charles Web Interface</title>
<link rel="stylesheet" href="css/plain.css" />
</head>
<body>
<h1>Charles Web Interface</h1>
<ul>
<li><a href="throttling/">Throttling</a></li>
<li><a href="recording/">Recording</a></li>
<li><a href="tools/">Tools</a></li>
<li><a href="session/">Session</a></li>
<li><a href="quit">Quit</a></li>
</ul>
</body>
</html>
例えば、Recordingメニューを閲覧する場合はrecording/
のエンドポイント
curl -x http://127.0.0.1:8888 http://control.charles/recording/
Sessionメニューを閲覧する場合はsession/
のエンドポイント
curl -x http://127.0.0.1:8888 http://control.charles/session/
といった感じで操作が行えます。
Charles Proxyでログを採取
それではCharles Proxyで通信ログの採取を行ってみましょう。
まず以下のコマンドででRecordingのメニューを開きます。
$ curl -x http://127.0.0.1:8888 http://control.charles/recording/
<html>
<head>
<title>Charles Web Interface</title>
<link rel="stylesheet" href="../css/plain.css" />
</head>
<body>
<h1>Charles Web Interface</h1>
<h2>Recording</h2>
<p>Status: Recording Stopped</p>
<ul>
<li><a href="start">Start</a></li>
<li><a href="stop">Stop</a></li>
<li><a href="../">Back</a></li>
</ul>
</body>
</html>
上記より、Recordingの開始はstart
のエンドポイント、停止はstop
のエンドポイントと分かります。
start/
のエンドポイントにアクセスし、Recordingを開始します。
$ curl -x http://127.0.0.1:8888 http://control.charles/recording/start
<html>
<head>
<title>Charles Web Interface</title>
<link rel="stylesheet" href="../css/plain.css" />
</head>
<body>
<h1>Charles Web Interface</h1>
<h2>Recording</h2>
<p>Status: Recording</p>
<ul>
<li><a href="start">Start</a></li>
<li><a href="stop">Stop</a></li>
<li><a href="../">Back</a></li>
</ul>
</body>
</html>
上記のように"Status: Recording"というレスポンスが返っていれば、Recordingが開始されている状態です。
その状態で、キャプチャしたい通信を行います。ここでは例としてcurl
を使用した通信を行います。
まずcurlの通信がCharles Proxyを経由するように環境変数を定義してCharles Proxyをプロキシとして指定します。
export http_proxy='http://127.0.0.1:8888'
export https_proxy='http://127.0.0.1:8888'
その後、通信を行います。
$ curl --location --request GET 'https://api.box.com/2.0/users/me' --header 'Authorization: Bearer 68l2JTE0wOQRM7tsC83ZDV8xl8GM11B0'
キャプチャしたい通信が完了したら、Charles ProxyでRecordingした内容をログファイルへと書き出します。
session/
のエンドポイントにアクセスすることで、出力可能なフォーマットとそのコマンドを閲覧できます
$ curl -x http://127.0.0.1:8888 http://control.charles/session/
<html>
<head>
<title>Charles Web Interface</title>
<link rel="stylesheet" href="../css/plain.css" />
</head>
<body>
<h1>Charles Web Interface</h1>
<h2>Session</h2>
<ul>
<li><a href="clear">Clear Session</a></li>
<li><a href="export-xml">Export Session as XML</a></li>
<li><a href="export-json">Export Session as JSON</a></li>
<li><a href="export-trace">Export Session as Trace</a></li>
<li><a href="export-csv">Export Session as CSV</a></li>
<li><a href="export-har">Export Session as HAR</a></li>
<li><a href="download">Download Session</a></li>
<li><a href="../">Back</a></li>
</ul>
</body>
</html>
例えば、JSONで保存する場合はexport-json
のエンドポイント
$ curl -x http://127.0.0.1:8888 http://control.charles/session/export-json --output <output_file_name>
Traceで保存する場合は/export-trace
のエンドポイント
$ curl -x http://127.0.0.1:8888 http://control.charles/session/export-trace --output <output_file_name>
といった感じです。
TraceファイルをCharles Proxyで開くことで、復号された通信の内容を確認することができます。
Common Errors
Web interfaceが有効化されてない
- Error:
<html>
<head>
<title>Charles Web Interface</title>
</head>
<body>
<h1>Charles Web Interface</h1>
<p>The Web Interface is disabled. You can enable it in the Web Interface Settings in the Proxy menu.</p>
</body>
- Cause: Web interfaceの有効化がされてない状態で、
http://control.charles
に接続が行われた。 - Solution: この手順を実施して、設定ファイルよりWeb Interfaceを有効化する。
Charles Proxyとの接続ができない
- Error:
curl: (7) Failed to connect to 127.0.0.1 port 8888: Connection refused
- Cause: Charles Proxyが起動してない、もしくは起動しているポート番号が8888とは異なっている。
- Solution: Charles Proxyが起動しているか確認、また接続先のポート番号と設定ファイルで指定されているポート番号(以下の箇所)が一致しているか確認する。
<proxyConfiguration>
<-- 略 -->
<port>8888</port>
<-- 略 -->
</proxyConfiguration>
SSLエラー
- Error:
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 127.0.0.1:8888
- Cause: Charles ProxyのSSL証明書が信頼されていない。
- Solution: この手順の証明書がインストールされていることを確認する。また、証明書インストール後、再起動が必要かも(自身がこのエラーにヒットした時は、OSの再起動で解消された記憶)。