HN🔥 235
💬 132

【脱curl】Bashの「/dev/tcp」を使ってHTTPリクエストを送るスマートな方法

mrshu
1日前

ディスカッション (11件)

0
mrshuOP🔥 235
1日前

知っていましたか?curlがインストールされていない環境でも、Bashの「/dev/tcp」機能を使えば、その場で直接HTTPリクエストを投げることができます。特別なツールをインストールできない制限付きのサーバー環境などで、非常に強力なテクニックです。使い方はとてもシンプルで、以下のように記述するだけです:exec 3<>/dev/tcp/example.com/80; echo -e "GET / HTTP/1.1\r\nhost: example.com\r\n\r\n" >&3; cat <&3。簡易的な疎通確認や、外部への依存を極力減らしたい時にぜひ活用してみてください。

1
mrshu
1日前

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 <&3

ここで service は通信先のホスト名で、8642はHTTPで話そうとしているポート番号だ。

かなりイケてるよね!

2
basilikum
約24時間前

bashはそれ自体でHTTPを話せるらしい

いや、そんなことはない。BashができるのはTCPソケットを開くことまでだ。

君がやってるのはHTTPを自分で「話そう」としてるだけで、テストやデバッグ用ならいいし、手作業でやるのは最高に面白いけど、この疑似HTTPクライアントを実際の環境で監視なしに使おうものなら、間違いなく足元をすくわれるぞ。このおもちゃみたいなコードはHTTPを適切にパースしてないから、絶対にどこかで壊れる。

もちろんBashでHTTP/1.1クライアントを全部自作することもできるし、純粋なBashだけでHTTPサーバーだって作れる:https://github.com/bahamas10/bash-web-server

もっと常識的な非Bashシェルを使うなら、nc(netcat)を使うのが多分一番賢い選択だろうね。

3
simonw
約24時間前

へえ、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 <&3

出力はこんな感じ:

  HTTP/1.1 200 OK
  Date: Tue, 16 Jun 2026 17:37:45 GMT
  Content-Type: text/html
  ...

最近はHTTPSを強制しないドメインが少なすぎて、結局いつもこの手のテストにはexample.comを使っちゃうよ。

4
sam_lowry_
約23時間前

数年前、DockerコンテナからのSpringBootヘルスチェックでこれやらなきゃいけなかったんだよね。

FROM openjdk:11-jre-slim
HEALTHCHECK --start-period=10s --timeout=3s --retries=5
CMD perl -e "use IO::Socket; $sock = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => 'localhost', PeerPort => '8888') or die $@; $sock->autoflush(1); print $sock 'GET /actuator/health HTTP/1.1' . chr(0x0a) . chr(0x0d) . 'Host: localhost:8888' . chr(0x0a) . chr(0x0d) . 'Connection: close' . chr(0x0a) . chr(0x0d) . chr(0x0a) . chr(0x0d); while (my $line = $sock->getline ) { if ($line =~ /UP/) {exit;} }; close $sock; exit 1;"

5
xenadu02
約22時間前

90年代後半に子供だった頃、telnetでポート80や25、110に接続して手動でサーバーとやり取りできるって知ったときは衝撃だったな。

簡単なGET:
GET / HTTP/1.1
Content-Type: text/html
User-Agent: l33t hax0rs lol
X-Funny-Monkey: farts

ポート25でメールを送るなら:
HELO
mail-from: whoever@whatever.com
mail-to: sysadmin@yaya.com
<その他のヘッダー>
<空行>
本文 yay.
<2行の空行で終了>

POP3は昔すぎて忘れたけど、メールボックスをリストアップして個別のメッセージを取得したりできたよ。

この発見が、俺にとって「魔法なんてない」という考え方の始まりだった。コンピュータのあらゆる部分は人間が作ったもので、努力さえすればあるレベルまでは理解できるっていう気づきだね。

たぶん将来の多くの人はそんなこと気にしないんだろう。ただエージェントに全部任せちゃうんだ。でも、モデル(やその安全性フィルタ)というフィルターを通さずに、どう動いているかを実際に理解しようとする人にとっては、様々なシステムに面白い穴が残されることになるはずさ。

7
pickle-wizard
約20時間前

前の職場でセキュリティチームがnetcatやcurlの使用を許可してくれなかったから、その回避策として /dev/TCP を使ってた。操作感はnetcatやcurlほど良くはなかったけど、用は足りたよ。

8
MisterTea
約20時間前

TIL: bashや他のシェルは、Plan 9の /net ディレクトリとカーネルのip(3)ファイルサーバーを真似しようとしてるのか。本物のファイルシステムじゃないのが残念。あと、パスのルートを /net と呼ぶチャンスを逃したのも惜しいな。

9
mlhpdx
約18時間前

次のレベルをアンロックするなら、/dev/udp 越しにHTTP/3リクエストを送ってみなよ。

10
ddlsmurf
約17時間前

なんで /dev なんて使うんだ?必要なのは電池と針2本、それに適当な長さのイーサネットケーブルだけでいいだろ。