世界を動かす技術を、日本語で。

TIL: Bashの/dev/TCPを使ってcurlなしでHTTPリクエストを送信できること

2026年6月17日原文(mareksuppa.com)

概要

  • curlwget が使えない最小限の Docker コンテナでの HTTP 通信方法の紹介
  • bash/dev/tcp 機能を利用した GET リクエストの実行手順
  • 追加ヘッダー の送信方法や注意点の解説
  • 制限事項 (TLS非対応・POSIX非互換など)への言及
  • 簡易チェックやデバッグ用途 に有効なテクニックの説明

curl や wget なしで Docker コンテナ間の HTTP 通信確認

  • curlwget がインストールされていない極小イメージでの HTTP 通信確認方法
  • bash の /dev/tcp 機能を使い、 TCPソケット を直接オープン
  • サービス名やホスト名、ポート番号は Docker ネットワーク 内で解決可能なものを指定
  • 以下のコマンドで GET /health リクエストを送信し、レスポンス全体を取得可能

    • 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 部分には通信したいサービス名やホスト名を指定
  • レスポンス にはステータスライン、ヘッダー、空行、ボディがすべて含まれる

HTTPヘッダー追加や Bearer 認証の付与方法

  • Authorization ヘッダーなどを追加したい場合は、リクエストのヘッダー行を増やす
  • 例:Bearer トークンを付与して /v1/models にアクセス

    • 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
  • 各ヘッダーは \r\n で区切り、最後は空行でリクエスト終了を明示

/dev/tcp の仕組みと注意点

  • /dev/tcp は実際のデバイスファイルではなく、bash 内部でのみ動作する特殊リダイレクト
  • ls /dev/tcp などで実体を確認することはできない
  • bash マニュアルによると、 /dev/tcp/host/port 形式で指定すると、bash が自動的に DNS 解決とソケット接続を実行
  • exec 3<> でファイルディスクリプタ3をソケットに割り当て、 読み書き が可能

制限事項と運用上のポイント

  • これは 本格的な HTTP クライアント ではなく、
    • リダイレクトチャンク転送圧縮リトライTLS など curl が持つ機能は一切非対応
    • Connection: close ヘッダーが重要
      • 省略するとサーバ側が接続を開いたままにし、cat が永遠に待機してしまう
      • サーバに接続終了を明示し、cat が EOF で終了できるようにする
    • timeout コマンドでタイムアウト制御も推奨
      • 例:timeout 6 bash -c '...'
  • TLS(HTTPS)非対応
    • /dev/tcp はプレーンなソケット接続のみ
    • HTTPS が必要な場合は openssl s_client など他ツールが必要
  • bash 固有機能
    • POSIX 標準ではなく dash や zsh では非対応
    • #!/bin/bash で明示的に bash を指定
    • bash ビルド時に --enable-net-redirections オプションが有効な場合のみ利用可能
      • 多くのディストリビューションでは有効だが、最小構成や古い環境では無効の場合あり
  • 通常は curl 推奨
    • あくまで極小コンテナや一時的なデバッグ用途のテクニック
    • 必要に応じて適切な HTTP クライアントの導入検討が望ましい

まとめ

  • bash の /dev/tcp 機能 を使えば、curl や wget なしで簡易的な HTTP 通信が可能
  • 最小限コンテナ内の疎通確認やデバッグ に便利な裏技
  • 制限事項や利用条件 を理解した上で、適切に使い分けることが重要

Hackerたちの意見

内部Dockerネットワークでコンテナ間の接続をチェックしてたら、curlやwgetが入ってないイメージに遭遇したんだ。驚いたのは、Bashには/dev/tcpがあって、ちょっとしたシェルマジックでHTTPリクエストができちゃうこと。例えば、こんな感じでね: exec 3/dev/tcp/service/8642 printf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3 cat ここでserviceは話してる相手のホスト名で、8642はHTTPで話しかけようとしてるポート。めっちゃクールだよね!

すごく面白そうだけど、curlをサポートしてるイメージを使うことに何か欠点があるのかな?思いつかないし、個人的には必須だと思うんだけど、プロダクションイメージでもね。

結局、bashは自分でHTTPを話せるってことだ。 いや、そうじゃないよ。BashはTCPソケットを開くことができるだけ。ここでやってるのは、自分でHTTPを話そうとしてるだけで、テストやデバッグにはいいけど、実際にこれを無人で使うと痛い目に遭うよ。このおもちゃのコードはHTTPを正しく解析できないし、壊れちゃうからね。もちろん、bashで完全なHTTP/1.1クライアントを書くこともできるし、純粋なbashで完全なHTTPサーバーも作れるよ: https://github.com/bahamas10/bash-web-server でも、あまり無茶じゃないシェルなら、ncを使うのが賢い選択だと思う。

いや、そうじゃないよ。BashはTCPソケットを開くことができる。 確かにその通りだね。ちょっと調子に乗っちゃったから、記事をもっと正確に更新するよ。指摘してくれてありがとう! あまり無茶じゃないシェルなら、ncを使うのが賢い選択だと思う。 ちなみに、ncやそれに相当するnetcatは、試してたイメージには入ってなかったんだ。確かに、そっちの方がいい選択だね。

そんなに無茶じゃないよ。HTTP/1.1や必須のホストヘッダーができる前から、手動でHTTPリクエストを打ってたし。真面目な用途には使うのは狂気だけど(逆に、bashでウェブサーバーを実装するのもね)、ちょっとしたテストにはすごくいいよ!

いや、そうじゃないよ。BashはTCPソケットを開くことができる。 それにはnetcatってプログラムを使わなきゃいけないと思ってたんだけど、じゃあそのバイナリの意味は何なの?それに、telnetを使って手動でHTTPを送信することもできるんじゃない?

「いや、10行のコードを書くことはできない。10万行の依存関係をインポートしなきゃならない」ってよくある誤解だよ。スイスアーミーナイフの依存関係を置き換えたいなら、スイスアーミーナイフを実装する必要はないんだ。時には、コルクスクリューの最後のヘリックスだけを実装すればいいこともある。

あのbash-web-serverにはいいパラメータ展開の例があったね。$_パラメータを使った方法は、前に考えたこともなかったし、変数の前処理のために単一の:${x}行がよく使われてた。

「純粋なbashでの完全なHTTPサーバー」というのは間違いだってことをはっきりさせておく必要があるね。BashはTCP/UDPソケットでの受信接続をリッスンできないから。bash-web-serverプロジェクトは、C言語でソケットリスナーを構築していて、実行時に「組み込み」モジュールとして動的にロードされて、その機能を利用できるようにしてるんだ。

Bash用のRailsみたいなフレームワークもあるよ。https://github.com/jneen/balls

いい感じだね、example.comに対して動くよ。 exec 3/dev/tcp/example.com/80 printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' >&3 cat 出力は: HTTP/1.1 200 OK Date: Tue, 16 Jun 2026 17:37:45 GMT Content-Type: text/html ...こういうことをやると、いつもexample.comに行き着くんだよね。最近はhttpsを強制してるドメインが少ないから!

example.comは、公共のWiFiでキャプティブポータルが失敗したときにも便利だよね。ウェブブラウザを開いてhttp://example.comに行くと、キャプティブポータルページにリダイレクトされて、インターネットアクセスを得るために必要なことを再試行できるんだ。

Hacker Newsで議論の続きを見る