2010/02/04

AlixのブロードバンドルータでIPv6

以前作成したalixなブロードバンドルータをフリービットのFeel6接続サービスを使ってIPv6に対応させてみました。

この手の作業は同じlinuxでもディストリビューションや環境に左右されるので、まず今回の環境をまとめておきます。

  • インターネット接続:NTT東日本 Bフレッツ + 固定IP
  • ブロードバンドルータHW:Alix 2C3
  • ブロードバンドルータSW:Debian lenny (eth0:Global ipv4 addr, eth1:192.168.1.1, eth2:192.168.10.1)
  • DTCPクライアント:自作Perlスクリプト
  • RAサーバ:debian lenny付属のradvdパッケージ from http://v6web.litech.org/radvd/dist/
  • クライアント1:Ubuntu 8.04 x86_64 (192.168.1.x)
  • クライアント2:Mac OS X 10.6.2 (192.168.1.x)

Feel6接続サービスへの登録

IPv6なネットワークに接続する方法はいくつかありますが、今回はフリービットのサービスを使う事にしました。 固定IPを使っているので静的にトンネルを作ってもらっても良かったのですが、将来プロバイダを変更するかもしれないですしね。

登録はFeel6のトップページから必要事項を送信するだけです。

DTCP接続を試してみる

Feel6のサーバにIPv6ネットワークへのトンネルを作ってもらうわけですが、その情報のやりとりはDTCPというプロトコルを使用するようです。 ここら辺の解説は「Linux 上で DTCP を使って IPv6 over IP トンネルを張る」がとても参考になりました。

検索してみるとDTCPの使い方としては、次のような方法がありました。

  • DTCPクライアントを自作する方法
  • USAGIプロジェクトが配布しているdtcpcコマンドを使用する方法

Linux 上で DTCP を使って IPv6 over IP トンネルを張る」にある"setup-dtcp"スクリプトやUSAGIプロジェクトのdtcpcを使ってみました。しかし内部で呼び出しているコマンドの実行に失敗するなど簡単にはできなかったため"setup-dtcp"の元になったスクリプトをベースに手作業でコマンドを実行していきました。

DTCPクライアントの自作

最終的には作り直したのですが、まずは参考にしたPerlスクリプトでトンネル状態を維持する事にしました。 参考にしたページにあるスクリプトでは変数定義が抜けているのと、Feel6から貰ったIPv6アドレスがわからないので出力ようにして、だいたい次のようなコードを追加しています。

#!/usr/bin/perl

my $host = "dtcp.feel6.jp";
my $port = 20200;
my $user = "xxxxxx";
my $pass = "xxxxxx";
...
    ($local, $remote, $prefix, $nbits) = ($1, $2, $3, $4);
    printf(STDERR "local=%s,remote=%s,prefix=%s,nbits=%s\n", $1, $2, $3, $4);
} else {
...

ここで$user$passには、Feel6登録時に入力したものを記入します。 実行に成功すると4つの文字列が手に入ります。

DTCPクライアントは接続を維持するために毎分PINGメッセージを送信しています。 そのためIPv6を使う間はずっと起動しておく必要があります。

AlixをIpv6ルータとして構成する

ここからはDTCPクライアントが裏側で動いている前提で書いています。

Feel6とは関係なしにBフレッツを使っているとNTTからIPv6アドレスが付与されます。 ただしこれは/64なプリフィックスなので、サブネット用に番号を加える事ができません。 また他の方のブログなどをみるとオプションを申し込まないと、NTTが準備したコンテンツ以外にアクセスする事は難しいようです。

Alixで確認すると、NTTから自動的に割り当てられるこのアドレスは以前Alixをルータにする投稿の中で、Bフレッツとの接続に使ったeth0に割り当てられています。

Bフレッツで自動的に割り当てられるIPv6アドレス

eth0      Link encap:イーサネット  ハードウェアアドレス 00:0d:xx:xx:xx:xx
          inet6アドレス: 2001:c90:489e:xxxx:xxxx:xxxx:xxxx:xxxx/64 範囲:グローバル
          inet6アドレス: fe80::xxxx:xxxx:xxxx:xxxx/64 範囲:リンク
...

Feel6から付与されるプリフィックスは/48ですから、前半64bitの残り16bit(0xffff分)を使ってネットワークを分割する事が可能になります。IPv4ではeth1, eth2でネットワークを分けているので、それにならってIPv6でもeth1, eth2でサブネットを設定する事にしました。

IPv6ルータになるための設定項目

Bフレッツ用のIPv6アドレスが割り当てられていた理由は、lennyのデフォルトとしてRouter Advertisement(RA)を受け付けるようになっている事に起因します。 ルータ自身がRAに反応しては困るらしくsysctlの設定を変更します。

Fee6を使う場合はRAを有効にしても大丈夫なんじゃないかという気はしつつ、先達に習うことにしました。 その他のアイデアとしてはeth0ではRAを受信してNTTのアドレスを構成しつつ、eth1, eth2はRAを無視して自分でアサインする、という構成も考えられましたが今回は試していません。

/etc/sysctl.confファイルの追加内容

...
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.all.forwarding=1
...

また直接は関係ないですが、この他にsysctl.confではipv6関連の設定を2つ行なっています。

net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
proc経由での設定変更について

sysctl.conf周りの設定は/procファイルシステムを通しても可能で、IPv6を説明した多くのサイトで$ echo 1 > /proc/sys/net/ipv6/conf/all/accept_raのようなコードが書かれています。 しかし恒久的な変更には/etc/sysctl.confファイルを使いましょう。

procに"0"や"1"を書き出したいが、sudoを使わないとという場合にはteeコマンドを使いましょう。

$ echo 1 | sudo tee /proc/sys/net/ipv6/conf/all/accept_ra

DTCPの出力からAlixにIPv6アドレスを付与する

DTCPクライアントの出力から次のような情報が得られています。

  • local - 自分のGlobal IPアドレス:219.117.xxx.xxx
  • remote - Feel6への接続用IPアドレス:43.244.xxx.xx
  • prefix - IPv6接続に使用するプリフィックス:2001:03xx:xxxx::/48
Alixの各インタフェースに割り当てる情報を決めていく

prefixは最後の2byte(16bit)が空いているので、ここを埋めてeth1, eth2にどのようなサブネットを設定するか考えます。 何でも良いのですが、IPv4に合わせて最後は0001,0010としました。

  • eth1 prefix - 2001:03xx:xxxx:1::/64
  • eth2 prefix - 2001:03xx:xxxx:10::/64

ここまでを踏まえてそれぞれのIPv6アドレスを決めました。 アドレスは何でも良いですが、"192.168.1.1", "192.168.10.1"を16進数に変換した"c0a8:0101", "c0a8:a101"を使う事にしました。

  • eth1 ipv6 addr - 2001:03xx:xxxx:1::c0a8:0101/64
  • eth2 ipv6 addr - 2001:03xx:xxxx:10::c0a8:0a01/64

ただしalixから外部に通信する必要がなければサイトローカルユニキャストアドレス(fe80::/64)で十分なはずで、必要だとしても2つも追加する必要はなかったりします。 まぁどちらかのデバイスをダウンさせる事もあるかもしれないので、こういう設定にしてみました。

実際にIPv6環境を構築していく

情報は決まったのでコマンドをパチパチ打っていきます。

トンネルの構築

remoteアドレスをベースにsit0, sit1インタフェースを構成します。

$ sudo /sbin/ifconfig sit0 up tunnel ::43.244.xxx.xx

Alixではiptablesを構成しているので、通常の構成ではカプセル化したパケットが出ていきません。 dropしたパケットのログをみると次のようになっています。

iptablesでdropしたパケットの情報

...
[135368.059979] netfilter drop IN= OUT=ppp0 SRC=219.117.xxx.xxx DST=43.244.xxx.xx LEN=124 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=41
...
[136225.974684] netfilter drop IN=ppp0 OUT= MAC= SRC=43.244.xxx.xx DST=219.117.xxx.xxx LEN=124 TOS=0x00 PREC=0x00 TTL=246 ID=16480 PROTO=41
...

このproto=41を通すためにiptablesに設定を追加します。

iptables -A inppp -s 43.244.xxx.xx --proto 41 -j ACCEPT
iptables -A outppp -d 43.244.xxx.xx --proto 41 -j ACCEPT
ルーティング情報の設定

eth0にはBフレッツから割り当てられたアドレスが付いています。 当然デフォルトゲートウェイはeth0に向いているので、このルーティングを削除しつつ、Feel6に変更する設定を行ないます。

$ sudo /sbin/route -A inet6 del ::/0 dev eth0
$ sudo /sbin/route -A inet6 add ::/0 dev sit1
eth1, eth2にIPv6アドレスを付与する

外部との通信に使用するために、IPv6でいうところのグローバルユニキャストアドレスを追加します。

$ sudo /sbin/ip -f inet6 addr add 2001:03xx:xxxx:1::c0a8:0101/64 dev eth1
$ sudo /sbin/ip -f inet6 addr add 2001:03xx:xxxx:10::c0a8:a101/64 dev eth2
ここまでの稼働確認

おそらくping6は既にインストールされていると思うので、これを使って接続が確立しているか確認します。

$ ping6 www.kame.net
$ ping6 2001:200:0:8002:203:47ff:fea5:3085

ping6 www.kame.netの出力

PING www.kame.net(orange.kame.net) 56 data bytes
64 bytes from orange.kame.net: icmp_seq=1 ttl=54 time=14.2 ms
64 bytes from orange.kame.net: icmp_seq=2 ttl=54 time=13.3 ms

ping6 2001:200:0:8002:203:47ff:fea5:3085の出力

PING 2001:200:0:8002:203:47ff:fea5:3085(2001:200:0:8002:203:47ff:fea5:3085) 56 data bytes
64 bytes from 2001:200:0:8002:203:47ff:fea5:3085: icmp_seq=1 ttl=54 time=14.6 ms
64 bytes from 2001:200:0:8002:203:47ff:fea5:3085: icmp_seq=2 ttl=54 time=13.5 ms

生のIPv6アドレスはwww.kame.netのものです。 将来的に変更されているかもしれないので、nslookupでアドレスを確認してからping6に渡してください。

$ nslookup -type=AAAA www.kame.net

nslookup -type=AAAA出力例

$ nslookup -type=AAAA www.kame.net
Server:		192.168.1.x
Address:	192.168.1.x#53

Non-authoritative answer:
www.kame.net	has AAAA address 2001:200:0:8002:203:47ff:fea5:3085
....

もしping6がインストールされていなければ、iputils-pingパッケージを導入してください。 nslookupはdnsutilsパッケージに含まれています。

$ sudo apt-get install iputils-ping

ここまでうまく行けば、radvdクライアントを動かすか、クライアント側を適切に設定すればIPv6ネットワークに接続する事ができるようになります。

トラブルシュート

もしping6の実行に失敗してデバイスを指定する次のようなコマンドが成功するとしたら、ルーティング情報が間違っているはずです。

$ ping6 -I sit1 2001:200:0:8002:203:47ff:fea5:3085

またping6実行時にping: sendmsg: Operation not permittedメッセージが出力されているとすれば、iptablesの設定に失敗しているか、ip6tablesが設定されているのが原因でしょう。

いまはIPv6用のfirewallは素通しの状態になっているはずで、次のコマンドでデフォルトが"(policy ACCEPT)"になっている事を確認します。

sudo /sbin/ip6tables -L

期待する出力

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

radvdクライアントの起動

Alixではパッケージで配布されているradvdコマンドを使用します。

$ sudo apt-get install radvd

今回は次のような設定ファイルを準備しました。

/etc/radvd.confファイル

interface eth1
{
        AdvSendAdvert on;

        MinRtrAdvInterval 3;
        MaxRtrAdvInterval 10;

        prefix 2001:03xx:xxxx:1::/64
        {
                AdvOnLink on;
                AdvAutonomous on;
        };
};

interface eth2
{
        AdvSendAdvert on;

        MinRtrAdvInterval 3;
        MaxRtrAdvInterval 10;

        prefix 2001:03xx:xxxx:10::/64
        {
                AdvOnLink on;
                AdvAutonomous on;
        };
};

最後にradvdを起動して終りです。

$ sudo /etc/init.d/radvd start
radvdの初期設定について

パッケージに含まれる通常の構成だとAlixの再起動時に自動的にradvdが起動します。 これが悪いとはいいませんが、トンネルの構成をまだ自動化していないので意図しないタイミングでradvdが起動してしまうかもしれません。

今回はradvdを制御する目的で明示的に/etc/init.d/radvdスクリプトを実行する事にして、自動起動は停止する事にしました。

$ sudo mv /etc/rc2.d/S50radvd /etc/rc2.d/K50radvd

クライアントの接続確認

本当は手動でルーティングをしていたのですが、radvdを使う方法を書く事にしたのでクライアント側でする事はあまりありません。 Ubuntu 8.04 x86_64以外にMac 10.6でもブラウザをいくつか立ち上げて確認をしています。

Ubuntu 8.04での稼働確認

accept_raは有効になっているので、基本的にIPアドレスはすでに割り当てられていました。 しかしufwを有効にしているせいかip6tablesのデフォルトポリシーがDROPになっていたためping6の実行に失敗しました。

ip6tablesの構成は後でする事にして、いまは全部の通信を許可しています。

$ sudo /sbin/ip6tables -P INPUT ACCEPT
$ sudo /sbin/ip6tables -P OUTPUT ACCEPT
$ sudo /sbin/ip6tables -P FORWARD ACCEPT

とりあえずWebブラウザだけを使って、keme.netの亀が踊るかどうか確認します。

http://www.kame.net/

Mozilla Firefox 3.0.17, Google Chromium 5.0.315.0 (37939) Ubuntu, Opera 10.10で確認しました。 結果としてOperaだけがIPv4で接続していました。

OperaはIPv6周りののバグ対策として、とりあえずIPv6を使えなくしたようですね。 一時的とはいえ後ろ向きな感じがしなくてはない対応ですが、フレームワークの問題で抜本的な対策が難しかったのかなぁ…。

Mac 10.6での稼働確認

Ubuntu同様に自動的にグローバルアドレスを受信しているので、Safariなどで何も考えなくても亀が踊っています。Opera 10.10を試してみたところやはりIPv6では接続できませんでした。

さいごに

Bフレッツのアドレスを使えるのであれば、eth0とbound0を組んでradvdだけ起動してしまえば使えそうな気もします。 それにサブネットを分ける必要性があるのか、という気もします。 まぁせっかくalixにはNICが3つも付いているので、これもまた良いでしょう。

しかし、一応動いているとはいえ頭の中が完全にIPv4のネットワークのマナーに染まっているので、IPv6的な考え方がまったくできていないと実感しています。 ここに書いた対応も成功事例ではありますが、本当のベストプラクティスとはいえないところがあるだろうと思います。まぁしばらくIPv6で遊んでみるつもりです。

この後の残作業はFirewall周りの他に、基本的なところでDTCPクライアントからeth1, eth2にサブネットワークを構成して、そのアドレスを反映したradvd.confを作成するところまでを自動化する必要があります。

まっさらなところからの自動化自体は簡単ですが、途中からのやり直しなんかを考えると、各作業の粒度を考えて個別のスクリプトにしないと安定しそうにありません。これも少し時間を考えて試行錯誤したいと思います。

とりあえずは次のステップはfirewallの設定ですかね。

0 件のコメント: