Curl を使わずに Bash の /dev/tcp で HTTP リクエストを送る

Bash の /dev/tcp を使ったネットワーク接続

Bash は TCP ソケットを直接開くことができ、curlwget といった外部ユーティリティに依存せずにネットワーク上でデータの送受信が可能です。これは、Docker コンテナのようにパッケージのインストールが制限されたミニマル環境や、余計なツールが削除された環境での接続デバッグに特に有用です。

基本的な HTTP GET リクエストを実行するには、以下のコマンドシーケンスを使用します。

exec 3<>/dev/tcp/service/8642
printf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3
cat <&3

この例では、service がホスト名、8642 がポート番号です。exec 3<> コマンドは指定したホストとポートへのソケットを開き、ファイルディスクリプタ 3 に割り当てます。printf コマンドで生の HTTP リクエストを送信し、cat <&3 で接続が閉じられるまでソケットからの応答を読み取ります。

ヘッダーと認証の扱い

Authorization トークンなどの追加ヘッダーを含める場合は、HTTP リクエストを終了させる空行の直前にヘッダー行を挿入します。

exec 3<>/dev/tcp/service/8642
printf 'GET /v1/models HTTP/1.1\r\nHost: service\r\nAuthorization: Bearer %s\r\nConnection: close\r\n\r\n' "$API_KEY" >&3
cat <&3

技術的実装と制限事項

/dev/tcp の本質

見た目とは異なり、/dev/tcp はディスク上の実際のデバイスファイルではありません。Bash が内部で処理するリダイレクションです。Bash が /dev/tcp/host/port というパスに遭遇すると、connect(2) システムコールを使って対応する TCP ソケットを開こうとします。この設計は、標準的な Unix システムに /dev/tcp/dev/udp の階層が存在しないため、実際のファイルとの衝突を防ぐために選ばれました。

重要な制約

デバッグには強力ですが、フル機能の HTTP クライアントと比べて以下のような重大な制限があります。

  • TLS/SSL 非対応: /dev/tcp は生のソケットを開くだけで、HTTPS を扱えません。暗号化通信が必要な場合は openssl s_client などのツールが必要です。
  • HTTP パースなし: Bash は HTTP プロトコルを解析しません。リダイレクト、チャンク転送エンコーディング、圧縮、リトライなどは処理できず、単にバイト列を送受信するだけです。
  • 接続管理: Connection: close ヘッダーは必須です。これが無いとサーバは接続を開いたままにし(HTTP/1.1 のデフォルト)、cat がデータ待ちで無限にハングします。
  • シェル互換性: Bash 固有の機能であり、POSIX 準拠ではありません。Debian のデフォルト /bin/sh である dashzsh では動作しません。この機能を使うスクリプトは必ず bash で実行する必要があります。
  • コンパイル時オプション: この機能は Bash のコンパイル時に --enable-net-redirections フラグで有効化されている必要があります。多くの主流ディストリビューションでは有効ですが、ミニマルビルドや古いビルド(例: 一部の古い Debian バージョン)では無効化されていることがあります。

実用的な利用ケースと代替手段

デバッグとセキュリティ

この手法は環境が極端に制限されているシナリオで頻繁に利用されます。

  • ミニマルコンテナ: 必要最低限のバイナリしか含まないイメージ内でヘルスエンドポイントを確認する。
  • ペネトレーションテスト: curlnc が存在しない CTF やセキュリティ監査の場で、初期シェルを取得したりローカル Web サーバとやり取りする。
  • 制限回避: セキュリティポリシーでネットワークツールのインストールが禁止されている場合に、サービスとやり取りする手段として利用する。

代替手段

利用可能なツールに応じて、以下の方法の方が信頼性が高いことがあります。

  • Netcat (nc): 生ソケット操作に特化した、より堅牢なツール。
  • Perl/Python: Perl の IO::Socket や Python の socket モジュールを使ってプログラム的にネットワークリクエストを処理する。
  • nsenter: ホストマシンに curl がインストールされている場合、nsenter でコンテナのネットワーク名前空間に入ってホスト側の curl を実行できる。

"これは 2026 年に皆が受け取るべき内容であり、面接でなぜクッキーが HTTP プロトコルでどのように表現されるかを説明させる理由でもある。" — @dennis16384


要約: Bash は /dev/tcp を介して TCP ソケットを開く組み込み機構を提供しており、curl や wget といったツールが利用できないミニマル環境でも基本的な HTTP リクエストを実行できます。

タイトル: Curl を使わずに Bash の /dev/tcp で HTTP リクエストを送る

Sources