ルーターで遊びたい欲が出てきており、適当なマシンを調達して遊ぶことになりました。 自分の家のルーター(IO DATA WN-AX2033GR)が微妙にIPoE環境だとフルスピードが出ないこと(だいたい200-300Mbpsが限界)や細かい設定ができない不満などがあり、いろいろ代替手段を物色していたんですがちょうどいいマシンを借りれたのでそれでやりました
よくある文献だとv6の設定まで詳しくは書いてなかったりするんですがv6のほうがカプセル化のオーバーヘッドがない分スループット高いはずだし、MAP-Eでセッション(ポート)枯渇することもないので使わない手はないはずなんですよね。
環境
- 光コラボ回線。NTTフレッツ光ネクスト相当
- DTI 光。 安いがIPoEが開通するとPPPoEが消滅する
- IPv4 over IPv6はJPNEのMAP-E
- おうちに光コンセントが生えているタイプ
- ひかり電話なし=HGWなし=RAの/64のほう。DHCPv6の/56ではない
ルーター選定
長い道のりがあった。要件としては
- 回線のスペックを生かしたいので1Gbpsフルで出ること
- いろいろ細かいところをいじって遊べること
- 常時運用して邪魔にならないサイズ
コストだけだと市販ルーターにOpenWrtを焼くのが最安なのだが、それだと1Gbps出ないらしい。ハードウェアオフローディングが前提だがOpenWrtだとその辺うまく扱えないとかいろいろな理由により最適化が進んでいないらしい。基本市販ルーターに乗っているチップはスループット要件的には全滅である。そんなこんなでこの辺が候補になった。
- Raspberry Pi 4 Model B 10000円くらい
- NanoPi R4S 8000円くらい
- Celeron J1900を積んだSBC 15000円くらい
価格はすべてケースやらアダプタやらいろいろ込みの概算。NanoPiが最安だがサポート体制もドキュメントもあんまりなさそうなのが難。RasPi 4は結構良いんじゃないかとおもう。Celeron JはいわゆるAtomベースのクアッドコアでx64が動作し互換性やらドライバやらなんやらで悩むことがほとんどないであろうことが約束されているのがうれしい。
とここまで調べたところで、友人がLattePandaを買っていたことを思い出した。Atom Cherry Trailのクアッドコアで性能十分だろうと借りたらLattePanda AlphaでCore m3でオーバースペックすぎるといううれしい誤算がありスタート。
UbuntuにするかOpenWrtにするか悩んだがとりあえずUbuntu Server 20.04でスタート。どっちがいいかは両方は試していないので謎。ルーター用じゃないディストロ使うとよくもわるくもルーターっぽい設定方法はできない
LANポートが1つしかなかったのでUSB 3.0-GbE変換をかった。これはなんでもいい。激安は主にRealtekかASIXらしいがx64 Ubuntuではどっちも無設定で動くし当然1Gbpsでる(OpenWRTの場合はどちらか見極めて別途ドライバインストールが必要らしい)
えらばなかったルーター
- 最近の市販WiFiブロードバンドルーター
最近のはv6やらv4 over v6やらもうまいことハードウェアオフローディングしたりしていてまあまあ高速らしい。完全にオーバーヘッドでなくなっているかは不明ですが手持ちのより速いことは間違いない。機能と安定性はバラバラだったり、JPNE 固定IPは対応していなかったり対応していてもなぜかポート開放できなかったりととにかく機能不足がすごい
- EdgeRouter X
手持ちで持っているがMAP-E非対応なのと単なるv4 over v6のカプセル化でもハードウェアオフローディングに対応できないのでCPUの能力不足で200-300Mbpsくらいしかでないということで除外
- YAMAHA NVR510
40000円也。富豪~。とはいえ自分がこうやって苦労したようなことが公式ドキュメントみながらササっとできるので金で時間と性能を買えるのはすごい
構成
IPv4, IPv6のデュアルスタックにしたい。したいんだがこれはつまり両方別に設定しつつたまに共通になったりあれこれする魔境である。めんどうったらありゃしない
IPv4
ルーターにDHCPv4サーバーを立ててやります
- LANのrangeは192.168.0.0/24
- ルーター=ゲートウェイのIPは他の固定IPがある都合で192.168.0.4
- nameserverは1.1.1.1とかを使います。自前管理しない
- ルーターでNATとv6カプセル化とMAPをやる
IPv6
ルーターはRAを中継するだけ。いわゆるL3スイッチに近い(けどちょっと追加で仕事する)
- radvdでRAを中継
- radvdで追加で設定できるのでnameserverも書いておく(1.1.1.1サービスのv6アドレスである2606:4700:4700::1111とか)
- RAのためのICMPv6をいい感じにするのにndppdとかいうやつもいれる
- DHCPv6は一切使わない
DEV (デバイス名)
ネットワーク周りではdevはdeviceの略称です。最初何?ってなった
- enp2s0: LAN側NIC
- enx18ece795bb0b: WAN側NIC
- ip6tnl0: 使うとうまく動作しない呪われたdev。勝手にできるしなんなのかわからない。ネット情報だとこの名前使ってるやつあるが使うとはまるのでやめましょう
- ipip6t0: ip4ip6トンネル。↑ではまったので名前変えたやつ
設定
設定はsystemd-networkdでやり、カバーできないところをipとiptablesでやりました。これがベストなのかは謎
apt purge network-manager netplan.io ifupdown
どっかで見かけてビビったんですがこれは初手としてやったほうがいいです。Ubuntuネットワーク管理するやつが多すぎてこいつらが勝手に動作するとわけわからなくなるのでpurgeは基本。systemd-networkd一本でいきましょう
apt install radvd npdpp isc-dhcp-server
$ cat /etc/systemd/network/10-enp2s0.network [Match] Name=enp2s0 [Network] LinkLocalAddressing=ipv6 Address=192.168.0.4/24 DHCP=no DNS=1.1.1.1 DNS=8.8.8.8 $ cat /etc/systemd/network/10-enx18ece795bb0b.network [Match] Name=enx18ece795bb0b [Link] RequiredForOnline=yes [Network] DNS=2606:4700:4700::1111 IPv6AcceptRA=yes DHCP=no Address=240b:10:xxxxxxxxxxxxxxx/64 Tunnel=ipip6t0 $ cat /etc/systemd/network/12-ipip6t0.network [Match] Name=ipip6t0 [Network] IPForward=ipv4 [Route] Destination=0.0.0.0/0 $ cat /etc/systemd/network/ipip6t0.netdev [NetDev] Name=ipip6t0 Kind=ip6tnl [Tunnel] Mode=ipip6 Local=240b:10:xxxxxxxxxxxxxxxxx Remote=2404:9200:225:100::64 DiscoverPathMTU=yes EncapsulationLimit=none $ cat /etc/radvd.conf interface enp2s0 { AdvSendAdvert on; prefix 240b:10:xxxxxxxxxxx::/64 { AdvOnLink on; AdvAutonomous on; }; RDNSS 2606:4700:4700::1111 2001:4860:4860::8888 { }; }; $ cat /etc/ndppd.conf proxy enx18ece795bb0b { router no rule 240b:10:xxxxxxxxxxx::/64 { iface enp2s0 } } $ cat /etc/dhcp/dhcpd.conf # default default-lease-time 600; max-lease-time 7200; ddns-update-style none; authoritative; subnet 192.168.0.0 netmask 255.255.255.0 { option routers 192.168.0.4; option domain-name-servers 1.1.1.1, 8.8.8.8; range 192.168.0.100 192.168.0.199; } $ cat /etc/sysctl.conf net.ipv6.conf.all.accept_ra = 1 net.ipv6.conf.enx18ece795bb0b.accept_ra = 2 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1 net.netfilter.nf_conntrack_tcp_timeout_established = 3600
設定は試行錯誤しながらやったのでなんか結構不要な設定が混じってそうな感がある。参考程度にお考えください。あとMAP-Eのアドレス計算はググってください。
以下はシェルスクリプト。systemdとかで起動時に自動設定されるようにしたほうがいいやつですね。まだやってない
#!/bin/sh set -ux # https://qiita.com/s_ponta/items/5652a7be49198288ae61 RA_RANGE='240b:10:xxxx:xxxx::/64' BR='2404:9200:225:100::64' CE='240b:10:xxxxxxxxxxxxxxxxxxx' IP4='xx.xx.xx.xx' PSID='xxx' LANDEV='enp2s0' WANDEV='enx18ece795bb0b' TUNDEV='ipip6t0' # udevadm info --export-db echo 'on' > /sys/bus/usb/devices/1-7/power/control # no way to config this from systemd-networkd https://github.com/systemd/systemd/issues/928 ip -6 r replace $RA_RANGE dev enp2s0 tab 1 ip -6 rule add from all tab 1 priority 1000 iptables -t filter -F iptables -t nat -F iptables -t mangle -F rule=1 while [ $rule -le 15 ] ; do mark=`expr $rule + 16` pn=`expr $rule - 1` portl=`expr $rule \* 4096 + $PSID \* 16` portr=`expr $portl + 15` iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet $pn -j MARK --set-mark $mark iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet $pn -j MARK --set-mark $mark iptables -t nat -A POSTROUTING -p icmp -o $TUNDEV -m mark --mark $mark -j SNAT --to $IP4:$portl-$portr iptables -t nat -A POSTROUTING -p tcp -o $TUNDEV -m mark --mark $mark -j SNAT --to $IP4:$portl-$portr iptables -t nat -A POSTROUTING -p udp -o $TUNDEV -m mark --mark $mark -j SNAT --to $IP4:$portl-$portr rule=`expr $rule + 1` done iptables -t mangle -o $TUNDEV --insert FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
いろんなサイトのコピペになってる
ip -6 r replace $RA_RANGE dev enp2s0 tab 1 ip -6 rule add from all tab 1 priority 1000
ここはちょっと大事でして、systemd-networkdだと現状こういうサブネット全体のmetric (ルーティング優先度、低いほうが優先される)を指定する方法がないのでRAなどでつけられたデフォルト優先度に負けないよう上書きしたい場合は手動でやる必要があります。この例だとこのsubnetは標準だとWAN側NICにアサインされてしまうのをLAN側NICに戻しています。このサブネットWAN側LAN側両方で使われているのがややこしいというかv6っぽいというか。しかし自分とこでレンジ切り出して再配布できるDHCPv6のほうがらくってのはよくわかりますね。NTT~。ということで最初はmetric変更したrouteを追加していたんですが上位概念としてtable/ruleというのがあるのでそっちで設定したほうが確実そうということでそれをやってます。priorityはtableのpriorityですね。標準のmainは32000くらい。
設定後はこうなる
$ ip -6 rule 0: from all lookup local 1000: from all lookup 1 32766: from all lookup main $ ip -6 route list tab 1 240b:10:8ac1:e800::/64 dev enp2s0 metric 1024 pref medium $ ip -6 route list tab main ::1 dev lo proto kernel metric 256 pref medium 240b:10:xxxxxxxxx::/64 dev enx18ece795bb0b proto kernel metric 256 pref medium 240b:10:xxxxxxxxx::/64 dev enx18ece795bb0b proto ra metric 1024 expires 2591640sec pref medium 240b:10:xxxxxxxxx::/64 dev enp2s0 proto ra metric 1024 expires 86177sec pref medium fe80::/64 dev ipip6t0 proto kernel metric 256 pref medium fe80::/64 dev enx18ece795bb0b proto kernel metric 256 pref medium fe80::/64 dev enp2s0 proto kernel metric 256 pref medium default via fe80::xxxx:xxxx:xxxx:xxxx dev enx18ece795bb0b proto ra metric 1024 expires 1440sec pref medium
余談ですがipもiptablesもv6とv4で別々に表示されるしv6はオプションつけないと表示されないから注意だ!
速度
適当にはかったとき、v4で600Mbpsくらいは出ている。いままでは200-300Mbpsが限度だったのでルーターの性能によるオーバーヘッドはほぼ消えたといっていいんじゃないだろうか
課題
- ↑で手動で設定したmetricがなにかのはずみに消えてしまうことがあり、謎。なくなるとv6は疎通しなくなるがv4は通じるので気づきにくかったり
- セキュリティー。ザルというか無設定なんですがどうなんだろう。v6アドレスの設定方法がどうなっているか調査したりとか、パケット解析してなんか弾くとかやったほうがいいのかね。でもv6では全部グローバルアドレスもっててincoming受け付けられるというのはまっとうなことでは
- UPnPとか。MAP-Eでどこまで対応する価値あるかはおいといてやりたいときに。可能なportであればできたほうがいい
次
- enひかりっていう光コラボのサービスがあるんですが、MAP-Eと固定IPオプションをつけると月3300+180+700=4180円でフルのv4アドレスを持つことができます。これで80やら443やらでサーバー公開できるね!!ということでそれをやりたいと思います。MAP-E + 固定IPオプションは実際にはJPNEの固定IPサービスになるのでごちゃごちゃやる必要があるMAP-EともおさらばできDS-Liteくらいの設定でいけますしセッションが増えた時のポート枯渇にも悩まされなくなります。よさそう!
- めちゃくちゃ高性能なやつでやってしまったのでどこまで低性能、低価格なルーターで同じスループット出せるかはチャレンジしてみたい。あと一分のチップは最近OpenWrtでハードウェアオフローディング対応したらしいので、市販ルーターのソフトウェアでやっているv4用のハードウェアオフローディングをv6で無理やり使えるようにするハックとかを自分でやるのはおもしろそう(大変そう)
参考文献
https://qiita.com/kakinaguru_zo/items/2764dd8e83e54a6605f2 https://qiita.com/s_ponta/items/5652a7be49198288ae61 https://quintrokk.subness.net/?p=2003 https://gato.intaa.net/archives/25972