Edgerouter X でひかり電話なし IPv6 をやる
表題のとおりですが、意外とがんばりが必要だったのと、同じような設定で悩む人が多いらしいので忘れないようにメモします
2年近く前の下書きを引っ張り出して焼き直してるので古かったり設定に齟齬があるかもしれません。ひらに
TL;DR
NGN から RA で降ってきた /64 のプレフィックスを Edgerouter で再び LAN 側に広報しつつどうにかして NDP プロキシをやるとできる。
背景
フレッツ光ネクストを使用して IPoE 方式による IPv6 接続を行う場合、ひかり電話契約の有無によってアドレス取得の方法が異なるというのは割と知られた事実だと思います。
具体的には、ひかり電話契約がある場合は DHCPv6-PD を用いてフレッツ網(NGN)から /56 の Prefix Delegation を受けることができ、NGN 側ルーターは PD を受けたルーターにパケットを流してくれるようになります。1
一方、ひかり電話契約がない場合、PD は受けられず、NGN 側ルーターから /64 の Router Advertisement が流れてきます。2 このとき、NTT が想定している使い方としては IPv6 のみ LAN 内のネットワークと L2 ブリッジ(a.k.a. IPv6 パススルー)してやることで LAN 内機器と NGN ルーターで直接通信するというものだと思います。
しかしながら、ウチのガバガバセキュリティの機器をインターネットに直接晒すのはやや怖い…… ので、なんとか L3 ルーティングでことを済ませたい、というのが本記事の背景となります。
構成
ONU: GE-PON タイプD
ルーター: Edgerouter X (ER-X)
以降の設定例では次のインターフェイスを使用することとします。(適宜読み替えてください)
WAN側IF: eth0
LAN側IF: switch0 (eth2-4)
設定
1. WAN側インターフェイスに IPv6 アドレスを当てる
これは単純で、RA を受けて SLAAC でアドレスを確定させるだけです。
set interfaces ethernet eth0 ipv6 address autoconf
set interfaces ethernet eth0 ipv6 dup-addr-detect-transmits 1
この段階で WAN 側インターフェイスにはグローバルアドレスがつき、ルーターから外へは IPv6 通信できるようになります。
4: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether fc:ec:da:XX:XX:1e brd ff:ff:ff:ff:ff:ff inet6 2409:10:XXXX:XXXX:feec:daff:feXX:XX1e/64 scope global dynamic valid_lft 2591862sec preferred_lft 604662sec inet6 fe80::feec:daff:fexx:xx1e/64 scope link valid_lft forever preferred_lft forever
2. IPv4 接続性を確保する
本筋から外れるので設定だけ列挙して詳細な解説は割愛します。
2.1 DS-Lite
set interfaces ipv6-tunnel v6tun0 encapsulation ipip6 set interfaces ipv6-tunnel v6tun0 firewall in name DSLITE_IN set interfaces ipv6-tunnel v6tun0 firewall local name DSLITE_LOCAL set interfaces ipv6-tunnel v6tun0 local-ip '2409:10:XXXX:XXXX:feec:daff:feXX:XX1e' set interfaces ipv6-tunnel v6tun0 mtu 1460 set interfaces ipv6-tunnel v6tun0 multicast disable set interfaces ipv6-tunnel v6tun0 remote-ip '2404:8e00::feed:100' set interfaces ipv6-tunnel v6tun0 ttl 64
出口は transix です local-ip に prefix を直打ちしない方法はまだ知らない
2.2 PPPoE
set interfaces ethernet eth0 description 'Internet(v4/v6)' set interfaces ethernet eth0 duplex auto set interfaces ethernet eth0 firewall in ipv6-name WAN6_IN set interfaces ethernet eth0 firewall local ipv6-name WAN6_LOCAL set interfaces ethernet eth0 ipv6 address autoconf set interfaces ethernet eth0 ipv6 dup-addr-detect-transmits 1 set interfaces ethernet eth0 pppoe 0 default-route none set interfaces ethernet eth0 pppoe 0 firewall in name WAN_IN set interfaces ethernet eth0 pppoe 0 firewall local name WAN_LOCAL set interfaces ethernet eth0 pppoe 0 mtu 1454 set interfaces ethernet eth0 pppoe 0 name-server auto set interfaces ethernet eth0 pppoe 0 password XXXX set interfaces ethernet eth0 pppoe 0 user-id XXX@sbb.ne.jp set interfaces ethernet eth0 speed auto set service nat rule 5010 description 'masquerade for WAN' set service nat rule 5010 outbound-interface pppoe0 set service nat rule 5010 type masquerade
2.3 PBR
PBR で基本は全て DS-Lite に向けつつ、特定ホストやシステムのデフォルトルートは PPPoE に向けることにする。こうすると必要に応じてポート開放できたり、UPnP を喋らせたりできて便利
set firewall group network-group PRIVATE_NETS network 192.168.0.0/16 set firewall group network-group PRIVATE_NETS network 172.16.0.0/12 set firewall group network-group PRIVATE_NETS network 10.0.0.0/8 set firewall modify PBR-121 rule 10 action modify set firewall modify PBR-121 rule 10 description 'これがないと VPN などが DS-Lite に吸われる' set firewall modify PBR-121 rule 10 destination group network-group PRIVATE_NETS set firewall modify PBR-121 rule 10 modify table main set firewall modify PBR-121 rule 20 action modify set firewall modify PBR-121 rule 20 destination group address-group ADDRv4_eth0 set firewall modify PBR-121 rule 20 modify table main set firewall modify PBR-121 rule 91 action modify set firewall modify PBR-121 rule 91 description 'ゲーム機とかはこうしてる' set firewall modify PBR-121 rule 91 modify table main set firewall modify PBR-121 rule 91 source address 192.168.XX.XX set firewall modify PBR-121 rule 92 action modify set firewall modify PBR-121 rule 100 action modify set firewall modify PBR-121 rule 100 description 'Default to DS-Lite(table 121)' set firewall modify PBR-121 rule 100 modify table 121 set interfaces switch switch0 firewall in modify PBR-121 set protocols static table 121 description 'default to v6tun0' set protocols static table 121 interface-route 0.0.0.0/0 next-hop-interface v6tun0 distance 100 # デフォルトルート設定など set port-forward wan-interface pppoe0 set protocols static interface-route 0.0.0.0/0 next-hop-interface pppoe0 distance 11 set protocols static interface-route 0.0.0.0/0 next-hop-interface v6tun0 distance 12 set service upnp listen-on switch0 outbound-interface pppoe0
3. LAN 内に IPv6 プレフィックスを広報する
1 で取得した /64 を RA で LAN 内に配ります。
set interfaces switch switch0 ipv6 address autoconf set interfaces switch switch0 ipv6 dup-addr-detect-transmits 1 set interfaces switch switch0 ipv6 router-advert cur-hop-limit 64 set interfaces switch switch0 ipv6 router-advert link-mtu 0 set interfaces switch switch0 ipv6 router-advert managed-flag false set interfaces switch switch0 ipv6 router-advert max-interval 600 set interfaces switch switch0 ipv6 router-advert other-config-flag false set interfaces switch switch0 ipv6 router-advert prefix '2409:10:XXXX:XXXX::/64' autonomous-flag true set interfaces switch switch0 ipv6 router-advert prefix '2409:10:XXXX:XXXX::/64' on-link-flag true set interfaces switch switch0 ipv6 router-advert prefix '2409:10:XXXX:XXXX::/64' valid-lifetime 2592000 set interfaces switch switch0 ipv6 router-advert reachable-time 0 set interfaces switch switch0 ipv6 router-advert retrans-timer 0 set interfaces switch switch0 ipv6 router-advert send-advert true
できればここも autoconf
だけで済ませて直打ちを避けたかったんですが、再起動するとアドレスが当たらなくなるので諦めています。4
フレッツの IPv6 プレフィックスは「半固定」とのことなので滅多なことでは変わらないと思いますが、過去1度再起動後に変わったことがあります。あと引っ越しでは(契約は引き継いだが)当然変わりました。
うまくいけば LAN 側インターフェイスにも IPv6 アドレスが付きます。
2: switch0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000 link/ether fc:ec:da:XX:XX:23 brd ff:ff:ff:ff:ff:ff inet6 2409:10:XXXX:XXXX:feec:daff:feXX:XX23/64 scope global dynamic valid_lft 2591805sec preferred_lft 604605sec inet6 fe80::feec:daff:feXX:XX23/64 scope link valid_lft forever preferred_lft forever
LAN 内のクライアントも SLAAC で global IPv6 アドレスが取得できます。
$ ip a 2: wlp60s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether a8:7d:12:XX:XX:XX brd ff:ff:ff:ff:ff:ff inet 192.168.XX.XX/24 brd 192.168.XX.255 scope global dynamic noprefixroute wlp60s0 valid_lft 67359sec preferred_lft 67359sec inet6 2409:10:XXXX:XXXX:f6e3:2d57:97ba:a680/64 scope global dynamic noprefixroute valid_lft 2591891sec preferred_lft 604691sec inet6 fe80::d234:29c:34:5381/64 scope link noprefixroute valid_lft forever preferred_lft forever
4. NDP Proxy する
さてここまでで見かけ上 LAN 内には global IPv6 が当たりましたが、このままでは通信ができません。これは、上流の NGN 側ルーターが LAN 内クライアントのアドレスを知らないためです。というわけで NDP Proxy で LAN 内クライアントのアドレス情報を上流ルーターに伝えてやります。
NDP Proxy の実装はこれを使わせてもらってます。
で、こいつを MIPS 向けにビルドする必要があるんですが、まあまあダルいのでビルドしたやつを置いておきます。無保証/自己責任でお願いします。 musl に static link しているので、環境を選ばず動くと思います。
https://minio.venusark.p1kachu.net/public/ndppd.zip
たぶん 2.x ファームなら Debian リポジトリからもインストールできるとは思いますが、これをやったのは 1.x ファームの時代で、 wheezy には ndppd なかった。
/config/user-data/ndppd
に実行ファイルと設定を配置します。設定 ndppd.conf
は以下です。
proxy eth0 { autowire yes rule ::/0 { iface switch0 } } proxy switch0 { autowire yes router yes rule ::/0 { iface eth0 } }
起動スクリプトを /etc/init.d/ndppd
に配置します。こちらのコードは
https://community.ui.com/questions/Set-up-IPv6-without-Prefix-Delegation/ea0998be-2d13-4747-ac1e-9a26cb1a2976 を参考にさせていただきました。
#!/bin/bash ACTION=$1 NDPPD_DIR="/config/user-data/ndppd" NDPPD_BIN="$NDPPD_DIR/ndppd" NDPPD_CONF="$NDPPD_DIR/ndppd.conf" NDPPD_PID="/run/ndppd.pid" do_stop(){ if [ -f $NDPPD_PID ]; then kill `cat $NDPPD_PID` > /dev/null 2>&1 rm -f $NDPPD_PID fi echo 0 > /proc/sys/net/ipv6/conf/all/proxy_ndp echo 0 > /proc/sys/net/ipv6/conf/default/proxy_ndp /sbin/ifconfig switch0 -promisc /sbin/ifconfig eth4 -promisc /sbin/ifconfig eth3 -promisc /sbin/ifconfig eth2 -promisc /sbin/ifconfig eth1 -promisc /sbin/ifconfig eth0 -promisc } do_start(){ if [ -f $NDPPD_CONF ]; then echo "Starting NDP Proxy Daemon ..." /sbin/ifconfig eth0 promisc /sbin/ifconfig eth1 promisc /sbin/ifconfig eth2 promisc /sbin/ifconfig eth3 promisc /sbin/ifconfig eth4 promisc /sbin/ifconfig switch0 promisc echo 1 > /proc/sys/net/ipv6/conf/default/proxy_ndp echo 1 > /proc/sys/net/ipv6/conf/all/proxy_ndp $NDPPD_BIN -d -c $NDPPD_CONF -p $NDPPD_PID else echo "ERROR: $NDPPD_CONF not found" exit 1 fi } case "$ACTION" in start) do_start ;; restart) do_stop do_start ;; stop) do_stop ;; *) echo "$1 start|stop|restart" ;; esac exit 0
/etc/rc.local
に追記すると自動起動できます。
service ndppd start
なお、 /config/user-data
外に配置したファイルについてはファームウェアアップデート時に失われるので、 /etc
以下をいじる際にはアップデート後に再度設定を行うことをお忘れなく。
できた
全てが上手く行っていれば LAN 内から IPv6 通信ができる状態になっていると思います。お疲れ様でした。あと v6 側のファイアウォール設定とかはよしなにやってください。
この記事を下書きから救い出した理由ですが、まだファームが1.xで止まってるのでいい加減2.xに上げようと思います。VPN周りのデグレが問題で上げれてなかった。
-
ひかり電話がある場合、大体は NTT の HGW(ホームゲートウェイ)を利用することになると思うのですが、その場合 HGW が /56 を受け、その下流にルーターを置くことでさらに /60 が移譲されます。↩
-
工事費が安くなるという口車に乗せられてSB光にしたが情弱プレイだったと思う / 内容はフレッツの再販なので大した違いはないがBB光ユニットとかいうやつの存在がウザかった(返却しないと他のv6オプションが使えない)↩
-
なんか
net.ipv6.conf.switch0.accept_ra = 2
するとか色々頑張ってた気がするんだけど今見たらその設定どこにも見当たらないしすっかり忘れてしまった↩