ユニバーサル TUN/TAP デバイスドライバ Copyright (C) 1999-2000 Maxim Krasnyansky Linux, Solaris 対応ドライバ Copyright (C) 1999-2000 Maxim Krasnyansky FreeBSD 対応 TAP ドライバ Copyright (c) 1999-2000 Maksim Yevmenkin この文書は 2002 年に Florian Thiel によって 改訂されました。 1. 解説 TUN/TAP デバイスドライバは、パケットを送受信するインタフェースを ユーザ空間のプログラムに提供します。 このデバイスは単純な Point-to-Point デバイスや、イーサネットデバイス  のようなものとみなせます。ただし、物理メディアからではなくユーザ空間の  プログラムからパケットを受信し、物理メディアにではなくユーザ空間の  プログラムにパケットを送信します。 このドライバを使うためには、プログラムは /dev/net/tun をオープンし、 適切な ioctl() を発行してカーネルにネットワークデバイスを登録 しなくてはなりません。 ネットワークデバイスは、選択されたオプションに応じて tunXX もしくは tapXX として現れます。 プログラムがそのファイルディスクリプタをクローズすると、 ネットワークデバイスおよびそのデバイスと通信しているすべてのルート (route) が消滅します。 選択されたデバイスのタイプに応じて、ユーザ空間のプログラムが 読み書きする対象は、IP パケット (tun デバイスの場合) もしくは イーサネットフレーム (tap デバイスの場合) のいずれかになります。 ioctl() に与えたフラグによって、どちらになるかかが決まります。 http://vtun.sourceforge.net/tun にあるパッケージには、tun デバイスと tap デバイスの使い方を示すふたつの簡単なプログラム例が 同梱されています。 どちらのプログラムも、ふたつのネットワークインタフェース間の橋 (ブリッジ) のように動作します。 br_select.c - select システムコールをベースにしたブリッジ br_sigio.c - async io と SIGIO シグナルをベースにしたブリッジ でも、ベストの実例は VTun http://vtun.sourceforge.net です :)) 2. 設定 デバイスノードを作成する: mkdir /dev/net (まだ /dev/net が存在しない場合) mknod /dev/net/tun c 10 200 パーミッションを設定する たとえばこのデバイスへのアクセスを root に限りたければ: chmod 0700 /dev/net/tun ネットワークデバイスをアサインする権利を一般ユーザに与えるのは いい考えでは「ありません」。ユーザが、ファイアウォールや 管理者をだます目的で、にせのネットワークインタフェースを アサインできるようになってしまいます。 ドライバのモジュールを自動的にロードする場合 お使いのカーネルで「カーネルモジュールローダ」−モジュールの 自動ロードのサポート−が有効になっているのを確認してください。 次の行を /etc/modules.conf に追加する: alias char-major-10-200 tun 次のコマンドを実行する depmod -a 手動でロードする場合 モジュールを手動でロードするには: modprobe tun 後者の場合、必要となるたびに毎回モジュールをロードしなくてはなりません。 前者の場合だと、/dev/net/tun がオープンされた時にモジュールは自動的に ロードされます。 3. プログラムのインタフェース 3.1 ネットワークデバイスの割当て: char *dev は、使用するデバイスの名前に書式指定文字列をくっつけたものに すべきです (たとえば "tun%d")。でも、(わたしの知る限りでは) 妥当な ネットワークデバイスの名前ならなんでも使えます。 この文字列へのポインタは、実際のデバイス名 (たとえば "tun0")  によって上書きされることに注目してください。 #include #include int tun_alloc(char *dev) { struct ifreq ifr; int fd, err; if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) return tun_alloc_old(dev); memset(&ifr, 0, sizeof(ifr)); /* フラグ: IFF_TUN - TUN デバイス (イーサネットのヘッダなし) * IFF_TAP - TAP デバイス * * IFF_NO_PI - パケットの情報を提供しない */ ifr.ifr_flags = IFF_TUN; if( *dev ) strncpy(ifr.ifr_name, dev, IFNAMSIZ); if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ close(fd); return err; } strcpy(dev, ifr.ifr_name); return fd; } 3.2 フレームのフォーマット: フラグ IFF_NO_PI がセットされていない場合、 それぞれのフレームのフォーマットは: フラグ [2 バイト] プロトコル [2 バイト] 生のプロトコル (IP, IPv6, など) のフレーム ユニバーサル TUN/TAP デバイスドライバについてよくある質問 1. TUN/TAP ドライバはどのプラットフォームをサポートしていますか? 今のところ、ドライバは 3 種類の Unix 系 OS に向けて書かれています。 Linux kernels 2.2.x, 2.4.x FreeBSD 3.x, 4.x, 5.x Solaris 2.6, 7.0, 8.0 2. TUN/TAP ドライバはどんな用途に使うのですか? 上記の通り、TUN/TAP ドライバの主な用途はトンネリングです。 VTun (http://vtun.sourceforge.net) で用いられています。 TUN/TAP を使うもうひとつの興味深いアプリケーションは、pipsecd です (http://perso.enst.fr/~beyssac/pipsec/)。 (FreeS/WAN とは違い) 完全なカーネルレベルのルーティングを使うことができる ユーザ空間での IPSec の実装です。 3. 仮想ネットワークデバイスは実際どのように動作するのですか? 仮想ネットワークデバイスは単純な Point-to-Point デバイスや、 イーサネットデバイスのようなものとみなせます。 ただし、物理メディアからではなくユーザ空間のプログラムから パケットを受信し、物理メディアにではなくユーザ空間のプログラムに パケットを送信します。 仮に tap0 に IPX を設定したとすると、その後はカーネルが tap0 に IPX パケットを送信するたびに、そのパケットはアプリケーション (たとえば VTun) に渡されます。アプリケーションはパケットを 暗号化・圧縮し、TCP や UDP 経由で通信先に送信します。 通信先で動作しているアプリケーションは、受信したデータを 伸長・復号化して、得られたパケットを TAP デバイスに書きこみます。 するとカーネルはそのパケットをあたかも実際の物理デバイスから 来たものと同様に処理するのです。 4. TUN ドライバと TAP ドライバの違いはなんですか? TUN は IP フレームに対して動作します。TAP はイーサネットフレームに 対して動作します。 言いかえると、tun を使用しているなら IP パケットしか読み書きできないし、 tap を使用しているならイーサネットフレームしか読み書きできない ということです。 5. BPF と TUN/TAP ドライバの違いはなんですか? BPF は先進的なパケットフィルタです。すでに存在している ネットワークインタフェースに結びつけることができます。 BPF は仮想ネットワークインタフェースを提供しません。 TUN/TAP ドライバは仮想ネットワークインタフェースを提供しますし、 この仮想ネットワークインタフェースに BPF を結びつけることも 可能です。 6. TAP ドライバはカーネルのイーサネットブリッジングをサポート していますか? はい。Linux と FreeBSD 用のドライバはイーサネットブリッジングを サポートしています。 日本語訳: 小林 雅典 (2003/01/24) 校正: 中野 武雄 山下 義之