FreeBSDルータでflets-v6にNAPTする


NTT東のキャンペーンで当選した光iフレームが送られてきました。箱を開けて説明書を読むとIPv6ブリッジ機能がある無線ルータを使って利用開始(月額210円 半年間無料)するとアプリがダウンロード可能とのことです。そういえば、申込みの時にルータは自分で用意しろと書いてあった気がします。
これまで、IPv6環境は得られるものが少なかったので二の足を踏んでいましたが、ちょうど、APNIC割り当て分のIPv4アドレスが枯渇したという報道もあり、これはIPv6環境構築しろという天の声と観念して、遅ればせながらIPv6環境を作る事にしました。



構成


我が家ではPCENGINEのwrapにFreeBSDを載せてルータとしています。手の平サイズのボードにNICx3とmini-PCIスロットx1のモデルです。mini-PCIスロットにはAR5212ベースの11bgのボードを載せています。
物理的な接続は

NIC0 ==> ONU
NIC1 ==> LAN
NIC2 ==> ひかり電話
WLAN0 ==> 無線LAN

としています。
パブリックな空間に晒す機器を最小にするというポリシーのもと、NIC0,NIC2間をブリッジにして、ひかり電話を内側に入れています。ひかり電話は起動時にひかり電話本体がPPPoEを張り設定情報を取得、その後は割り当てられたアドレスにてIPv4で直接通信します。
したがって、このブリッジはL2はipfw,L3はpfにてフィルタし、PPPoE,UDP/IPv4,ARPだけ通します。
以下でbridge0とあるのはこのブリッジの事です。ひかり電話をONUに直結する場合はNIC0に読み替えてください。

接続方式


さて、これにflets-v6を追加するわけですが、flets-v6では/64なアドレスが割り当てられ、flets-v6対応のルータではIPv6パケットをWAN,LAN間でブリッジして接続します。国内で販売されているBBルータのいわゆるIPv6ブリッジ機能。
選択肢は

  1. flets-v6へのパケットをルーティングする
    /80でルーティングが可能ならばもっとも素直な方法ですが、こんなこと可能かどうか判らないうえに、光iフレームでは確実に無理そうです。
    proxy arpのようにNDを誤魔化す方法で可能かもしれませんが、ざっと探したところこれを実現するプログラムは公開されていませんでした。
  2. IPv6パケットをNIC0,NIC1間でブリッジする(市販ルータと同じ方式)
    閉域網とはいえクライアントを直接パプリック空間にさらすのはポリシーに反します。
  3. flets-v6に対してNAPTする
    幸いIPv4のパケットフィルタ+NAPTに使用しているpfはIPv6に対応しているので、ルールを追加するだけで行けそうです。
  4. flsts-v6に対してproxyする
    ルータの負荷が高くなる(特にメモリ)上に柔軟性に欠ける
NAPT方式を採用します。

設定


ルータとして設定すると自動的にRAを受け付けない設定になるので、まず、非ルータとしてrtsolを実行してみるとルータアドレスfe80::211:bcff:fe0e:3c1aと2001:c90:xxxx:xxxx/64なるプリフィックスが降ってきました。

flets-v6網へのインターフェースにRAで割り当てられた2001:c90:xxxx:xxxx/64を振りますが、直結してるNIC0はNIC2とブリッジしているのでbridge0に振ります。


/etc/rc.conf:
prefix_flets6="2001:c90:xxxx:xxxx"
ifconfig_bridge0_ipv6="inet6 ${prefix_flets6}:: eui64 prefixlen 64"


flets-v6網は2001:c90::/32と2404:1a8::/32を使用しているので、これへのスタティックルートを設定します。

/etc/rc.conf:
ipv6_gateway_enable="YES"
ipv6_route_flets1="2001:c90::/32 fe80::211:bcff:fe0e:3c1a%bridge0"
ipv6_route_flets2="2404:1a8::/32 fe80::211:bcff:fe0e:3c1a%bridge0"
ipv6_static_routes="flets1 flets2"


ネームサービスに関してはIPV4のflets網はトップドメインがfletsと、閉じた名前空間を利用していたので、flets網のネームサーバにフォワードする必要がありましたが、flets-v6はインターネット側から参照できる名前空間となっていて、ネームサーバに関する特別な設定は不要です。
これで、ルータ本体からflets-v6.jpにアクセス可能になるはずです。

ルータ本体からの接続を確認したらIPv6ルータとしての設定を行います。

/etc/rc.conf:
ipv6_forwarding="YES"
rtadvd_enable="YES"
rtadvd_interfaces="NIC1 WLAN0"


最後にpfでNATPしてやります。変換アドレスがbridge0に割り当てたアドレスになりますが、bridgeのMACアドレスはインターフェース作成時に自動生成され、それに伴いflets-v6のアドレスも変化します。
固定で与えてもよいのですが、pfのアンカー機能を利用してアドレス生成後にルールを追加することにしました。


pf.conf:
nat-anchor flets-v6


pfのルール追加はstart_if.bridge0に記述したいところですが、pfの設定はnetifの後になっているので、start_if.bridge0で設定しても、そのルールはクリアされてしまいます。
pfの設定はnetifの後なのでpf起動時に渡せそうなものですが、rc.confの読み込み時にはbridgeは生成されていないので

rc.conf:
pf_flags="-D flets6_addr=$(getv6addr bridge0 ${prefix_flets6})"

とすることはできません。評価を遅延する仕組みが思いつかなく、rcNGのスクリプトを書くのも面倒なのでrc.localで設定します。

/etc/rc.local:
#!/bin/sh

if [ -z "${source_rc_confs_defined}" ]; then
if [ -r /etc/defaults/rc.conf ]; then
. /etc/defaults/rc.conf
source_rc_confs
elif [ -r /etc/rc.conf ]; then
. /etc/rc.conf
fi
fi

getv6addr()
{
local ifs prefix
ifs="$1"
prefix="$2"
ifconfig "$ifs" | \
sed -e "/inet6 *$prefix:/!d" \
-e 's/[ ]*inet6 *//' \
-e 's/ *prefixlen .*//'
}

native6_if="bridge0"
flets6_world="{2001:c90::/32 2404:1a8::/32}"
flets6_addr="$(getv6addr bridge0 ${prefix_flets6})"

pfctl -a flets-v6 -f - < $flets6_addr
EOF

フィルタールールは適当に書きます。

2011年4月23日記

The Design and Implementation of the FreeBSD Operating System
Addison-Wesley Professional
Marshall Kirk McKusick
amazon.co.jpで買う
Amazonアソシエイト by The Design and Implementation of the FreeBSD Operating System の詳しい情報を見る / ウェブリブログ商品ポータル


ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 0

この記事へのコメント

この記事へのトラックバック