OpenVPN のための Solaris 用 TAP ドライバ

目次

ご注意

ここで紹介しているプログラムは、カーネルモジュールを含んでいます。そのため、プログラム上に問題があった場合にはシステムがパニックもしくはハングし、システムに重大な障害を引き起こす可能性があります。以下のプログラムはテストプログラムで、十分な検証を行ってはいません。したがってあくまで個人の検証ためにお使いいただき、重要なシステム上では動作させないでください。本プログラムの使用により発生したトラブルなど、いかなる損害についても一切の責任を負いかねます。ご利用は自己責任にてお願いいたします。

概要

OpenVPN で利用する Solaris 用の TAP ドライバです。こちらを使うことで、Solaris 上で OpenVPN を使って レイヤ 2(Ethernet レベル)の VPN を構築することができるようになります。

もともとは 「Solaris で SoftEther もどきを動かそう」の仮想 HUB と 仮想 NIC デーモン間で利用するプロトコルの参考にしようと OpenVPN のコードを参照していたのですが、Solaris 用 TAP ドライバが無いことが分かったので、TUN ドライバと以前書いた仮想 NIC ドライバを元に TAP ドライバを作ってみることにしました。

TUN ドライバと TAP ドライバについて

OpenVPN は 仮想ネットワークに接続するため仮想ネットワークドライバとしてUniversal TUN/TAP ドライバ (もしくは互換ドライバ)を利用しています。TUN/TAP ドライバは Windows/Linux/BSD/MAC 等、各 OS 上で実装されたものが公開・配布されており、この TUN/TAP デバイスを使って OpenVPN の仮想ネットワークを構成することができます。
ドライバ名にある「TUN」と「TAP」は別々の機能を有したネットワークドライバで、各々以下のような特徴を持っています。

TUN ドライバ
IP トンネルを行うための 仮想 Point-To-Point ネットワークデバイスのドライバ。
TAP ドライバ
Ethernet トンネルを行うための仮想 Ethernet ネットワークデバイスのドライバ。

TUN ドライバと TAP ドライバを比べた場合、VPN 上で単にユニキャストパケットしか伝送しないのであれば、利用する側としてはほとんど差はないと思います。しかし、たとえばブロードキャストパケットやマルチキャストパケットを伝送する必要がある場合や、レイヤ 3 プロトコルとしてIP 以外のプロトコルを使う場合には TAP(=Ethernet ネットワークデバイス)を使う必要があります。
ほとんどの OS の場合には、この2つのドライバは一緒に配布されており、TUN、TAP デバイス共に利用可能です。しかし、Solaris 用の TUN/TAP ドライバには残念ながら「TUN」ドライバ、つまり Point-To-Pointネットワークデバイスのドライバしか含まれておりません。

TUN/TAP ドライバの変更点

Solaris 用の TUN ドライバの最終更新日(2000/06/20)を見る限り、今後 Solaris 用の TAP ドライバがリリースされる可能性は残念ながら少なそうです・・(やはり Solaris というところでしょうか)そこで、既存の Solaris 用 TUN ドライバを改造し、OpenVPN で利用可能な TAP ドライバを作成いたしました。変更点は以下のとおりです。

  • 04/28/2006
    • 新しい PPA の割り当てを行う tun_alloc_ppa() に自身の MAC アドレスをセットする処理を追加
    • DL_INFO_REQ を処理する tun_info_req() に MAC アドレスを返す処理を追加
    • DL_BIND_REQ を処理する tun_bind_req() に MAC アドレスを返す処理を追加
    • DL_PHYS_ADDR_REQ を処理する tun_physaddr_req() に MAC アドレスを返す処理を追加
    • DL_UNITDATA_REQ を処理する tun_unitdata_req() 内から tun_eth_hdr() を呼ぶように変更した。
    • DL_UNITDATA_IND を処理する tun_unitdata_ind() 内で、実際の宛先・送信元 MAC アドレスをセットするように変更した。
    • Ethernet ヘッダを追加する tun_eth_hdr() 内で、Ethernet ヘッダに実際の宛先・送信元 MAC アドレスをセットするように変更した。
    • Ethernet フレームのルーティングを行う tun_frame() 内から tun_frame_is_eligible() を呼ぶように変更した。
    • DL_SET_PHYS_ADDR_REQ を処理する tun_set_physaddr_req() 関数を追加した。
    • DL_ENABMULTI_REQ を処理する tun_enabmulti_req() 関数を追加した。(現在のところ実際にはなにもしない)
    • DL_DISABMULTI_REQ を処理する tun_disabmulti_req() 関数を追加した。(現在のところ実際にはなにもしない)
    • Ethernet ヘッダーのフレームタイプや宛先アドレスをチェックする tun_frame_is_eligible() 関数を追加した。
  • 05/03/2006
    • tun_frame_is_eligible() 内で、 802.3 フレームを受信した場合に SAP 0 でバインドしているストリームへのパケットの転送を許可するようにした。
    • tun_unitdata_req() を変更し 802.3 フレームを要求されている場合にはフレームのタイプフィールドにメッセージのサイズを書くようにした。
  • 05/08/2006
    • x86 Solaris 9 対応のために tun_unitdata_req() を修正し、frame type に使う SAP 値を、 STREAM がバインドしている SAP 値からもってくるようにした。*1
  • 05/12/2006
    • MAC アドレスを生成する tun_generate_mac_addr() を追加し、tap ドライバのアッタチ時に呼ばれるように変更した。
  • 11/05/2006
    • tun_ioctl()の中 PPA 取得するする部分を Universal TUN/TAP のオリジナルのものに戻した。
      これによって、openvpn 等のユーザプログラム側から TUNNEWPPA IOCTL コマンドを使ってインスタンス番号を指定できるようになった。
  • 11/16/2009
    • tun ドライバ時にも IP ヘッダのバージョンフィールドから IPv6/IPv4 を判断し、適切なストリームにルーティングできるようにした。これで、tun ドライバでも IPv6 パケットをやり取りできるようになった。

これ以降の変更履歴はこちらをご参照ください

OpenVPN 側の変更点

OpnenVPN 2.2.0 から、ここでご紹介していた patch が正式リリース版に統合されました。(2011/04/28)
そのため、OpenVPN 2.2.0 以降のバージョンを使う場合には OpenVPN 側の変更は必要ありません。

2.1.x 以前のバージョンの OpenVPN では Solaris 用の TAP デバイス(/dev/tap)を処理するルーチンが存在せず、そのままでは OpenVPN の設定ファイルで「dev tap」と TAP デバイスを指定してもエラーになってしまいます。そこで、OpenVPN 側のコードも併せて変更、追加を行い、Solaris 上でも「dev tap」が利用できるように Patch を提供していました。
Patch の変更履歴は以下のとおり。
  • 04/28/2006
    • Solaris 用の open_tun() 関数の中で /dev/tap を Ethernet ネットワークインターフェースとして plumb する処理を追加した。
    • do_ifconfig() 関数内の Solaris 用の処理の中に「dev tap」の場合の ifconfig コマンドの構文を追加した。
  • 10/09/2006
    • OpenVPN 2.0.9 がリリースされたので、OpenVPN 2.0.9 でもテストを行い、この tun.c ファイルを使ってコンパイル可能なことを確認した。(コードの変更はしてません)
  • 11/05/2006
    • Solaris用の open_tun() 関数の中で、インスタンス番号(ppa)を TAP ドライバに渡す方法を変更した。これによって、 "dev tap7"のように、openvpn の「dev」オプションで、インスタンス番号を指定できるようになった。
  • 12/07/2008
    • openvpn2.2 から内部で使われている関数名や引数が変更されたため、これにあわせて変更を行った。
  • 05/20/2009
    • tap ドライバのオープン時の処理に誤りがあり、opensolaris 上で実行した場合にエラー(I_POP ioctl の失敗)になってしてしまう問題を修正
  • 11/16/2009
    • tunドライバの変更にあわせて OpenVPN の tun ドライバ操作のコード内で「ipv6_explicitly_supported」フラグを True に設定した。これで tun-ipv6 オプションが使えるようになった。

ソースコードとダウンロード

Solaris 用 TAP(および TUN) ドライバソースファイル

管理の利便性からソースコードはGithub に移動いたしました。
今後はこちらにアップデートしていきます。ソースコードもこちらからご参照いただけます。(07/18/2012 更新)

TUN/TAP ドライバのダウンロード
tuntap.tar.gz
ソースコードの参照
http://github.com/kaizawa/tuntap

本コードは http://vtun.sourceforge.net/tun/ の TUN/TAP ドライバのコードを元にしており、本コードの配布は GPL に準じます。

Solaris 用 TAP デバイス対応のための OpenVPN の差分ファイル

OpenVPN 2.2.0 以降では必要ありません。2011/04/28

tun.c (OpenVPN 2.0.7、2.0.9 用)OpenVPN の TUN/TAP ドライバへの操作が書かれているソースコード
tun.c (OpenVPN 2.1_rc21 用*2)OpenVPN の TUN/TAP ドライバへの操作が書かれているソースコード

本コードは http://openvpn.net の tun.c のコードを元にしており、本コードの配布は GPL に準じます。

動作確認済み Solaris バージョン

TAP ドライバおよび 変更後の OpenVPN の動作確認状況は以下のようになっています。

プラットフォーム
Solarisバージョン
Sparc(32bit)Sparc(64bit)x86x64
Solaris 8 以前???
Solaris9?
Solaris10-
OpenSolaris-
Solaris 11 Exp??
OpenIndiana 148???
Soalris 11-?-

○:動作確認済み ×:動作不可 ?:未確認 -:該当なし

私の環境に限りがあるので全てを調べきれてませんが、Solaris 9 以上であれば(希望も含めて)動くのではないかと思います。

コンパイル&インストール

Solaris 用 TAP(および TUN) ドライバのコンパイル

コンパイルには gcc を使います。上記の tuntap.tar.gzファイルを展開し tuntap ディレクトリに移動後、configure, make を実行すると「tun」と「tap」という2つのドライバが作成されます。コンパイル終了後、make install にてファイルのコピーと、システムへのデバイスの追加が行われます。(configure スクリプトも少々変更しており、64bit Solaris で実行された場合には 32bit モジュールではなく、64bit ドライバをビルドし、ドライバが適切な場所にコピーされるようにしています。)

# ./configure						    
checking for gcc... gcc					    
checking for C compiler default output file name... a.out   
checking whether the C compiler works... yes		    
checking whether we are cross compiling... no		    
checking for suffix of executables...			    
checking for suffix of object files... o		    
checking whether we are using the GNU C compiler... yes	    
checking whether gcc accepts -g... yes			    
checking for gcc option to accept ANSI C... none needed	    
checking for a BSD-compatible install... ./install-sh -c    
checking for isainfo... :				    
configure: creating ./config.status			    
config.status: creating Makefile	
		    
# make                                            
gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" 
-DPACKAGE_BUGREPORT=\"\" -DTUN_VER=\"1.1\ 04/23/2006\" -O2 -Wall -D_KERNEL -I. -m64 -c tun.c -o tun.o -DTUNTAP_TUN
gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" 
-DPACKAGE_BUGREPORT=\"\" -DTUN_VER=\"1.1\ 04/23/2006\" -O2 -Wall -D_KERNEL -I. -m64 -c tun.c -o tap.o -DTUNTAP_TAP
ld -r -o tun tun.o
ld -r -o tap tap.o

# make install
ld -r -o tun tun.o
ld -r -o tap tap.o
./install-sh -c -m 644 -o root -g root if_tun.h /usr/include/net
./install-sh -c -m 644 -o root -g root tun /usr/kernel/drv/sparcv9
./install-sh -c -m 644 -o root -g root tap /usr/kernel/drv/sparcv9
./install-sh -c -m 644 -o root -g root tun.conf /usr/kernel/drv
./install-sh -c -m 644 -o root -g root tap.conf /usr/kernel/drv
/usr/sbin/rem_drv tun >/dev/null 2>&1
/usr/sbin/rem_drv tap >/dev/null 2>&1
/usr/sbin/add_drv tun
/usr/sbin/add_drv tap
#

差分ファイルを使った OpenVPN のコンパイル

OpenVPN 2.2.0 以降では必要ありません。2011/04/28

以下は OpenVPN 2.1.x 以前のバージョンで tap ドライバーを使う場合に必要な手順です。
OpenVPN のダウンロードページ より OpenVPN のソースコードをダウンロードしてきて展開し、展開後のディレクトリ内にある tun.c を上記の tun.c ファイルで置き換え、通常通り configure*3, make, make install を行います。
なお、OpenVPN 2.1 から tun.c が変更されたため、Version 2.1 用の tun.c も作成いたしましたので、コンパイルしようとしている OpenVPN のバージョンにあわせて適切な tun.c ファイルをダウンロードしてください。(以下は OpenVPN 2.0.7 の場合の例です)

# unzip openvpn-2.0.7.zip
# cd openvpn-2.0.7/
# cp /download_files/tun.c .

# ./configure --disable-lzo
checking for ifconfig... /usr/sbin/ifconfig
checking for ip... ip
checking for route... /usr/sbin/route
... 略...

# make
make  all-am
if gcc -DHAVE_CONFIG_H -I. -I. -I.    -I.  -g -O2 -MT base64.o -MD
... 略...

# make install
test -z "/usr/local/sbin" || /var/tmp/openvpn-2.0.7/install-sh -d "/usr/local/sbin"
 ./install-sh -c 'openvpn' '/usr/local/sbin/openvpn'
test -z "/usr/local/man/man8" || /var/tmp/openvpn-2.0.7/install-sh -d "/usr/local/man/man8"
./install-sh -c -m 644 './openvpn.8' '/usr/local/man/man8/openvpn.8'
#

** tun.c は OpenVPN 2.0.7、OpenVPN 2.0.9、および OpenVPN 2.2_rc15 に含まれている tun.c ファイルを元に作成しておりますので、それ以外の以外のバージョンの OpenVPN のソースコード群と一緒にコンパイルするとエラーになってしまうかもしれません。

使い方

インストール後は通常通り OpenVPN を利用可能です。TAP デバイスを使う場合は設定ファイルに「dev tap」と指定するか、openvpn コマンドの起動オプションとして「--dev tap」を指定します。
OpenVPN の設定例」に私がテストで利用した設定ファイルをサンプルとして載せてありますのでこちらも参照いただければと思います。ただこれは単純な場合の設定例ですし、私自身あまり OpenVPN の設定について詳しくないので、詳細については公式ページのマニュアルをご参照ください。
また、Google 等で検索すると Linux や BSD での設定方法について日本語で詳しく解説されているページ見がつかりますので、そちらも参考になるのではないかと思います。

[WYSIWYG編集]


*1 本来 SAP 値は DL_UNITDATA_REQ メッセージに含まれる DLSAP アドレスから取ってくるべきですが、x86 Solaris 9 ではなぜか DLSAP アドレスに正しい SAP 値が含まれていないようなので、このように修正しました。x86 Solaris 9 のサポートを考えなければ以前のコードの方が適切と思います。
*2 次期 OpenVPNバージョンのリリース候補版です
*3 私の環境では lzo(圧縮ライブラリ) がインストールされていないため、--disable-lzo を指定しています。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: Wed, 18 Jul 2012 00:48:10 JST (1746d)