はじめに
アプリケーションで {"name": "Alice", "age": 25}
というJSONを送っているとき、
それはネットワーク上でも そのまま "{"name": "Alice", "age": 25}"
という文字列として流れているのか?
それとも、どこかで勝手に暗号的な何かに変換されているのか?
実際に TypeScript (Express) サーバ と Python クライアント 、そしてtcpdumpで検証しました。
実験環境
- macOS (Apple Silicon M3)
- Node.js + Express (サーバ)
- Python + requests (クライアント)
- tcpdump (パケットキャプチャ)
実験
1. サーバを用意
TypeScript + Express で /echo
エンドポイントを作成しました。
import express from "express";
const app = express();
app.use(express.json());
app.post("/echo", (req, res) => {
res.json({
received: req.body,
serverTime: new Date().toISOString(),
});
});
app.listen(6000, () => console.log("Listening on http://127.0.0.1:6000"));
2. クライアントからJSONをPOST
Python の requests ライブラリでPOSTしました。
import requests
r = requests.post("http://127.0.0.1:6000/echo", json={"name": "Alice", "age": 25})
print(r.json())
3. パケットキャプチャ
パケットキャプチャとは?
ネットワーク上を流れるデータを小さな単位(パケット)に分割し、その内容を記録・解析する技術
イメージ
[App1] ⇄ (TCP/IP stack) ⇄ [lo0] ⇄ (TCP/IP stack) ⇄ [App2]
↑ここをtcpdumpが覗いている
6000番ポートへのTCP通信をキャプチャし、ASCIIに変換します。
sudo tcpdump -i lo0 dst port 6000 -A
キャプチャ中サーバーにリクエストを送ると、このように受け取られた結果が出ました。
{"name": "Alice", "age": 25} がバッチリ入っており、ネットワーク上に文字情報が流されていることが確認できました!
tcpdumpの -xオプションを使うことで、16進数で表示することもできます。
ハイライトしている部分が、ASCII表示のAliceに対応します。
4. 暗号化通信の場合
せっかくなので、https対応させた場合にどのような情報がやりとりされているのかを確認してみました。先ほどの実装に自己署名証明書(mkcertで作成)をつけて検証しています。
httpでは読めていた情報が全く読めなくなった!
結論
アプリケーションが送った文字列は、バイト列に変換されてそのままネットワーク上を流れている。
直感的なアプローチで情報が送受信されていることに感動!