CLI環境でCharles Proxyを利用して暗号化通信の中身を見る

CLI環境でCharles Proxyを利用して暗号化通信の中身を見る

CLI環境でCharles Proxyを利用して暗号化通信の中身を見る

ここでは、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で開くことで、復号された通信の内容を確認することができます。

CharlesProxyDesktop

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の再起動で解消された記憶)。