NAT 越えに置ける STUN の位置付け

## Intro

WebRTC 関係で、 NAT 越えの際に必ずお世話になる STUN について。

## STUN

まず STUN 関連の RFC では大きく 2 つある(7350 は除く)

- https://tools.ietf.org/html/rfc3489
- https://tools.ietf.org/html/rfc5389

後者が前者の更新版なので、前者を旧仕様、後者を新仕様と呼ぶことにする。

新旧どちらの仕様も STUN であり、 NAT 越えに使うという雑な説明の上では同じなのだが、
この二つは更新とはいえかなり違うものになっている。


## 旧仕様の範囲

まず、旧仕様では STUN は以下の略だった。

`Simple Traversal of UDP Through NATs`

つまり、 UDP で NAT を超えるためのプロトコルとして定義されており、
実際にそのための方法が定義されている。


具体的には Discovery という、インターネット上にあるサーバとやり取りする中で インターネット側から見た IP と Port の組を調べながら、どういう NAT の配下に置かれているかなどを調べるフローが記載されている。


```
                      +--------+
                      |  Test  |
                      |   I    |
                      +--------+
                           |
                           |
                           V
                          /\              /\
                       N /  \ Y          /  \ Y             +--------+
        UDP     <-------/Resp\--------->/ IP \------------->|  Test  |
        Blocked         \ ?  /          \Same/              |   II   |
                         \  /            \? /               +--------+
                          \/              \/                    |
                                           | N                  |
                                           |                    V
                                           V                    /\
                                       +--------+  Sym.      N /  \
                                       |  Test  |  UDP    <---/Resp\
                                       |   II   |  Firewall   \ ?  /
                                       +--------+              \  /
                                           |                    \/
                                           V                     |Y
                /\                         /\                    |
 Symmetric  N  /  \       +--------+   N  /  \                   V
    NAT  <--- / IP \<-----|  Test  |<--- /Resp\               Open
              \Same/      |   I    |     \ ?  /               Internet
               \? /       +--------+      \  /
                \/                         \/
                |                           |Y
                |                           |
                |                           V
                |                           Full
                |                           Cone
                V              /\
            +--------+        /  \ Y
            |  Test  |------>/Resp\---->Restricted
            |   III  |       \ ?  /
            +--------+        \  /
                               \/
                                |N
                                |       Port
                                +------>Restricted

               Figure 2: Flow for type discovery process
```


この結果を元に、 NAT が有るのか、無いのか、フルコーンなのかシンメトリックなのか、などを推測する。

「これこそが NAT 越え」感があるが、実は旧仕様に書かれていた一連の方法は、実際のネット上では十分で無いことがわかってきた。


## 新仕様の範囲

そうなると、新仕様では様々な仕様を追加して、より正確に Discovery できるようにするのかと思うところだが、
新仕様はこうした Discovery に関する仕様をごっそりと落としている。

加えていくつかの Attribute (パケットの形式) も「無視して良いものリスト」に追加され、
それ単体でできることは、リクエストを投げて、自分の IP を返してもらうくらいのことに止まる。


じゃあ、 NAT を超えるための細々したことはどこにいったのかというと、それは別の仕様で用途に応じて定義される。
WebRTC であれば、その役目を担うのが MMUSIC-ICE ということになる。

ICE はより包括的に、 STUN 以外のものも使って、 NAT を越えた通信経路を確立するための枠組みを提供する。
STUN はその部品の一つという位置付けになった。

なので名前も、変わっている。

`Session Traversal Utilities for NAT (STUN)`


STUN はあくまで、 NAT を超えるための Utility であり、実際に目的を達成するために STUN を使うソリューションは *stun usage* と呼ばれている。

新仕様は、実際の用途は各 *stun usage* に移譲し、そこに提供する最低限のプロトコルフォーマットなどの定義を行っている。


加えて新仕様は旧仕様の欠点を補うような形でいくつか拡張されている。

例えば、 パケット中の IP アドレスを勝手に書き換えるミドルボックス対策(固定値との XOR)が入っていたり、考慮が足らず拡張しにくい部分に謎のエンコーディング方式を導入(Message Type Field)してしのいだりしている。互換性に引きづられた、涙ぐましい努力は随所に見られる。


## デプロイ状況

デプロイされた STUN サーバはネット上に幾つかある。

https://gist.github.com/zziuni/3741933


実際に叩いてみて、返ってくるパケットで新旧のどちらかを見てみた。
なお、 WebRTC 用途では、おそらくどちらのバージョンであっても動作に問題は無いはず。

- 新: stun.l.google.com:19302
- 新: stun1.l.google.com:19302
- 新: stun2.l.google.com:19302
- 新: stun3.l.google.com:19302
- 新: stun4.l.google.com:19302
- 旧: stun.ekiga.net:3478
- 旧: stun.ideasip.com:3478
- 旧: stun.iptel.org:3478
- 旧: stun.schlund.de:3478
- 旧: stun.voiparound.com:3478
- 旧: stun.voipbuster.com:3478
- 旧: stun.voipstunt.com:3478
- 旧: stun.voxgratia.org:3478


google 以外は旧だった。


## まとめ

「STUN は NAT 越えのソリューション」みたいな説明自体は間違って無いが、実際はこんな感じになっている。
WebRTC の文脈で言えば、必要なのは NAT 越えに必要なソリューションは ICE であり、
その中のユーティリティの一つとして、新仕様の範囲の STUN が活躍しているというのが実際のところという話。