要約

  • RFC 3581 は、要求が実際に来た IP アドレスと UDP ポートへ応答を返すよう、空の rport でクライアントが求める仕組みである。成立したのは当該 transaction の戻り道であって、将来の着信経路ではない。
  • 観測 tuple、NAT mapping、flow、registration、dialog、利用者の結果は寿命も権限者も異なる。一度の応答成功を「到達可能」にまとめると、どの約束が切れたのか再現できなくなる。

端末の Via は 10.1.1.1:4540 と言い、受信 proxy のパケット記録は 192.0.2.1:9988 と言う。どちらかが単純に偽なのではない。前者は端末の内側、後者は NAT を越えた観測であり、用途と時間軸が違う。

RFC 3581 は、この差を一つの応答について解く。2003年8月に Standards Track として公開された文書は、最上位 Via に rport を追加した。クライアントは値なしで機能を求め、サーバーは観測した port を記録する。そして応答をその観測 tuple へ、要求を受けたのと同じサーバー側 socket から返す。

ここで証明されたのは狭い。いま届いた要求から得た新鮮な証拠を、いまの応答に使ったということだ。この狭さを守ると障害は説明できる。広げると、応答が届いたのに次の INVITE が消えるという現象を「矛盾」と誤認する。

混成ルールを線上の観測で補う

元の SIP/UDP 応答先は混成だった。IP アドレスは受信 packet の source から取り、port は Via の sent-by から取る。サーバーが単一の公開 socket で要求と応答を扱いやすい一方、NAT が address と source port の両方を変えると、公開 address と私的 port が組み合わされる。

空の rport は、クライアントが公開 port を自己申告しているのではないことを示す。受信者の観測を使ってほしいという flag である。サーバーは数値 rport と received を埋める。received は観測 address が sent-by と同じでも必要になる。

unreliable unicast で maddr がなく、両 parameter がある場合、応答先は received:rport となる。さらに応答元も要求を受けた同じ address と port でなければならない。symmetric NAT にとって remote 側 tuple も mapping の一部だからだ。

したがって、数値だけでは証拠が不足する。要求時の top Via、wire source、受信 interface、server instance、応答 source、branch、Call-ID、CSeq、送受信時刻を同じ receipt に閉じ込める必要がある。

Stateful と stateless は証拠の置き場所が違う

複数 interface や port で待ち受ける server は、どこで要求を受けたかを覚えなければならない。stateful proxy なら transaction 中の memory に置ける。stateless proxy は response まで memory を保持しないため、自分が追加する Via に宛先情報を符号化し、戻ってきたときに復元できる。

これは重要な設計判断である。stateless は provenance 不要という意味ではない。provenance が message と一緒に移動するという意味だ。論理的な service 名だけを記録しても、NAT が見た具体的 socket は復元できない。

cluster の一台が要求を受け、別の一台が後の要求を送ると、application 上は同じ service でも wire 上の peer は異なる。load balancer の健全性は、この transaction が同じ socket から戻った証拠を代替しない。

応答成功に有効期限は刻まれていない

RFC 3581 は NAT binding が transaction の間存続する必要があると書く。短い non-INVITE は当時一般的と考えられた UDP timeout 内に収まりやすい。INVITE は最終応答まで任意に長くなり得るため、provisional response の後も再送して mapping を更新するよう勧めた。

この運用は、tuple が lease ではないことを示す。最後の packet から時間がたつ、NAT が再起動する、policy が変わる、edge が failover する。それだけで経路はなくなる。SIP のユーザー名や登録 expiry が残っていても関係ない。

文書は RFC 3489 の binding lifetime discovery に触れつつ、その測定が不確実だと認める。RFC 3489 は RFC 5389 に、さらに RFC 5389 は RFC 8489 に置き換えられた。2003年の timeout 見積りを現在の事実として使ってはならない。保存すべきなのは測定値、最後の成功、再送条件と不確実性である。

Contact に書けば route になるわけではない

received と rport を見れば、端末は server から見た public tuple を知る。その値を Contact に入れて再登録すれば着信にも使える、と考えたくなる。RFC 3581 はこれを本来の response routing と区別し、UNSAF として脆弱性を列挙した。

mapping を保つための再登録は通常よりはるかに頻繁になり得る。symmetric NAT では、観測した server からの packet だけが通ることがある。cluster の別 node は同じ Contact を読めても着信を届けられない。REGISTER を registrar ではなく proxy が受けたなら、将来の要求はその proxy を通る必要があり、RFC 3327 Path がその事実を表す。

rport には有効 remote peer、期限、edge proxy、cluster affinity が入っていない。つまり観測値を address book に移すと、必要条件が不可視になる。

RFC 3581 が求めた長期解は、address を推測して公開するのではなく、client が自分の開始した connection/flow を着信にも使うよう明示できること、server cluster を扱えること、過剰 refresh を要求しないことだった。RFC 5626 SIP Outbound は registration binding と client-initiated flow を結び、複数 flow、keepalive、failure detection を定義した。RFC 6314 は NAT traversal practice として Outbound を推奨する。

それでも claim は分かれる。RFC 6223 は keepalive negotiation が connection reuse を定義しないとする。RFC 5923 は connection-oriented transport の reverse request を扱う。RFC 5627 の GRUU は UA instance に安定した routable URI を与える。pong は registration 選択ではなく、flow token は authorization ではなく、URI は通話結果ではない。

暗号化しても観測の寿命は延びない

source address と port は機微情報になり得るため、RFC 3581 は SIP over TLS による保護を挙げる。TLS は Via の改変を防ぎ得る。だが TCP/TLS では rport の response-routing 機能より、server が見た port の通知という意味が中心になる。

中間者が rport を除けば NAT 内の client は応答を失い得る。integrity はその妨害を防ぐが、public tuple の所有者を証明せず、mapping の将来を保証しない。IANA registry の登録も syntax の調整を示すだけで、実装、稼働、到達性の証拠ではない。

完全な record は、identity authentication、transaction tuple、proxy socket、Path/flow、registrar selection、dialog route、alert/answer/media/application outcome を別々に結ぶ。前段の成功を後段の代わりにしてはならない。

証拠の境界

本稿は carrier、PBX、SIP provider、UA、proxy、registrar、NAT 製品、cluster、利用者、call、incident、media result を特定しない。Standards Track は deployment share を示さない。

RFC 3261 は SIP transaction と Via の基礎、RFC 3327 は Path、RFC 3424 は UNSAF の評価枠を与える。RFC 3489 は歴史的参照に限定し、RFC 5389 と RFC 8489 が後続 STUN を示す。RFC 5626、RFC 6314、RFC 5923、RFC 6223、RFC 5627 はそれぞれ Outbound、practice、connection reuse、keepalive、安定 UA routing の境界を示す。IANA 登録は running proof ではない。

Heng Lu の Running-Code Primacy と Minimum Initial Specification は、公開した編集上の lens である。宣言ではなく走った経路を確認し、共通仕様を相互運用に必要な範囲に抑えるために使う。RFC 著者の意図や導入実績の証拠には使わない。

結論は小さいから強い。一つの応答が一つの時点で一つの port に届いた。その receipt を守る。同時に、それを次の要求の保証にはしない。

出典