8 ポイント 投稿者 GN⁺ 2025-02-04 | 2件のコメント | WhatsAppで共有
  • httptaphttptap -- <command> の形式で Linux プログラムを実行し、そのプログラムが生成する HTTP/HTTPS リクエストとレスポンスの要約をターミナルに表示するツール
  • root 権限、デーモン、システム全体への変更、iptables ルール、ルーティングテーブルの変更なしで動作し、実行ファイルは依存関係のない 静的 Go バイナリ
  • 現時点では Linux 専用で、network namespace のような Linux 専用システムコールを使用しているため、他の OS への移植は難しいとしている
  • HTTPS トラフィックは、実行時にその場で生成した認証局をサブプロセス環境に注入して復号し、生の IP/TCP/UDP パケットを処理する 透過 TCP プロキシ 方式で動作する
  • Ubuntu 23.10 以降や、非特権 user namespace をデフォルトで無効化しているディストリビューションでは sysctl 設定が必要になる場合があり、受信接続の待ち受けや /dev/net/tun へのアクセスなどの制約がある

httptap ができること

インストールと実行条件

  • 事前ビルド済みバイナリは最新リリースの tarball を取得してインストールできる
    • すべてのバージョンと CPU アーキテクチャは releases で確認可能
  • Go でのインストール方法も提供されている
    • go install github.com/monasticacademy/httptap@latest
  • 実行には通常 root 権限は不要で、デーモンやシステム全体の設定も必要ない
    • iptables ルールを作成しない
    • ルーティングテーブルを変更しない
    • 同じシステム上の他プロセスに通常は影響しない
  • Ubuntu 23.10 以降では次の設定が必要
    • sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0
    • sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
  • これらの設定は、非特権 user namespace を制限する最近のカーネル機能を無効化する
    • 非特権 user namespace をデフォルトで無効化している他のディストリビューションでも必要になる場合がある
    • httptap 用の AppArmor プロファイルを同梱してこの必要性をなくす方法を調査中

使用例

  • curl -s https://buddhismforai.sutra.co -o /dev/null の実行例では、サーバーが 302 リダイレクトを返したことがわかる
  • curl -sL のようにリダイレクトをたどるようにすると、追加のリクエストまで表示される
    • 最初のリクエストは 302
    • 2 番目のリクエストはリダイレクト先 URL に対する 200
  • gcloud compute instances list の例では、Google Cloud CLI が内部的に使用する HTTP エンドポイントを確認できる
  • kubectl get all の例では、Kubernetes API サーバーへのリクエストを表示する
    • --https 443 6443 は 443 と 6443 ポートへの TCP 接続を HTTPS として扱わせる
    • --insecure-skip-tls-verify は、kubectl が httptap の生成した認証局を使用しないため必要
  • curl --doh-url https://cloudflare-dns.com/dns-query の例では、DNS-over-HTTP の流れを確認できる
    • 最初の 2 リクエストは DNS 問い合わせ
    • 次の 2 リクエストは対象サイトへの通常の HTTP リクエスト
  • --head--body オプションを併用すると、HTTP ヘッダーと生のペイロードを出力する

HAR 出力

  • --dump-har out.har オプションで HTTP リクエストとレスポンスを HAR ファイル としてダンプできる
  • 生成された HAR ファイルは複数の HAR ビューアーで可視化できる
  • 例の HAR には https://monasticacademy.org への 308 Redirect リクエストと https://www.monasticacademy.org への 200 OK リクエストが含まれる

localhost へのアクセス

  • httptap 内からホストの localhost ポートへアクセスするには、localhost の代わりに host.httptap.local または 169.254.77.65 を使う
  • Linux の各 network namespace は独自の loopback デバイス 127.0.0.1 を持つため、httptap 内の 127.0.0.1:1234 はホスト側の同じアドレスとポートではない
  • httptap は 169.254.77.65127.0.0.1 にルーティングするようハードコードして、この問題を回避している

デーモン化されるサブプロセス

  • Linux では、元のプロセスが終了した後も残るサブプロセスを作成できる
    • これはデーモンや、コマンドラインから起動した GUI アプリで一般的な方式
  • こうしたプロセスを httptap 配下で実行すると、デーモン化されたプロセスはそのまま httptap の network namespace 内に残る
  • --no-exit オプションを使うと、直接起動したサブプロセスが終了した後も httptap がプロキシとロギングを継続する
    • Visual Studio Code の例では httptap --no-exit -- code --ignore-certificate-errors . の形式を使う
    • 終了するには VS Code を閉じた後、Ctrl+C で httptap を停止する必要がある
  • --no-exit なしで httptap が先に終了すると、network namespace は残っていても TUN デバイスのパケットを読むプロセスがいないため、アプリのネットワーク接続は切断される
  • setsid setsid curl http://httpbin.org/get や Python の forksetsidfork の例でも、--no-exit がないと Could not resolve host エラーが発生する

仕組み

  • httptap -- <command><command> を隔離された network namespace で実行し、その場で生成した認証局を注入して HTTPS トラフィックを復号する
  • Linux の TUN デバイスを作成し、すべてのネットワークトラフィックがそのデバイスを通過するようにサブプロセス環境を構成する
    • TUN デバイスに書き込まれたトラフィックは、そのデバイスを作成したプロセスが保持するファイルディスクリプタへ渡される
  • root の network namespace を変更するとシステム全体のトラフィックに影響するため、httptap は別の network namespace を作成する
    • その namespace には loopback デバイスと TUN デバイスしか存在しない
    • サブプロセスはこの namespace 内で実行される
  • TUN デバイスから受け取るトラフィックは生の IP パケット
    • httptap は IP パケットとその内部の TCP/UDP パケットをパースする
    • さらにサブプロセスへ生の IP パケットを書き戻す必要がある
    • 独自の TCP/IP 実装は TCP プロトコル全体の多くを省いているが、目的には十分に機能する
  • サブプロセスが www.example.com にリクエストすると、httptap は対象 IP 宛ての TCP SYN を受け取り、SYN+ACK で応答する
    • 別途 Linux カーネルの通常のソケット API を使って実際の宛先 IP と TCP 接続を確立する
    • その後、双方向にデータを中継する
    • この構成が 従来型の透過 TCP プロキシ
  • HTTPS の復号は認証局の注入によって行う
    • 起動時に private key と x509 certificate に対応する認証局を生成する
    • サブプロセスにだけ見えるファイルシステムへ証明書を書き込む
    • サブプロセスにだけ見える環境変数を設定し、その認証局を信頼リストへ追加する
    • httptap はその認証局の private key を保持しているため、サブプロセスが通信しようとしているサーバーであるかのように証明でき、平文の HTTP リクエストを読める

制約

  • 現時点では Linux 専用 で、network namespace のような Linux 専用システムコールに依存している
  • プロセスは受信ネットワーク接続を待ち受けできない
  • /dev/net/tun へのアクセス権限が必要
  • すべての ICMP echo リクエストは、実際のネットワークへ ICMP パケットを送信せず、そのまま echo される

2件のコメント

 
halfenif 2025-02-06

it was developed at the Monastic Academy in Vermont in the US. We believe that a monastic schedule, and the practice of the Buddhist spiritual path more generally, provide ideal conditions for technological development.

テストしながらGitHubを見ていたら、修道院で修行?している方々が精神的な達成の一環として作ったのかな、という気もします。

 
GN⁺ 2025-02-04
Hacker News のコメント
  • README の「How it was made」セクションは、ツールそのものと同じくらい興味深かった
    100エーカーを少し超える土地で共同生活しながら修行し、朝夕に一緒に念仏と瞑想を行い、毎月およそ1週間は瞑想リトリートを運営・参加しているという。残りの時間は土地の管理、建物の保守、料理、掃除、計画、資金調達、そしてここ数年はソフトウェア開発まで一緒に行っている、という内容

    • 『Soul of a New Machine』の一節を思い出す
      マイクロコードとロジックがナノ秒単位で問題を起こしていた時期に、過労のエンジニアが1人退職する際、端末に辞表としてこんなメモを残したという:「私は Vermont のコミューンへ行き、季節より短い時間単位は扱わない」
    • 正直に言うと、西洋圏のあちこちにすでにたくさんあるヨガ/スピリチュアル系カルトの一つのように聞こえる
    • 「ここ数年、私たちは Buddhism for AI という講義シリーズを録画してきました。AI システムが直接消費できるように、仏教に基づく宗教、そう、宗教を設計しようとする取り組みについてのものです。世界の状況を考えると、私たちはこの取り組みが非常に重要だと感じています」という部分は、今私たちが生きている時代がどれほど奇妙かを示す指標のように感じる
      良いアイデアなのか、彼らが想像する結果につながるのかは別問題
    • 最初の田舎の写真は生成画像だと思ったが、今では実写のように見える
      技術と瞑想の組み合わせには惹かれる。アイデア自体は魅力的だが、実際にやるのはたぶん難しそう。一種の仏教版 Recurseのように見える
  • httptap は、root 権限なしで実行できるプロセス単位の HTTP トレーサー
    httptap <プログラム> のように Linux プログラムを実行すると、標準出力で HTTP/HTTPS リクエストとレスポンスのトレースを見られる

    httptap -- python -c "import requests; requests.get('https://monasticacademy.org')"
    ---> GET https://monasticacademy.org/
    <--- 308 https://monasticacademy.org/ (15 bytes)
    ---> GET https://www.monasticacademy.org/
    <--- 200 https://www.monasticacademy.org/ (5796 bytes)

    分離されたネットワーク名前空間内で実行する方式で、独自の TCP/IP スタックとして gVisor を使う。HTTP プロキシではないため、プロキシ設定に依存しない。TLS トラフィックはその場で CA を生成して復号し、iptables ルールをインストールしたりグローバルなシステム変更を行ったりしない

    • macOS でも動かせるのか気になる。Tailscale は macOS の一部機能で gVisor の TCP/IP ライブラリを netstack ライブラリとして使っていると理解している
    • リクエストやレスポンスを変更できるのか気になる。現在の Web がますますユーザーに敵対的になっていく中で、こうしたツールの必要性はかつてなく高まっている
      特にプロキシ設定が不要なら、さらに有用
    • root なしでも実行できる Wireshark をみんな忘れているのかと思う
      https://blog.wireshark.org/2010/02/running-wireshark-as-you/
  • プロセスを分離されたネットワーク名前空間で実行するというアイデアが天才的
    HTTPS の部分はさらに興味深い。プログラムに共通の環境変数[1]を設定して、一時ディレクトリ内の CA バンドルを使わせているように見えるが、http_proxy の派生変数と同様に、プログラムがその変数を単に無視できてしまうという問題がある

    /etc/resolv.conf にオーバーレイファイルシステムをマウントしているのも見える[2]。httptap が /etc/ca-certificates ディレクトリを一時 CA バンドルとしてマウントすると役に立つのか気になる

    [1] https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...
    [2] https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...

    • 任意のプロセスにCA ルートを指定する合意された方法や、システムが強制する方法が事実上ないのはもどかしい、という点には同意する
      httptap が /etc/resolv.conf にオーバーレイをマウントしているのは、DNS 解決についても CA ルートと同じように、任意のプロセスにどの DNS サーバーを使えと確実に伝える方法がないため。ただし /etc/resolv.conf はかなり信頼できる選択肢ではある。プロセスをネットワーク名前空間に入れた瞬間、デスクトップ Linux で最も一般的な設定である systemd リゾルバー localhost:53 にもはやアクセスできなくなるため、DNS 解決を提供する必要がある
      /etc/ca-certificates をオーバーレイでマウントするのも役に立つかもしれない。ただ、そのディレクトリ構造を見てみると、ディストリビューションごとにあまりにも一貫性がなくて困惑した。それでも可能ではある。少なくとも一部の TLS 実装が認識する形で、そのディレクトリに証明書を追加する方法について知見があれば聞きたい
    • HTTPS 部分には、あらゆる種類のプログラムとロングテールの証明書ピンニング実装までをカバーする一般解はないと思う
      反例として、TLS で通信し、コンパイル済みコードを強力に難読化したマルウェアを想像できる。固定された CA 証明書の束をバイナリに含め、ファイルシステムを一切開かないプログラムかもしれない。それでも、ほとんどのルート CA 証明書が期限切れになるまで約10年は有効で、安全な TLS 接続を作れる。TLS はすべてユーザー空間で処理され、OpenSSL や他の共通ライブラリを使う保証はないため、特定の OpenSSL 関数にフックする方式にも期待できない。サーバーが自己署名証明書を使い、クライアントが何らかの理由でそれを受け入れるなら、さらに悪くなる
      それでも、多少の作業で 99% のケースを安定して処理することは確実に可能。何もないよりはましだ
  • ここで TUN デバイスを使うのは本当に見事なアイデア。README の “How it was made” セクションも、GitHub README で読んだものの中でも最高レベルだった
    Subtrace[1] というものを作っているのだが、入ってくるリクエストと出ていくリクエストの両方を自動的にインターセプトできる。プログラムを起動するインターフェースも同じ形に収束したようで面白い[2]。ただし Subtrace の目的は httptap とは少し異なり、クラウドバックエンドサービスの可観測性/モニタリング寄りなので、双方向のリクエストを強調している。アプローチも違う。Seccomp BPF で socketconnectlistenaccept など約 10 個のシステムコールをインターセプトし、すべての TCP 接続を Subtrace 経由でプロキシする。その後 TCP ストリームから HTTP リクエストをパースし、Chrome DevTools の Network タブを通常の Web アプリのようにブラウザで動作するよう再利用してユーザーに見せている

    httptap 配下でプログラムを実行してみて、何か面白い逸話があったのか気になる。どのプログラムが一番頻繁に「おうちに電話」しているのかも気になる

    [1] https://github.com/subtrace/subtrace
    [2] https://docs.subtrace.dev/quickstart

    • Android の VPN サービスを使ってパケットフィルタリングを行う NetGuard を思い出した。生の TUN ではなく Android VPN サービスを使っている
      https://github.com/M66B/NetGuard
    • キャプチャした内容を Chrome DevTools に接続するのも興味深いし、eBPF を使うのも興味深い。開発者ツールをスタンドアロンの Web アプリとして動くようにしたのも素晴らしい
      信じがたいかもしれないが、Firefox のネットワークタブで同じことをやろうとした半分できかけの試みが、リポジトリの networktab ディレクトリにある。とても素晴らしいプロジェクトなので、もっと学びたいし、さらに話してもよい
  • 権限のないユーザーがネットワークトラフィックを分析する別のツールとして、rootless Podman と Pasta を使うこともできる
    podman run のオプションに次を追加すればよい

    --network=pasta:--pcap,myfile.pcap

    すると Pasta がネットワークトラフィックを PCAP ファイルに記録し、後で分析できる。tshark で記録済み PCAP ファイルを分析する簡単な例も書いておいた
    https://github.com/eriksjolund/podman-networking-docs?tab=re...

    • 知っておくと非常に良いが、それでも TLS トラフィックの復号 という問題は残る
  • かなり興味深い。Go アプリケーションで似たような「タップ」機能をするライブラリを書いたことがある: https://github.com/henvic/httpretty
    https://asciinema.org/a/297429

    任意のプログラムに対してこのようなことをやることも考えたが、実際の実装方法を深く掘り下げたわけではなかった。誰かが作り上げたのを見ると嬉しい

  • なぜ eBPF を使わないのか気になる。そうすれば、すでに実行中のものも含めて、すべてのプロセスの HTTP リクエストを一括で見られるはずだ。しかも TLS も気にする必要はなく、例えば write(2) にフックすればよさそうに思える

    • write(2) にフックすることで TLS がどう解決するのか分からない。暗号文を読んで変更することはできるだろうが、プロセスは平文バイトで write(2) を呼び出しているわけではないので、実際の HTTP リクエストは読めない。結局ネットワークに載る暗号化されたバイトだけを見ることになり、それは NSA でも見られる
      httptap が使っているような CA 証明書トリック が必要になる。もちろん証明書ピンニングのような注意点はあるが、ほとんどの実用的なシナリオでは安定して動作させられる
      Subtrace[1] を作りながらこの特定の問題についてばかげたほど考えてきたので、もっと単純またはエレガントなアプローチがあるなら本気で興味がある
      [1] https://github.com/subtrace/subtrace
    • 残念ながら TLS はカーネルではなくアプリケーション内部で行われるため、eBPF で write システムコールにフックしても TLS 復号 には役立たない
    • SSL ライブラリに uprobe を仕掛ければ、復号された HTTP レスポンスのような内容を検査・変更してコンテンツをフィルタリングできるのか気になる
    • eBPF はおそらく root 権限が必要なのではないかと思う
    • この方式は root が必要なのでは? httptap の大きな「売り」は、まさに root 権限が不要な点 に見える
      いずれにせよ選択肢が多いほどよい
  • いいね。nginx 設定のデバッグにすぐ使ってみると思う
    今は curl -v を使って、出力から何が間違っているのかを手作業で眺める必要があるが、このツールならリダイレクトループのようなものがすぐ明らかになりそうだ

    • 実際の利用文脈でどう動作するのか、特にどの機能が役立つのか聞いてみたい
  • アプリの HTTP/S 呼び出しスタックを素早く大まかに眺める必要があるときに、とても良さそうだ
    個人的にはすべてを見るために eBPF を好むが、このユーティリティは eBPF トレースで重要な部分を絞り込むのに役立つかもしれない

  • 良さそう
    GitHubプロフィールが https://www.monasticacademy.org/about を指していて、それ自体に特に意見はないが、彼らの修道院式トレーニング・リトリートとGitHubプロジェクトがどうつながっているのか気になった
    READMEのいちばん下を見ると、そのつながりが説明されていた: https://github.com/monasticacademy/httptap?tab=readme-ov-fil...

    • このスレッドを見ている人向けに言うと、つながりは単に httptapがMonastic Academyのプロジェクト だということ
      その意味するところは、バーモント州の123エーカーの土地で、人々が比較的伝統的な仏教の僧院構造に従って共同生活をしているということ。ただし、正式に受戒した僧侶ではない。日中はさまざまな技術系・非技術系プロジェクトに一緒に取り組んでいる。上にあるREADMEリンクが良い概要になっている
      https://github.com/monasticacademy/httptap?tab=readme-ov-fil...