Linux 上で DTCP を使って IPv6 over IP トンネルを張る

IPv6 over IP トンネルを張るときに、トンネルの向こう側 (つまり IPv6 接続サービスを提供するプロバイダ) と、 トンネルのこちら側 (つまり自分のサイトのルータ) の IP アドレスを決める必要があります。 アドレスさえ決まっていれば、あとは

ifconfig sit0 up tunnel ::トンネルの向こう側のアドレス

を実行して、トンネルを張るだけです。 トンネルのインタフェースを調べるには、 「ip -6 tunnel」 を実行します。 例えば、 「トンネルの向こう側のアドレス」 として 「43.244.255.37」 を指定してトンネルを張り、 トンネルのインタフェースを確認してみます。

% ifconfig sit0 up tunnel ::43.244.255.37

% ip -6 tunnel
sit0: ipv6/ip  remote any  local any  ttl 64  nopmtudisc
sit1: ipv6/ip  remote 43.244.255.37  local any  ttl 64 

インタフェースが「sit1」 であることが確認できました。 では、sit1 へ ping6 を打って、 トンネルが開通しているか調べてみましょう。

% ping6 -I sit1 ff02::2
PING ff02::2(ff02::2) from fe80::3cc1:375 sit1: 56 data bytes
64 bytes from fe80::2bf4:ff25: icmp_seq=1 ttl=64 time=6.50 ms
64 bytes from fe80::2bf4:ff25: icmp_seq=2 ttl=64 time=7.34 ms
64 bytes from fe80::2bf4:ff25: icmp_seq=3 ttl=64 time=7.14 ms

--- ff02::2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2007ms
rtt min/avg/max/mdev = 6.501/6.997/7.348/0.367 ms

無事、向こう側のルータから返事 (echo reply) が返ってきました。 「fe80::2bf4:ff25」 というのは 10 進数で書けば 「fe80::43.244.255.37」 のことで、 つまりトンネルの向こう側のアドレスですね。

DTCP (Dynamic Tunnel Control Protocol)

以上のような感じで極めて手軽に IPv6 over IP トンネルを張ることができるわけですが、 問題は冒頭に述べた、 「トンネルの向こう側と、こちら側の IP アドレス」 を決める方法です。 基本的には、プロバイダに設定してもらうことになりますが、 こちら側の IP アドレスが固定でない場合は、 自動的に設定する仕掛けが必要になります。

Trumpet Software International Pty Ltd. によって提案された方法が、 DTCP (Dynamic Tunnel Control Protocol) です。 Feel6 をはじめとして、 いくつかのプロバイダで採用されています。 DTCP 接続の一例を次に示します。 S: が、プロバイダ (Feel6) の DTCP サーバ、 C: が、こちら側で動かす DTCP クライアント (この例では telnet で代用) です。

    % telnet dtcp.feel6.jp 20200
    Trying 43.244.255.119...
    Connected to dtcp.feel6.jp.
    Escape character is '^]'.
S:  +OK 7829445925a06093ef7f5d995ac7d7f5 FBDC TunnelBroker (version 0.2) Ready. <1817>:4096
C:  tunnel sengoku f0e130bfddaef3a5a526f77738bc91a3 network
S:  +OK 60.32.85.217 43.244.255.37 2001:03e0:03c3::/48

C:  ping
S:  +OK pong

C:  quit
S:  +OK tunnel server quitting

このように APOP によく似たプロトコルで認証を行ないます。 つまり、サーバから最初に提示される 「7829445925a06093ef7f5d995ac7d7f5」 が チャレンジで、これに対するレスポンスは、 「ユーザID」 「チャレンジ」 「パスワード」 をつなげた文字列の MD5 を計算する ことによって求めます。 この例では、 ユーザID は 「sengoku」 、 パスワードは 「password」 なので、以下のように計算できます。

% echo -n 'sengoku7829445925a06093ef7f5d995ac7d7f5password' | md5
f0e130bfddaef3a5a526f77738bc91a3

こうやって求めたレスポンスを、 「tunnel sengoku f0e130bfddaef3a5a526f77738bc91a3 network」 という形で送って認証が成功すると、 「+OK 60.32.85.217 43.244.255.37 2001:03e0:03c3::/48」 という返答がサーバから返ってきます。 「+OK」 に続く最初の IP アドレスが、 「トンネルのこちら側の IP アドレス」 で、 これは DTCP クライアントの IP アドレスがそのまま使われます。 二番目の IP アドレス 「43.244.255.37」 が、 サーバが指定した 「トンネルの向こう側のアドレス」 です。 三番目の IPv6 アドレスは、 プロバイダから割当てられた 「/48」 アドレスです。

これでトンネルは使える状態になっているはずです。 前述したように 「ifconfig」 でトンネルを張ります。 ただし DTCP 接続が切れると、 プロバイダはトンネルを無効にしてしまいます。 DTCP 接続は通信がない状態が続くと切られてしまうので、 定期的に 「ping」 を送る必要があります。 DTCP 接続を明示的に切りたい場合は、 「quit」 を送信します。

DTCP クライアント

Linux 上の DTCP クライアントの実装もあるようですが、 前述したように DTCP 自体は非常に単純なプロトコルなので、 perl スクリプトで書いてみることにしました。 perl スクリプトなら必要に応じて書き換えるのが容易なので、 いろいろ実験してみたいときは最適です。


use Net::POP3;
use Digest::MD5;

my $pop = Net::POP3->new($host, Port => $port);
my $banner = ${*$pop}{'net_pop3_banner'};
if ($banner =~ /^(\S+)\s/) {
    $banner = $1;
} else {
    $pop->close();
    exit 1;
}

my $md = Digest::MD5->new();
$md->add($user, $banner, $pass);
my $cmd = $pop->command('tunnel', $user, $md->hexdigest, 'network');
my $response = $cmd->getline();
if ($response =~ /^\+OK\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+([\d\:a-fA-F]+)\/(\d+)/) {
    ($local, $remote, $prefix, $nbits) = ($1, $2, $3, $4);
} else {
    $pop->close();
    exit 1;
}

while (1) {
    sleep 60;
    my $cmd = $pop->command('ping');
    my $pong = $cmd->getline();
    unless ($pong =~ /^\+OK pong/) {
        last;
    }
}

DTCP はもともと APOP によく似ているので、 Net::POP3 モジュールを使うと、 このように非常に簡単に書けてしまいます。 動作確認しつつ、 必要に応じて機能を拡充していけばよいでしょう。

セッションが切れてしまったときにつなぎ直す機能などを 追加した、私が現在使っているバージョンはこちら:

設定ファイル 「/etc/ppp/dtcp.conf」 には、 次のような感じで設定情報を書いておきます。

# ホスト名   ポート番号   ユーザID    パスワード
dtcp.feel6.jp     20200   sengoku     password

| home | up | Last modified: 2019-10-08 | Browser: 3.15.7.212
sengoku@gcd.org