こんにちは!クラウドインフラやKubernetesの裏側で、日々飛び交うパケットの海に魅せられているSREの私です。
皆さんは、物理的なルーターやLANケーブルが一本もないクラウドの世界や、一つのマシンのなかで何個もの仮想マシン(VM)やコンテナが何食わぬ顔で動いている仕組みについて、不思議に思ったことはありませんか? 「目に見えないネットワークの世界って、いったいどうなっているんだろう?」と、胸をときめかせた方も多いはずです。
今回は、そんな仮想化ネットワークの心臓部であり、Linuxカーネルの隠れた名優である「TAP(タップ)デバイス」と「TUN(タン)デバイス」の世界へ皆さんをご案内します。難しい英語の仕様書を放り出して、身近な例えから一歩ずつ紐解いていきましょう!
—
1. 仮想空間の郵便配達:vNICと仮想ネットワークの基本
私たちが普段使っているノートパソコンには、Wi-Fiや有線LANの差込口(物理的なNIC)がありますよね。これがあるからこそ、世界中のWebサイトと通信できます。
では、1台の強靭な物理サーバーのなかで動く「仮想マシン(VM)」や「KubernetesのPod」は、どうやって外の世界と通信しているのでしょうか?
実は、彼らが使っているのは物理的なハードウェアではなく、ソフトウェアで作られた「vNIC(仮想ネットワークインターフェイス)」という偽物の(しかし極めて優秀な)NICです。
このvNICは、いわば「仮想マシン専属の郵便受け」です。仮想マシンが手紙(データパケット)を書き上げてこの郵便受けにポンと放り込むと、それを現実世界のネットワークへと送り届けなければなりません。ここで「誰がその手紙を受け取って、どこへ運ぶのか?」という重大な役割を担うのが、今回主役となるTAPデバイスとTUNデバイスなのです。
—
2. TUNとTAPは何が違う? 身近な例えで理解する
Linuxカーネルのなかには、OSとアプリの橋渡しをするための「仮想的なネットワークカード」を作る仕組みが備わっています。それが、名前がよく似た tun と tap です。
一言で違いを言うと、以下のようになります。
TUNデバイス(L3 / ネットワーク層)- 「荷物そのもの(IPパケット)」だけをやり取りする。宛先の宛名や差出人は見るけれど、段ボール箱の形やガムテープの色(L2のイーサネットフレーム)は気にしない。
TAPデバイス(L2 / データリンク層)- 「段ボール箱(イーサネットフレーム / MACアドレス付き)」ごとやり取りする。LANケーブルのプラグそのものを抜き差しするようなイメージ。
郵便配達員に例えてみましょう
- TUN(L3)のイメージ:
手紙に書かれた「住所(IPアドレス)」だけを見て、テキパキと仕分けして次の街へ運ぶ「普通郵便の配達員」です。封筒(MACアドレスやL2ヘッダー)の細かい見た目は気にしません。VPNソフト(OpenVPNなど)でよく使われます。
- TAP(L3)のイメージ:
段ボール箱ごと、荷札(MACアドレス)をしっかり確認してトラックに積み込む「宅配便のドライバー」です。仮想マシンを物理ネットワークにそのままブリッジ(直結)させたいときや、KVMなどの本格的な仮想化ソフトでよく使われます。
—
3. 実際にLinuxでTAP/TUNを触ってみよう!
「百聞は一見にしかず」ということで、私たちの手元のLinux環境(ご自身のPCの検証用VMやWSLなど)で、実際にこの仮想デバイスを作ってみましょう!
ここからの操作には管理者権限(root)が必要です。ターミナルを開いて、一歩ずつ進んでいきましょう。
ステップ1:TUNデバイスの作成と確認
まずは、IPパケットを扱う tun0 という名前のTUNデバイスを作成してみます。以下のコマンドを実行してください。
# tunタイプの仮想ネットワークインターフェイス「tun0」を作成する
sudo ip tuntap add dev tun0 mode tun
# 作成されたデバイスの状態を確認する
ip link show tun0
コマンドが成功すると、カーネル内に新しいネットワークの窓口が生まれます。しかし、生まれたばかりの赤ちゃん状態なので、まだIPアドレスも振られておらず、眠った(DOWN)状態です。
ステップ2:IPアドレスを割り当てて起こしてみる
このTUNデバイスにIPアドレスを渡し、息を吹き込んでみましょう。
# tun0にIPアドレス(例: 192.168.100.1/24)を割り当てる
sudo ip addr add 192.168.100.1/24 dev tun0
# デバイスを有効化(UP)する
sudo ip link set tun0 up
# もう一度ステータスを確認する
ip addr show tun0
これで、あなたのLinuxカーネルのなかに 192.168.100.1 というIPを持った、仮想的な「手紙の受け渡し口」が完成しました!
ステップ3:使い終わったらお片付け
検証が終わったら、お行儀よく綺麗に削除しておきましょう。デバイスを削除すると、それに紐づくルート情報などもカーネルが綺麗に片付けてくれます。
# 作成したtun0デバイスを削除する
sudo ip tuntap del dev tun0 mode tun
—
4. アプリケーションからパケットを読み書きする魔法
「でも、作ったデバイスの向こう側には誰もいないよね? 誰が手紙を読むの?」という疑問が湧くはずです。
実は、TAP/TUNの最大の特徴は、「Linuxのネットワークカードなのに、普通のプログラム(ファイル読み書き)でパケットをごっそり読み書きできる」という点にあります。
C言語やPythonなどのプログラムから、作成した /dev/net/tun ファイルを開き、read() や write() システムコールを呼び出すだけで、仮想マシンが送信した生きたパケットをそのままキャプチャしたり、逆にパケットを注入したりできてしまうのです。
Pythonを例に、その概念的なコードを見てみましょう(※実際の動作には適切な権限やライブラリが必要です)。
import os
import fcntl
import struct
# TUNデバイスを操作するための定数(カーネルのお作法)
TUNSETIFF = 0x400454ca
IFF_TUN = 0x0001
IFF_NO_PI = 0x1000
# /dev/net/tunを開く(ネットワークカードと直接つながるファイル!)
tun_file = os.open("/dev/net/tun", os.O_RDWR)
# カーネルに対して「tun1という名前のTUNデバイスを作って!」とお願いする
ifr = struct.pack("16sH", b"tun1", IFF_TUN | IFF_NO_PI)
fcntl.ioctl(tun_file, TUNSETIFF, ifr)
print("仮想ネットワークカード tun1 がPythonプログラムと結びつきました!")
# 無限ループで仮想マシンから流れてくるパケットを待ち受ける
while True:
# パケットが届くまでここでブロック(待機)する
packet = os.read(tun_file, 2048)
print(f"パケットをキャッチしました! サイズ: {len(bytes(packet))} バイト")
# ここでパケットの中身を解析したり、加工して送り返したりできる!
まるで魔法のようですが、OpenVPNなどのセキュアなトンネリングツールや、DockerやKubernetesが内部で使っている高度な仮想ネットワーク(CNIプラグインの一部など)も、基本はこの仕組みを何重にも高度に応用して成り立っています。
—
5. まとめ:パケットの旅立ちを見守るSREの視点
今回は、仮想化ネットワークの基礎の基礎である TAP/TUNデバイス について、郵便配達の例えや実際のコマンド操作を交えて解説しました。
- TUN はL3(IPパケット)を扱う、宛先重視の配達員。
- TAP はL2(フレーム)を扱う、段ボール箱ごと運ぶドライバー。
- これらはカーネル空間とユーザー空間(プログラム)を繋ぐ、パケットの出入り口(ファイル)として振る舞う。
「クラウドの裏側って難しそう…」と感じていた方も、Linuxのカーネルのなかで小さな郵便受け(TAP/TUN)がせっせと手紙を仕分けしている姿を想像すると、少し親しみが湧いてきたのではないでしょうか?
現場のトラブルシューティングで ip link や ip tuntap コマンドに出会ったときは、ぜひ今回の「郵便配達の仕組み」を思い出してみてください。きっと、目に見えないパケットの流れが鮮やかに脳内再生されるはずです。
それでは、また次回のインフラ探訪でお会いしましょう!快適なクラウド&K8sライフを!
コメント