ディスカッション (11件)
知っていましたか?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。簡易的な疎通確認や、外部への依存を極力減らしたい時にぜひ活用してみてください。
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で話そうとしているポート番号だ。
かなりイケてるよね!
bashはそれ自体でHTTPを話せるらしい
いや、そんなことはない。BashができるのはTCPソケットを開くことまでだ。
君がやってるのはHTTPを自分で「話そう」としてるだけで、テストやデバッグ用ならいいし、手作業でやるのは最高に面白いけど、この疑似HTTPクライアントを実際の環境で監視なしに使おうものなら、間違いなく足元をすくわれるぞ。このおもちゃみたいなコードはHTTPを適切にパースしてないから、絶対にどこかで壊れる。
もちろんBashでHTTP/1.1クライアントを全部自作することもできるし、純粋なBashだけでHTTPサーバーだって作れる:https://github.com/bahamas10/bash-web-server
もっと常識的な非Bashシェルを使うなら、nc(netcat)を使うのが多分一番賢い選択だろうね。
へえ、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を使っちゃうよ。
数年前、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;"
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は昔すぎて忘れたけど、メールボックスをリストアップして個別のメッセージを取得したりできたよ。
この発見が、俺にとって「魔法なんてない」という考え方の始まりだった。コンピュータのあらゆる部分は人間が作ったもので、努力さえすればあるレベルまでは理解できるっていう気づきだね。
たぶん将来の多くの人はそんなこと気にしないんだろう。ただエージェントに全部任せちゃうんだ。でも、モデル(やその安全性フィルタ)というフィルターを通さずに、どう動いているかを実際に理解しようとする人にとっては、様々なシステムに面白い穴が残されることになるはずさ。
これ1997年頃からのKornShellの機能だよ。
https://github.com/ksh93/ast-open-archive/blame/master/src/c...
前の職場でセキュリティチームがnetcatやcurlの使用を許可してくれなかったから、その回避策として /dev/TCP を使ってた。操作感はnetcatやcurlほど良くはなかったけど、用は足りたよ。
TIL: bashや他のシェルは、Plan 9の /net ディレクトリとカーネルのip(3)ファイルサーバーを真似しようとしてるのか。本物のファイルシステムじゃないのが残念。あと、パスのルートを /net と呼ぶチャンスを逃したのも惜しいな。
次のレベルをアンロックするなら、/dev/udp 越しにHTTP/3リクエストを送ってみなよ。
なんで /dev なんて使うんだ?必要なのは電池と針2本、それに適当な長さのイーサネットケーブルだけでいいだろ。