フレッツ光ネクスト用IPv6 PPPoEアダプターを作ってみる

フレッツ光ネクストとIPv6接続サービス

NTT東日本/西日本が提供しているFTTH NGNサービス「フレッツ光ネクスト」のユーザーは、プロバイダーのIPv6接続サービスを利用することができる。現在フレッツ光ネクストではIPv6接続サービスとして次の二通りの方式を用意しており、ユーザーが契約するプロバイダーによってどちらかの方式を選ぶことになっている。

  • IPv6 PPPoE方式
  • IPv6 IPoE方式

大手のプロバイダーでも、例えばOCNやSo-netなどはPPPoE方式、BIGLOBEや @niftyなどはIPoE方式と、提供する方式に違いがある。自分が利用するプロバイダーがどちらの方式によるIPv6接続サービスを提供しているか、確認する必要があるということだ。中にはIIJのように、両方の方式を提供しているプロバイダーもある。

どちらの方式が優れているということはなく、いずれも一長一短があるわけだが、特にPPPoE方式の方は接続するために「アダプター」と呼ばれる専用の機器 (機能)が必要になるので、この方式を利用する場合には何らかの方法で用意しなくてはいけない。プロバイダーやNTT東日本/西日本などから専用のアダプターを購入することもできるし、別のルーター機器を用意する方法もあるだろう。

アダプターの要求仕様は公開されており、「NGN IPv6 ISP接続<トンネル方式> 用アダプタガイドライン[NTT東日本][NTT西日本]」から入手可能だ。基本的にはRFCにしたがった標準仕様から構成されているので、頑張ればこれを見て自分で作ることもできる。

というわけで、PCルーターを使ってフレッツ光ネクスト用IPv6 PPPoEアダプターを作ってみることにしよう。接続形態にもよるが、アダプターに求められる機能はだいたい以下の通りとなる。

  1. IPv6 PPPoE機能
  2. DHCPv6機能
  3. IPv4ブリッジ機能
  4. マルチプレフィックス対応機能
  5. DNSプロクシー機能
  6. マルチキャスト通信機能

まず今回は、IPv6でインターネットと通信するために最低限必要な、1.〜3.までを実装してみたい。なお言うまでもないが、当然PCルーターのOSはNetBSDである。今回はNetBSD 6.0を使うことにしよう。

あらかじめ、プロバイダーへの申し込みを済ませておくことを忘れずに。

アダプターの接続形態

アダプターの仕様は、IPv4接続用のブロードバンドルーターと一緒に使う可能性を考慮して設計されている。接続形態としていくつかのパターンが考えられるが、次の二種類が代表的なパターンと言えるだろう。

  • 単機能型
  • ルーター機能一体型

単機能型IPv6 PPPoEアダプター

単機能型のアダプターは、IPv4用ブロードバンドルーターと縦に繋がる形で設置する。

../../_images/fig1.png

実はアダプターの置き場所はブロードバンドルーターの上(WAN側)でも下 (LAN側)でも良いのだが、ここでは直下に置く形を想定しよう。ただしこの形態では、ブロードバンドルーターの方に、PPPoEパススルー機能 [1] があることが前提となる。ブロードバンドルーターの仕様を確認しておこう。

アダプターはブロードバンドルーターのPPPoEパススルー機能を経由して、プロバイダーとのIPv6 PPPoE接続を行う。端末PCなどLAN側のネットワーク機器に対するIPv6インターネットへの接続性は、アダプターが提供する。IPv4インターネットへの接続性は従来と同じくブロードバンドルーターが提供し、ブロードバンドルーターとLANの間のIPv4通信はアダプターのIPv4ブリッジ機能によって双方向に転送される。

既にプロバイダーとのIPv4接続契約があり、ブロードバンドルーターを設置して運用していた実績がある場合には、単機能型のアダプターを導入するハードルの方が低いだろう。

ルーター機能一体型IPv6 PPPoEアダプター

ルーター機能一体型のアダプターは、IPv4用のルーター機能とIPv6用のルーター機能を一台で賄うデュアルスタック型ルーターとなる。

../../_images/fig2.png

新規にインターネット接続を始める場合には、IPv4/IPv6それぞれに別の接続機器を導入するよりも、ルーター機能一体型のアダプターを導入する方がシンプルで良いと思う。ただ自分で作ることを考えた場合には、ルーター機能一体型アダプターは若干ハードルが高い。

今回は、既存環境への影響が少ない単機能型アダプターを作ることにしよう。

アダプター機能の実装

IPv6 PPPoE機能

アダプターにするPCの想定環境は以下とする。

../../_images/fig3.png

まずPPPoEの設定をする。PPPoEセッションを張るWAN側のEthernetインタフェースを re0 として、その上にPPPoEインタフェース pppoe0 が起動されるように設定する。

# cat /etc/ifconfig.re0
up
# cat /etc/ifconfig.fxp0
up
# cat /etc/ifconfig.pppoe0
create
! /sbin/pppoectl -e re0 $int
! /sbin/pppoectl $int myauthproto=pap 'myauthname=<PPPoE接続ユーザ名>' 'myauthsecret=<PPPoE接続パスワード>' hisauthproto=none max-auth-failure=0
up
# cat /etc/rc.conf
(snip)
auto_ifconfig=NO
net_interfaces="re0 fxp0 pppoe0"
ip6mode=router
(snip)

設定そのものは、普通のIPv4用PPPoEの設定と変わらない。上記ではついでに ip6mode=router も設定し、RA受信による自動アドレス設定機能が働かないようにしてある。

ここまで設定したら再起動して、コンソールに次のようなカーネルメッセージが表示されてPPPoEが繋がったことを確認。ただしここではまだアドレスも経路も設定されていないため、通信はできないはずである。

pppoe0: connected to xxxxxxxxx-xxxxxxxxxx

PPPoEが繋がったら pppoe0 のリンクローカルアドレスを調べ、IPv6のデフォルトルーターとして指定する。

# ifconfig pppoe0
pppoe0: flags=8851<UP,POINTOPOINT,RUNNING,SIMPLEX,MULTICAST> mtu 1492
        inet6 fe80::2a0:b0ff:fe97:ce36%pppoe0 ->  prefixlen 64 scopeid 0x4
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# cat /etc/rc.conf
(snip)
defaultroute6="-interface fe80::2a0:b0ff:fe97:ce36%pppoe0"
(snip)

DHCPv6機能

プロバイダーからのIPv6アドレス取得には、DHCPv6-PDを使用する。

IPv4の場合には、通常PPPoE接続時にプロバイダーから単一の動的グローバル IPv4アドレスを取得するため、PPPoE上のIPCPプロトコルでアドレス割り当てを行うが、IPv6の場合にはグローバルIPv6プレフィックスを取得するので、PPPoE上のIPV6CPプロトコルではなく、DHCPv6-PD(Prefix Delegation)プロトコルを使うのである。

DHCPv6機能として、今回はwide-dhcpv6パッケージを使うことにしよう。まずは pkgsrcからwide-dhcpv6をインストールする。

# cd /usr/pkgsrc/net/wide-dhcpv6; make install
# pkg_info -I wide-dhcpv6
wide-dhcpv6-20080615 DHCP6 client, server and relay agent by WIDE project

次にwide-dhcpv6パッケージのDHCPv6クライアント dhcp6c 用の設定をする。PD(プレフィックス委譲)用のIA(アイデンティティ・アソシエーション)として IA_PD=0 を使用して、プロバイダーからIPv6プレフィックスが取得できることを確認しよう。

# cat /usr/pkg/etc/dhcp6c.conf
interface pppoe0 {
        send ia-pd 0;
};

id-assoc pd 0 {
        prefix-interface fxp0 {
                sla-len 0;
        };
};
# cat /etc/rc.conf
(snip)
dhcp6c=YES              dhcp6c_flags="pppoe0"
(snip)

再起動し、DHCPv6-PDでグローバルIPv6プレフィックス [2] が取得できて、LAN側のEthernetインタフェース fxp0 に設定されることを確認する。

# ifconfig fxp0
fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        address: 00:16:76:01:91:37
        media: Ethernet autoselect (none)
        status: no carrier
        inet6 fe80::216:76ff:fe01:9137%fxp0 prefixlen 64 scopeid 0x2
        inet6 2001:240:2002:6a00:216:76ff:fe01:9137 prefixlen 56
              ^^^^^^^^^^^^^^^^取得した/56プレフィックス       ^^プレフィックス長

LAN側のEthernetセグメントに、/48または/56以降のサブネット番号を設定したい場合には、dhcp6c.confprefix-interface 節にサブネット番号のビット長(sla-len)と値(sla-id)を指定する。

# cat /usr/pkg/etc/dhcp6c.conf
(snip)
id-assoc pd 0 {
        prefix-interface fxp0 {
                sla-len 8;
                sla-id 1;
        };
};
# ifconfig fxp0
fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        (snip)
        inet6 2001:240:2002:6a01:216:76ff:fe01:9137 prefixlen 64
                              ^^サブネット番号1               ^^56+8

グローバルIPv6プレフィックスが設定されたら、ルータ通知デーモン rtadvd を起動してLAN側ネットワークに対し fxp0 からRAを配布する設定をする。

# cat /etc/rc.conf
(snip)
rtadvd=YES              rtadvd_flags="fxp0"
(snip)

dhcp6c には、DHCPv6-PDでIPv6プレフィックスを取得した際にスクリプトを実行する機能がある。プレフィックスと一緒にDNSサーバーのアドレスを取得して /etc/resolv.conf に設定する処理と、fxp0 にリンクローカルアドレス以外のIPv6アドレスが設定されるのを待って rtadvd を再起動する処理を実行するスクリプトの設定を追加しておこう。

# cat /usr/pkg/etc/dhcp6c.conf
interface pppoe0 {
        send ia-pd 0;
        request domain-name-servers;
        script "/usr/pkg/etc/dhcp6c-script";
};
(snip)
# cat /usr/pkg/etc/dhcp6c-script
#!/bin/sh

new_resolv_conf="/etc/resolv.conf.new"
lan_if="fxp0"

if [ -n "$new_domain_name_servers" ]; then
    for nameserver in $new_domain_name_servers; do
        echo nameserver $nameserver >> $new_resolv_conf
    done
    chown root:wheel $new_resolv_conf
    chmod 644 $new_resolv_conf
    mv -f /etc/resolv.conf /etc/resolv.conf.old
    mv -f $new_resolv_conf /etc/resolv.conf
fi

(
    while ! /sbin/ifconfig "$lan_if" | egrep "prefixlen" | egrep -v "%$lan_if" >/dev/null 2>&1; do
        sleep 1
    done

    /etc/rc.d/rtadvd restart
) &

ここまで設定して再起動したら、LAN側ネットワークに接続されている端末機器からインターネットに対してIPv6通信ができる状態になっているはずだ。ただしまだIPv4通信はできない。

IPv4ブリッジ機能

上位に設置されているブロードバンドルータとLAN側端末機器との間のIPv4通信を透過させるために、WAN側Ethernetインタフェース re0 とLAN側 Ethernetインタフェース fxp0 をブリッジ接続し、IPフィルター ipf でIPv4パケットのみ透過させる設定をする。

ブリッジでipf設定を行うために、まず BRIDGE_IPF オプションを有効にしたnetbsdカーネルを用意しよう。

# cd /usr/src/sys/arch/i386/conf
# cat <コンフィグファイル>
(snip)
options         BRIDGE_IPF              # bridge uses IP/IPv6 pfil hooks too
(snip)
# config <コンフィグファイル>
# cd ../compile/<コンフィグファイル>
# make; make install

次にブリッジ接続とipf設定を行う。

# cat /etc/ifconfig.bridge0
create
! brconfig $int add re0 add fxp0
! brconfig $int ipf
up
# cat /etc/ipf.conf
pass in on re0
block in on pppoe0
pass in on fxp0
# cat /etc/ipf6.conf
block in on re0
pass in on pppoe0
pass in on fxp0
# cat /etc/rc.conf
(snip)
net_interfaces="re0 fxp0 pppoe0 bridge0"
ipfilter=YES            ipfilter_flags=""       # uses /etc/ipf.conf
(snip)

これで再起動すれば、IPv4/IPv6デュアルスタック環境ができたことになる。

LAN側ネットワークの端末機器には、IPv4のDHCPでIPv4アドレスを取得させるようにする。これによりLAN側ネットワーク上で利用可能なDNSサーバーについてもDHCP経由で通知され、端末から参照できる状態になるだろう。通常であればブロードバンドルーターのLAN側IPv4アドレスがDNSサーバーのアドレスになると思う。

ただしここでちょっと注意しておいてほしいのは、IPv4用のブロードバンドルーターから通知されるDNSサーバーを利用してアドレス解決をする場合、利用しているIPv4プロバイダーによってはDNS解決にAAAAフィルターが適用される可能性がある点だ。[3] この場合本来はIPv6経由で通信が可能であるはずのインターネット上のノードに対し、IPv4経由でしか通信が行われないことがある。

明らかにIPv6アドレスを持っているはずのインターネットノードに対してLAN側端末から通信を行ってみて、常にIPv4でしか通信が行われないようであれば AAAAフィルターを疑ってみよう。もしAAAAフィルターが適用されているようであれば、別のDNSサーバーを手動で設定する手順などが必要になるかも知れない。

動作確認

まずはアダプター自身からのIPv6通信を確認しておこう。

# ping6 www.re.soum.co.jp (DNSが参照できる場合)
PING6(56=40+8+8 bytes) 2001:240:2002:6a01:216:76ff:fe01:9137 --> 2001:200:1d2::1
16 bytes from 2001:200:1d2::1, icmp_seq=0 hlim=56 time=5.023 ms
16 bytes from 2001:200:1d2::1, icmp_seq=1 hlim=56 time=11.471 ms
16 bytes from 2001:200:1d2::1, icmp_seq=2 hlim=56 time=4.745 ms
16 bytes from 2001:200:1d2::1, icmp_seq=3 hlim=56 time=4.823 ms
^C
--- widegw.soum.co.jp ping6 statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 4.745/6.516/11.471/3.306 ms

# ping6 2001:200:1d2::1 (DNSが参照できない場合)
PING6(56=40+8+8 bytes) 2001:240:2002:6a01:216:76ff:fe01:9137 --> 2001:200:1d2::1
16 bytes from 2001:200:1d2::1, icmp_seq=0 hlim=56 time=4.595 ms
16 bytes from 2001:200:1d2::1, icmp_seq=1 hlim=56 time=4.980 ms
16 bytes from 2001:200:1d2::1, icmp_seq=2 hlim=56 time=4.845 ms
16 bytes from 2001:200:1d2::1, icmp_seq=3 hlim=56 time=5.206 ms
^C
--- 2001:200:1d2::1 ping6 statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 4.595/4.906/5.206/0.256 ms

次にLAN側端末からも確認する。以下は、Windows 7 PCのcmdコンソール上で ping を実行した例である。

C:\Users\ko>ping 2001:200:1d2::1

2001:200:1d2::1 に ping を送信しています 32 バイトのデータ:
2001:200:1d2::1 からの応答: 時間 =5ms
2001:200:1d2::1 からの応答: 時間 =5ms
2001:200:1d2::1 からの応答: 時間 =5ms
2001:200:1d2::1 からの応答: 時間 =5ms

2001:200:1d2::1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 5ms、最大 = 5ms、平均 = 5ms

WebブラウザによるIPv6疎通のテストには[KAMEプロジェクトのWebサイト]が良く利用されるが、例えば[創夢のWebサイト]を参照したときにトップページの左下に表示されるIPv6 forumのバナーでもIPv6で通信しているかどうかが分かる。

../../_images/fig4.png

今後の課題

ここまでで、一応IPv6インターネットは使えるようになった。だが最初に書いたように、IPv6 PPPoEアダプターには今回実装した機能以外にまだ足りない機能がある。

  1. マルチプレフィックス対応機能
  2. DNSプロクシー機能
  3. マルチキャスト通信機能

この中でも特にマルチプレフィックス対応機能は重要で、かつ実現がなかなか難しい。またDNSプロクシー機能はマルチプレフィックス対応の機能でもあるが、同時にAAAAフィルターへの対策でもあり、重要な機能である。この二つに比べるとマルチキャスト通信機能は重要性は低いが、利用するアプリケーションによっては欲しい機能になるだろう。

これらの実装はまた別の機会にでも。

[1]ルーターの下(LAN側)から上(WAN側)へのPPPoEセッションを中継して透過させる機能。ルーターベンダーにより「PPPoEブリッジ機能」や「ダイレクトPPPoE機能」などとも呼ばれる。
[2]一般的に、フレッツ光ネクストのIPv6 PPPoEでプロバイダーから割り当てられるグローバルIPv6プレフィックスは、/48または/56になることが多い。
[3]IPv6 PPPoE接続サービスと同じプロバイダーでIPv4 PPPoE接続サービスを利用している場合には、通常プロバイダー側でのAAAAフィルターは適用されないだろう。しかしブロードバンドルーター自体に搭載されているDNSプロクシー機能がAAAAフィルターを適用する場合もあるので注意すること。
記事執筆者: ko
記事公開日:2012年12月05日