LAN/Wi-Fi回線で VoIP が片通話になる原因

最近、VoIP/SIP URI 関連の記事を書くにあたり、各社のサービスにサインアップし、相互に通話テストを行っているが LAN の Wi-Fi 環境を使っていると高確率で片通話になる現象が起きていた。

はじめは原因がわからず、アプリ側の設定を変えるなど試行錯誤していたがけっきょく原因はうちの LAN環境(というより、インターネットとの接続に使っているルータ)の仕様により片通話にならざるをえない、ということがわかったので情報を共有する。

結論から言うと、同じ LAN内の端末同士で SIP URI を使って VoIP通話をしようと思った場合はインターネットとの接続に使っているルータで、ヘアピンNAT という機能を実装している必要がある。

うちの環境だと Yahoo!BB からレンタルする BB光ユニット(E-WMTA2.4)をルータとして使っているが、このルータにはヘアピンNAT が実装されていないのでむつかしい。


片通話になる理由


SIP による通話では、通話を制御するためのやりとりは、UDP/IP 5060 などを使って互いにテキストメッセイジとして相互に送り合うが、音声信号は別に RTP というパケットを使ってやりとりし、SIP内でこの RTP の情報を SDP という形で共有する。

具体的には通話する相互の端末が、自身が RTP を受けることができるポート情報をテキストで SIPメッセイジに SDP として流し、それを受けた相手側が指定されたポートへ接続して RTPパケットを投げる、という動作をする。

RTPパケットは片方向なので、送話と受話で 2つの信号路ができることになる。こちらから送信する信号は、相手の指定したポートへ送る。一方、相手から受信する信号は、こちらで指定したポートへ送ってもらう。

99% の SIPクライアントは NAPT配下にあってプライベートIPアドレスを割り振られているので、SDP で指定する自身の IPアドレスもプライベートIPアドレスになる。(STUN などを使うことで NAPT配下の端末であってもグローバルIPアドレスを通知することもできるが、今回は考慮しない)

このままだと、相手からは疎通できないので間にセッションボーダーコントローラ(SBC)という、RTP をやりとりしてくれる特殊なルータが介入し、SDP の中身を書き換えてプライベートIPアドレスで書かれていた内容を、ユーザが使っているグローバルIPアドレスに書き換えて相手に送る、といった動作をする。

SBC が間に介入してくれるおかげで、どちらも NAPT配下にいる VoIPクライアント同士で、相手のプライベートな IPアドレスを知らない状況でも通話出来るようになるがこの副作用として、同じ LAN内にある端末同士での VoIP通話で不具合が出てくる

本来、同じ LAN内にある端末同士であればプライベートIPアドレスで疎通できる(もちろん、ルータでブロックしていなければ)ので、SBC による IPアドレスの書き換えの必要はない。

しかし、SBC は通話する端末同士が同じ LAN 内に居るかまではわからないので、すべての通信を同じようにグローバルIPアドレスに書き換えていく。

SBC を通した結果、同じ LAN内に居る端末同士が、SDP の中でグローバルIPアドレスを通知されるので、当然、RTPパケットをこのグローバルIPアドレス宛に送ろうとする。

そして、実はルータ内にいるプライベートIPアドレスを持った端末から、そのルータの WAN側に付与されたグローバルIPアドレス宛に送られたパケットは、破棄されてしまうのである。

送出した RTPパケットが破棄されてしまうので相手には音声が伝わらず、片通話(というかどちらも送られないので、片通話というより送受話とも音が出ない)になってしまう。


ヘアピンNAT とは


実は上記の動作はルータとしては間違っていない。ルータは LAN内から自身の WAN側IPアドレス宛に送られたパケットは破棄してしまう動作は仕様としては合っている。

しかし今回のように LAN内のクライアントから、自身の WAN側IPアドレス宛にパケットを投げる状況はありえなくないので、これをうまいこと取り持ってくれる機能を実装したルータがある。この機能を、ヘアピンNAT、NATループバックなどと呼ぶ。

ヘアピンNAT はあまりメジャーな機能ではなく、YAMAHA のルータでも RTX830、NVR510 しか実装していない。


SIP URI による通話を阻害する


いままでの記事の中で、SIP URI を持つことで、世界中の SIP URI を持つユーザ同士が通話料無料で通話できる、という話をしてきた。SIP URI はオープンな規格なので Skype、Whatsapp、LINE のような特定企業のアプリの使用を強制されることなく、各自が好きな環境で使うことができるが、この同じLAN内の端末同士での通話が難しいという問題を解決する良い方法がいまのところない。

極端な話、同じ事業所内、同じ敷地内で Wi-Fi を使ってる同士だと通話できなくなってしまうので近い人ほど使えないという状況になってしまう。

一番よいのは、ヘアピンNAT の機能がどのルータにも当たり前に実装されていくことだが、需要としてはあまり大きくないので今後も機能が実装されていく可能性は高くない。

なお Twilio の SBC はかなり優秀で、同じグローバルIPアドレスから接続してきた場合でもちゃんと相互に変換してくれる。これはクライアントの生の IPアドレスは一切相手に通知せず、すべての RTP を Twilio の SBC を介するように制御しているためだ。(Twilio はこの SBC を運用するために、超大量の IPアドレスを確保している。そしてそのインフラ維持のため、VoIP to VoIP による通話であっても、0.51円/1分・ch の通話料を課金する)

SIP URI を提供する各SIPプロバイダが同じように完全秘匿で使える SBC を提供すれば良いのだが、RTP はユーザ同士の P2P にしてしまったほうがコストが掛からないので(SIPプロバイダは SIP だけ扱えば良い)、極力、P2P になるように制御しようとしてくる。

ちなみに、OnSIP はクライアントが SDP内でプライベートIPアドレスを使う場合のみ、SBC による介入を行う。STUN  や SIP-NAT(SIP ALG)などを使って下手にグローバルIP を送ると、SBC が介入してくれなくなる。


さいごに


技術的な小難しい話題でしたが、最後まで読んでいただいてありがとうございました。

よければ ↓ にある、♡ をクリックしていただけると励みになります。質問のコメントも歓迎です。

この記事が気に入ったらサポートをしてみませんか?