仙石浩明の日記

2011年6月20日

フレッツ 光ネクストの IPv6 PPPoE 接続を OCN 光アクセスで使ってみた tweets

6月1日から NTT東日本のフレッツ 光ネクストにおいて IPv6 PPPoE 接続の提供が始まった。 私は OCN光アクセスを契約しているが、 幸い OCN (NTTコミュニケーションズ) も、 NTT東日本に合わせて順次対応を開始ということなので、 さっそく OCN へ電話で問合わせてみたら、 申込書をメールで送るので記入押印の上 FAX で送り返して欲しい、とのこと。

いまどき Web で申し込めないなんて、 と思いつつ 8ページにもわたる申込書 (いつも感じるが OCN の申込書は無駄にページ数が多い *_*) を FAX で送付。 すると翌日電話がかかってきて、 開通日は 10日後などとおっしゃる。 それじゃ World IPv6 Day に間に合わないじゃんと思ったが、 どんな変更でも申込みから 7営業日は最低でもかかるらしいので仕方がない。 なお、 工事費および月額使用料は無料。

OCN には元々月額 315円の 「OCN IPv6」 というサービスがあるが、 OCN IPv6 はフレッツ網に PPPoE によるトンネルを張って IPv4 を通し (OCN フレッツ光)、 その IPv4 上に L2TP (Layer 2 Tunneling Protocol) によるトンネルを張って PPP セッションを通し、 その PPP 上に IPv6 を通すという屋上屋を架す方式だったのに対し、 6月1日から始まった 「IPv6インターネット接続」 はフレッツ網に PPPoE によるトンネルを張って IPv6 を通す方式。

つまり OCN フレッツ光の IPv4 の部分を IPv6 でそのまま置き換えたシンプルな方式。 もちろんフレッツ網に IPv6 を直接通す 「ネイティブ方式」 が一番シンプルだが、 ネイティブ方式に関しては 「平成23年7月を目途に提供を予定」 ということなので、 どのようなサービスが始まるのか今のところ不明 (もう来週には 7月が始まってしまうのだが)。 7/24追記: ネイティブ方式サービスが始まった!

開通日の 2日前に郵便で届いた 「ご利用内容のご案内」 の欄外の注釈に、

IPv6 でインターネットに接続する際、 認証ID の @ 右側を “@bizf.ocn.ne.jp” の場合は “@bizf6.ocn.ne.jp” に、 “@bizd.ocn.ne.jp” の場合は “@bizd6.ocn.ne.jp” に変更してご利用下さい。

と書いてあった。 IPv6 での接続に関する説明はこの部分だけなので、 あとは推測するしかない (サポートに接続方法を聞いても、 単に IPv6トンネル対応ルータを購入してくれと言われる)。

とりあえず、 ふだん IPv4 で接続するときに使ってる PPPoE スクリプト (RP-PPPoE) を、 認証ID を “xxxx@bizf.ocn.ne.jp” から “xxxx@bizf6.ocn.ne.jp” に変更して走らせてみる:

20:39:13 senri pppd[16587]: Plugin /etc/ppp/plugins/rp-pppoe.so loaded.
20:39:13 senri pppd[16587]: RP-PPPoE plugin version 3.10 compiled against pppd 2.4.5
20:39:13 senri pppd[16587]: pppd 2.4.5 started by root, uid 0
20:39:13 senri pppd[16587]: PPP session is 6394 (0x18fa)
20:39:13 senri pppd[16587]: Connected to 00:1e:13:c2:69:c2 via interface eth1
20:39:13 senri pppd[16587]: Using interface ppp0
20:39:13 senri pppd[16587]: Connect: ppp0 <--> eth1
20:39:13 senri pppd[16587]: Couldn't increase MTU to 1500
20:39:13 senri pppd[16587]: Couldn't increase MRU to 1500
20:39:13 senri pppd[16587]: PAP authentication succeeded
20:39:13 senri pppd[16587]: peer from calling number 00:1E:13:C2:69:C2 authorized
20:39:13 senri pppd[16587]: local  LL address fe80::fd61:ff9b:eb97:1f93
20:39:13 senri pppd[16587]: remote LL address fe80::0090:1a00:41a3:d3f3

PPP は 1 つ以上のネットワーク層プロトコルを選択できるので、 IPCP (IP Control Protocol) と IPv6CP (IPv6 Control Protocol) の両方が流れてくるのかと予想したのだが、 流れてきたのは IPv6CP のみだった。 つまり “@bizf.ocn.ne.jp” で IPv4 用、 “@bizf6.ocn.ne.jp” で IPv6 用、 計 2本の PPPoE セッションを張ることになる。

上記ログから分かる通り Link Local とはいえ IPv6 なアドレス fe80::fd61:ff9b:eb97:1f93 が割り振られたのだから、 IPv6 で通信できるはず。 試しに PPP の対向サーバへ ping を打ってみると、 ちゃんと応答が返ってきた:

senri:~ $ ping6 -c 3 fe80::0090:1a00:41a3:d3f3%ppp0
PING fe80::90:1a00:41a3:d3f3%ppp0 (fe80::90:1a00:41a3:d3f3%ppp0): 48 data bytes
56 bytes from fe80::90:1a00:41a3:d3f3%ppp0: icmp_seq=0 ttl=255 time=3.936 ms
56 bytes from fe80::90:1a00:41a3:d3f3%ppp0: icmp_seq=1 ttl=255 time=4.050 ms
56 bytes from fe80::90:1a00:41a3:d3f3%ppp0: icmp_seq=2 ttl=255 time=4.176 ms
--- fe80::0090:1a00:41a3:d3f3%ppp0 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 3.936/4.054/4.176/0.098 ms
senri:~ $ 

じゃ、 Global なアドレス (固定アドレス契約なのでプレフィックスが 「ご利用内容のご案内」 に書かれていた) を付けて routing 設定を行なえば Global に通信できそうと思い、 試してみると...

senri:/ # ifconfig eth0 add 2400:400d:100::1/56
senri:/ # ip -6 route add default via fe80::0090:1a00:41a3:d3f3 dev ppp0
senri:/ # ping6 www.kame.net
PING www.kame.net (2001:200:dff:fff1:216:3eff:feb1:44d7): 48 data bytes
^C--- www.kame.net ping statistics ---
15 packets transmitted, 0 packets received, 100% packet loss
senri:/ # 

う〜ん、ダメか。 tcpdump を使って ppp0 に届く IPv6 パケットを監視してみたが、 OCN へ送信したパケットのみが表示され、 OCN 側からは何のパケットも届かない。

しかも、 他のサイトから 2400:400d:100::1 に対して ping6 を打ってみても何も届かない。 仮にこちらの設定に何か間違いがあったとしても、 OCN 側で 2400:400d:100::1 宛のパケットを routing していれば、 パケット自体は流れてきそうな気がするのだが... 少なくとも IPv4 の場合なら、 こちらの IP アドレス設定が間違っていても、 受け取れないだけでパケット自体は流れてくる。

ひょっとして、 「ご利用内容のご案内」に書かれていた 「2400:400d:100::」 というプレフィックスが間違っているんじゃ? と、 途方に暮れる。

仕方がないので 「次世代ネットワークに関する情報」 で提供されている仕様書にざっと目を通してみる。 すると、 NGN IPv6 ISP接続<トンネル方式>UNI仕様書の 7ページに、 IPv6 通信開始までの通信シーケンス図があった:

IPv6 sequence diagram

現在は IPv6CP まで完了している段階だから、 次は DHCPv6-PD Prefix 付与フェーズということになる。 この時まで、 DHCP (Dynamic Host Configuration Protocol) は自動設定のための仕掛けだから、 固定プレフィックスの場合は PD (Prefix Delegation, プレフィックス委譲) してもらうまでもないと思い込んでいた。 少なくとも IPv4 の場合は、 DHCP クライアントを動かさずに勝手に IP アドレスを割当てても通信できる。

OCN 側から一切パケットが流れてこないということは、 プレフィックス委譲してもらわなければ通信できない、 ということになる。 なぜ OCN は、 そんな不便な仕様にしているのか? と疑問に思いつつも、 WIDE-DHCPv6 をインストールして dhcp6c (DHCPv6 クライアント) を実行してみる:

senri:/ # cat /tmp/dhcp6c.conf
interface ppp0 {
        send ia-pd 0;
};
id-assoc pd 0{
        prefix-interface eth0 {
                sla-len 0;
        };
};
senri:/ # dhcp6c -c /tmp/dhcp6c.conf ppp0

「send ia-pd 0」 が solicit message (要請メッセージ) を OCN のルータ (上記シーケンス図では 「IP通信網」) へ送信するための設定。 「ia-pd」 というのは Identity Association for Prefix Delegation (プレフィックス委譲ID) の意味で、 複数の委譲を行ないたいときにそれぞれを区別するための ID らしいが、 今回は一つだけなのでデフォルトの 0 を指定。

「id-assoc pd 0」 がプレフィックス委譲ID が 0 のもの (今回は一つだけなので 0 しかない) に関する設定で、 「prefix-interface eth0」 と指定することによって、 OCN から委譲されたプレフィックスを eth0 インタフェースに割当てる。

dhcp6c を実行しつつ tcpdump で ppp0 での通信を監視してみると:

senri:/ # tcpdump -i ppp0
tcpdump: WARNING: ppp0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ppp0, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
23:38:43.826300 IP6 fe80::fd61:ff9b:eb97:1f93.546 > ff02::1:2.547: dhcp6 solicit
23:38:43.831744 IP6 fe80::90:1a00:41a3:d3f3.547 > fe80::fd61:ff9b:eb97:1f93.546: dhcp6 advertise
23:38:44.871958 IP6 fe80::fd61:ff9b:eb97:1f93.546 > ff02::1:2.547: dhcp6 solicit
23:38:44.876597 IP6 fe80::90:1a00:41a3:d3f3.547 > fe80::fd61:ff9b:eb97:1f93.546: dhcp6 advertise

無事、 solicit message が OCN へ送られ、 シーケンス図通り OCN から advertise が返ってきていることが分かる。 IPv6 のアドレスは桁数が多くて目がチラチラする (^^; ので、 こちら側 (シーケンス図では 「端末機器」) のアドレス fe80::fd61:ff9b:eb97:1f93緑色で表した。

シーケンス図によると advertise を受け取った後、 端末機器は Request を送らなければならないのだが、 なぜか 1秒待って solicit を再送している。 これが今回唯一のハマったところ。 原因を探るために DHCPv6 の仕組みを一通り調べる羽目になった。

原因は分かってみれば単純で、 単に ip6tables で advertise パケットを落とす設定になっていただけ。 そのため dhcp6c が advertise パケットを受け取れず、 solicit の再送を繰り返していた。 Link Local からの UDP 546番ポート宛のパケットを受け入れるよう設定したら、 無事 DHCPv6-PD のシーケンスも完了して IPv6 通信を開始することができた。

より正確に言えば、元々 「-m conntrack --ctstate ESTABLISHED,RELATED」 などと送信パケットと関連があるパケットは受け入れる設定にしていたが、 DHCPv6 の solicit は ff02::1:2 宛、 つまり全ルーターアドレス宛のマルチキャストであるのに対し、 OCN から返ってくる advertise は (当然) ユニキャストであるため、 関連があるパケットとは見なされず落としてしまっていた。

以下のような ipv6-up / ipv6-down スクリプト (IPv6 接続/切断時に pppd が呼び出すスクリプト) を書いて、 dhcp6c および radvd が自動的に起動/終了するようにした。

#!/bin/sh
PATH=/usr/bin:/usr/sbin:/bin:/sbin
. /etc/rc.d/hostname
command=$0
interface=$1
device=$2
speed=$3
local=$4
remote=$5
ipparam=$6
echo `date "+%F %T"` "$0" "$@" >> /var/log/pppd-ip6.log
case $command in
    *ipv6-up)
        updown="up"
        cat > /var/run/dhcp6c.$interface.conf <<EOF
interface $interface {
        send ia-pd 0;
};
id-assoc pd 0{
        prefix-interface $INNER_DEV {
                sla-len 0;
        };
};
EOF
        dhcp6c -c /var/run/dhcp6c.$interface.conf -p /var/run/dhcp6c.$interface.pid $interface
        ;;
    *ipv6-down)
        updown="down"
        if [ -f /var/run/dhcp6c.$interface.pid ]; then
            kill `cat /var/run/dhcp6c.$interface.pid`
        fi
        ;;
    *)
        exit 1
esac
case $ipparam in
    ngn6)
        if [ $updown = "up" ]; then
            ip -6 addr add 2400:400d:100::1 dev $INNER_DEV
            ip -6 route add default via $remote dev $interface
            radvd -C /usr/etc/radvd.conf
        else
            ip -6 addr del 2400:400d:100::1 dev $INNER_DEV
            if [ -f /var/run/radvd.pid ]; then
                kill `cat /var/run/radvd.pid`
            fi
        fi
        ;;
    *)
        exit 1
esac

dhcp6c によって自動的に割当てられる IPv6 アドレスの他に、 対外サービス用として 2400:400d:100::1 も割当てるようにしている。

Filed under: IPv6,システム構築・運用 — hiroaki_sengoku @ 09:08

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.