YAMAHA ルータと Splatoon 2

結論から言うと、ヤマハルータの Rev.14.01.09 以降ではデフォルトだと Splatoon 2 が動かないが、 nat descriptor backward-compatibility 1 を叩くと動くようになる。

背景

RTX1210 で動いている WiFiNintendo Switch を繋いで遊ぼうとしたら、まったく動かない。マッチを始めるとエラーコード 2618-0513 で「相手のゲーム機と通信できませんでした」と表示され失敗するし、 10回に 1回ぐらいはマッチングが始まるが 8人揃わず制限時間を迎える。(制限時間がちょくちょく伸びるので対戦者を追加しようとして失敗してる様子)

調査

マッチングのときに出る問題であることと、NAPT箱が異なる別のネットワークでは正常に動くので、まあ NAPT越え(NAT traversal)まわりやろと当たりをつけた。

Switch の接続テストでは「NATタイプ B」と表示される。

比較的インターネット経由での対戦・協力プレイが行いやすい環境です。

https://support.nintendo.co.jp/app/answers/detail/a_id/34273?a_id=34278

大雑把に RFC 3489 の分類ではどれなの?ということで、https://play.google.com/store/apps/details?id=hu.uszeged.inf.wlab.stunner&hl=jaを動かしてみたところ、 "Network Type: Symmetric cone" とのこと。
Symmetric NAT は UDP hole punching が効かないのでダメそう。

Symmetric NAT になる実装はあんまり多くなく*1、知ってる範囲だと OpenBSD pf(4) のデフォルト(static-port オプション無し)ぐらいなので、不思議に思って RTX のドキュメントを探したところ、そのものずばりのものがあった。*2

NAT動作タイプの違いについて

曰く、ポートセービングIPマスカレードなる機能が Rev.14.01.08 で追加され、これは Symmetric NAT 相当の振る舞いでありデフォルトで有効となっている。

対策

マニュアルどおり nat descriptor backward-compatibility 1 を叩く。

# nat descriptor backward-compatibility 1
NAT backward-compatibility setting has been configured. Please save config and
restart router to enable new setting.
# save
Saving ... CONFIG0 Done .
# restart

STUNner を動かしたところ "Network Type: Port restricted cone" に変化し、 Splatoon 2 も速やかにマッチが終わり問題なく遊べるようになった。やったー!!

未解決の疑問点

2つある。

まず、 Symmetric NAT にもかからず、なんで "NATタイプ B" になるんだろうか? Nintendo Switch の NATタイプ判定に考慮漏れがありそうだが、そもそも rfc3489 が廃止になっちゃうぐらい NAT traversal は複雑奇っ怪なので、しょうがない気はする。

次に、NAT動作タイプの違いについてによると Rev.14.01 系以降でも TCP 以外のすべてのプロトコルでは従来の(ポートセービングIPマスカレードではない) NAPT になるとあり、 Splatoon 2 は UDP なので、本来はデフォルトのまま動くはずである。が、動かなかった。
もっと言うと nat descriptor backward-compatibility を変更しても変化が無いはずだが、改善した。これはなぜか?実は UDP の挙動も変わってしまっている?

Nintendo Switch の挙動

Nintendo SwitchUPnP に対応していない模様。 UDP 1900 をまったく投げない。 CGN で二重 NAPT になっていることが多いからやめちゃったのだろうか?
また、 Splatoon 2 は UDP フルメッシュで通信し、マッチ中に UDP が届くか相互にパケットを投げて確認しています。サーバが選出されるようなアーキテクチャではないようで、 8台がすべて相互に通信できる必要があります。

Symmetric NAT

今回はトラブルに遭遇してしまったけれども、ポートセービングIPマスカレード自体は良い機能だと思う。 * cone NAT だと振る舞い上、変換後の送信元ポート数(16bit)でセッション数が制限されてしまうので、グローバル IPアドレスあたりの集約率に限界がある。
しかし、 Symmetric NAT なら宛先 IPアドレスが異なれば送信元ポートを共有できるので大幅に集約率を向上できる。例えば Webクローラーを含む数千台のサーバを 1 IPアドレスに収容するといった芸当も可能で、事例も知っている。
しかし、 CGN で導入すると今回のように NAT traversal でクレームが上がりそうだし、 abuse 問い合わせで src port だけでなく dest ip まで必要になるので、(Webサービスなどで)サーバ側のグローバル IPアドレスを含むログを取得しているのかといった問題がでてくるので、ちょっと難しそうであった。
RTX1210 の用途を考えると良い機能だな、と思います。

結論

NAPT むづかしい

STUNner

STUNner はこんな感じで大変便利なツールでした。

RTX1210 ポートセービングIPマスカレード

RTX1210 nat descriptor backward-compatibility 1

*1:正確にはセッション数が数千程度という条件があり、例えば iptables MASQUERADE はセッション数 2^16 以上いけるのでポートが足りなくなると Symmetric NAT になるはず。

*2:話は逸れるけど、こういうの調べる度に YAMAHA はドキュメント良くていいなぁと思います。