OpenBSDでIPv6 IPoEを設定したときのメモ

OpenBSDでIPv6 PPPoEを設定 していたがIPoE接続が利用できるようになったのでPPPoEからIPoEに変更したときのメモ.半年くらいIPoEで使用しているが特に問題は発生していない.

ISPはOCNを利用している.2017年夏にIPoE形式のIPv6接続を提供することを発表していた.

確認したところ自宅の環境でも利用できたのでPPPoEからIPoEに変更した.ちなみに割り当てられるIPアドレスは 2409:10::/28 からだった.Internet Multifeed が管理するアドレスのようだ.

今回はIPv6はIPoE接続だが,IPv4は従来のPPPoE接続を利用する.IPoEは無料で利用できるがIPv4 over IPv6を利用するには別料金が必要なようだ(どうせならこちらも無料で提供してくれれば良いのに).

(IPv6のアドレスがMF管理だったのでMFのDS-Liteが使用できるかなと思ったが,そもそも gw.transix.jp にpingが飛ばなかった.そりゃそうか.)

IPv6 IPoE 接続の流れ

IPoEな場合,IPアドレスはシンプルに router advertisement (RA) で取得する(PPPoEの場合はDHCPv6-PDだった).ルータはNGN網から流れてくるRAを受信して,その情報に従いIPv6アドレスを設定することができる.ここまでは単純である.

次のコマンドでインターフェイス em0 に到着するRAに従いIPv6アドレスを設定できる.

doas ifconfig em0 inet6 autoconf

受信したRAの情報などはコマンド slaacctl(8) で確認できる.

LAN 内への IPv6 の提供方法

LAN内の端末がIPv6アドレスで外部と通信できるようにするには少なくとも3つの方法がある.

  1. NGN網からのRAをLAN内にも配布する.
    • ホームルータがIPv6の RA, RS, ND, NS をL2 switchのように転送する必要がある.
    • 少なくとも一部のICMPv6のパケットから見ると外部インターフェイスと内部インターフェイスが同じブロードキャストドメインに見える.
  2. ホームルータでRAをプロキシする.NGN網と同じアドレスのRAをホームルータで再配布する.
    • NDPをプロキシする必要がある.上流のルータはLAN内の端末と直接(L2的に)通信できないため.
    • 上流ルータはNDPによりIPv6とMACを紐付ける必要がある.
  3. ホームルータで独自アドレスを配布し,外部と通信する際はNAT66を利用してグローバルアドレスに変換する.
    • NATしたくない

方法1はIPv6とIPv4のブロードキャストドメインが異なる.WAN側インターフェイスがIPv6では同一ブロードキャストドメインとなる.LANからのRA, RS, ND, NS がNGN側のルータに届く必要があるため.一方でIPv4はPPPoE接続なのでWAN側インターフェイスにLANのARPなどが流れるのはよろしくない.IPv4に関連するL2のフレームだけフィルタする必要があるが簡単に実現する方法が不明だったため却下.

方法2はNS, NAをプロキシするデーモンがOpenBSDにはなさそうなので却下.( pfdup-to を使えばNS, NAをプロキシできると思い試してみたが送信元MACアドレスがduplicate時に書き変わってしまうようで,L2的に転送するような動作はしていないようだった.)

方法3はIPv6なのにNATするのが非常に気に喰わないが他に方法がないため今回はこれを選択.設定自体は簡単.というよりもIPv4とほぼ同じなので簡単.

IPv6用のNATも存在する.アドレスを1:1で変換するためステートテーブルを保持する必要がないようだ.

LAN 内への IPv6 配布設定

次のようにしてLAN側のインターフェイスにIPv6アドレスを設定できる.

doas ifconfig vether0 inet6 XXXX:YYYY:ZZZZ::1 prefixlen 64

このとき指定するアドレスはunique local address (ULA)であることが望ましいのだが,後述の理由で適当な(使われてなさそうな)グローバルIPv6を設定している.これはWindows10では使用するアドレスの優先順位が標準で次のように設定されているからである.

C:\WINDOWS\system32>netsh interface ipv6 show prefixpolicies
アクティブ状態を照会しています...

優先順位   ラベル  プレフィックス
----------  -----  --------------------------------
        50      0  ::1/128
        40      1  ::/0
        35      4  ::ffff:0:0/96
        30      2  2002::/16
         5      5  2001::/32
         3     13  fc00::/7
         1     11  fec0::/10
         1     12  3ffe::/16
         1      3  ::/96

上の表で ::/0 がグローバルなIPv6に対応する. ::ffff:0:0/96 がIPv4, fec0::/10 がULAに対応する.優先順位はIPv4がULAより上位に設定されていることに注意する.ULAをLAN内のWinodws10端末に配布すると,通信先がIPv4とIPv6の両方のアドレスをもっていた場合,IPv4が通信に使用されてしまいせっかくIPv6を配布しているので全然使用してくれないということになる.

詳細な選択ルールは次のRFCに記載されている.

実際のアドレス配布は RA を使う.OpenBSD 6.3 以前は rtadvd(8) が利用されていたが 6.4 からは rad(8) に置き換わった.次のような設定ファイル /etc/rad.conf を作成して rcctl(8) によりサービスを有効化する.

interface vether0 {
        prefix XXXX:YYYY:ZZZZ::/64
        dns {
                nameserver XXXX:YYYY:ZZZZ::1
                search local.your.domain
        }
}

ちなみに以前はWindowsにDNS情報を配布するためにDHCPv6を設定していたがWindows10 Creators updateでRDNSSに対応したため不要となった.

firewall と NAT の設定

firewall と NAT を実現するために /etc/pf.conf に次のような設定を追加する.

# NAT66
match out log on em0 inet6 from (vether0:network) to any nat-to $ext_ip6

# Permit outgoing IPv6
pass out quick inet6

# Permit IPv6 within LAN
pass in on $int_if inet6

# ICMPv6 transit traffic (RFC 4890, Sec. 4.3)
pass in on em0 inet6 proto ipv6-icmp icmp6-type { unreach, toobig, timex, paramprob, echoreq, echorep }

# ICMPv6 local configuration traffic (RFC 4890, Sec. 4.4)
pass in on em0 inet6 proto ipv6-icmp icmp6-type \
        { routersol, routeradv \
        , neighbrsol, neighbradv, redir \
        , 141, 142 \ # Inverser neighbor discovery sol. and adv.
        , listqry, listenrep, listendone, listenrepv2 \
        , 148, 149 \ # Certificate path sol. and adv.
        , 151, 152, 153 \# Multicast router adv., sol., and termination
        }

# Permit SSH
pass in on em0 inet6 proto tcp from any to (self) port $ssh_port

最初のNATのルール中の nat-to の対象を (em0:0) とするとリンクローカルアドレスに解決されて外部と通信できなくなるのでWANインターフェイス em0 のグローバルアドレスを $ext_ip6 と定義してそれを利用している.

また,ICMPv6 のフィルタリングは下記のRFCを参考に設定した.

参考