SIP 通話が VPN 経由で登録できても音声が送られない理由
登録と音声は別々の経路を通ります。一本の通話をトンネル越しに追い、PBX が使えるアドレスと RTP が実際に止まる場所を確認します。
登録が成功しても、音声についてはほとんど何もわかりません。ソフトフォンはオフィスの PBX との有効なバインドを何時間も保持しながら、沈黙を届けることがあります。トンネルは誰かが意図的に送り込んだパケットだけを運び、通話は三つの別々の経路、すなわちバインド、ダイアログの確立、そして RTP ストリームを使います。これらを分けて考えると、障害は VPN という言葉ではなく、一つの経路に落ちます。
自宅の Wi-Fi につないだノートパソコンが、承認済みのトンネル経由でオフィスの内線を呼び出す場面を想像してください。PBX はユーザーを認証し、REGISTER を受け入れ、内線は利用可能として表示されますが、それでも通話は一方向で完全な無音のままつながります。
登録が結びつけるのは連絡先であり、メディア経路ではない
REGISTER リクエストは、レジストラにレコードのアドレスと一つ以上の連絡先 URI の対応を保存するよう求めます。その対応が答えるのは、新しいダイアログを今どこへ送るかという狭い問いだけです。メディアがどこに属するかは何も語りませんし、登録が受け入れられても、後続の INVITE が到達可能なメディアアドレスを運ぶことは証明されません。登録にはタイマーによる期限もあり、更新をやめた電話は、トンネルが健全に見えたまま着信を失います。トンネルの状態ではなく、連絡先の期限を見てください。
ソフトフォンがトンネルの内側にあると、連絡先ヘッダーがプライベートアドレスを運ぶことがあります。それを別の端点へ転送する PBX は、呼ばれた側が到達できないネットワークを指すダイアログを作ります。PJSIP の端点で rewrite_contact=yes を設定すると、PBX は観測した送信元アドレスに置き換えますが、これが呼び出し音とタイムアウトの違いになることがよくあります。
INVITE が提示するものと、それを使える相手
SDP 本文を持つ INVITE は、発信者がメディアを受け取りたい場所、つまりアドレス、ポート、コーデックの一覧を提示します。着信側は自分のアドレスとポートで応答し、その後、双方が相手の提示した場所へ RTP を送ります。発信者が自宅ネットワークの中にしか存在しない 192.168.x.x というアドレスを提示した場合、シグナリングがどれほどきれいでも、着信側には音声を送る先がありません。マスカレードはパケットがルーターを出るときに IP ヘッダーを書き換えますが、SDP 本文の中のテキストは決して書き換えません。
このずれが、シグナリングは両方の端点が PBX に到達できるため機能し、音声は一方の端点が別の NAT の内側にしか存在しないアドレスへ送るよう指示されていたために失敗する、古典的な片方向通話を説明します。
| Path | Who picks the address | Typical failure |
|---|---|---|
| REGISTER | Softphone, rewritten by the registrar if configured | Binding expires or points at a private address |
| INVITE and SDP | Each endpoint in its own offer or answer | Offer names a media address nobody can route to |
| RTP | PBX relay policy or the two endpoints | Port range blocked, or no return path |
音声を誰が運ぶかは設定の選択である
シグナリングとメディアは別の役割です。プロキシは通話全体を通してシグナリング経路上にとどまり、RTP パケットを一つも触らないことがあります。PBX がメディアリレーになるかどうかは、トンネルの有無ではなく設定で決まります。
直接メディアでは端点どうしが RTP を交換しますが、これは一つの LAN ではうまく機能し、片側が狭いポート範囲の内側にあると悪化します。
direct_media=no を設定すると、PBX がメディア経路に入り、両方のレッグが PBX の管理するアドレスで終端し、帯域と CPU を引き換えに、予測可能なアドレス指定を得る形です。リレーする場合でも、PBX は到達可能なアドレスを通知しなければなりません。複数ネットワークのホストでは、pjsip.conf の external_media_address と external_signaling_address が、SDP と Via ヘッダーに何が現れるかを決めます。これらを未設定のままにすると、PBX はトンネルの遠端しか経路を持たない発信者に LAN アドレスを提示してしまうことがあります。
設定に触れる前に、各方向を追跡する
通話が継続している間に PBX のソケット表から始め、ss -uanp | grep -E '5060|10000' で RTP ポートがバインドされているか、どのローカルアドレスを使っているかを確認します。メディア範囲に何もバインドされていなければ、リレーは動いておらず、端点どうしが直接話しています。次にソフトフォン側で tcpdump -ni any -s0 udp portrange 10000-20000 -w rtp.pcap を使ってキャプチャします。受信パケットのない送信パケットは、問題を戻り経路か、遠端が使うよう指示されたアドレスに絞り込み、キャプチャが空ならメディアはトンネルのインターフェースにまったく届いていません。sngrep によるシグナリングのキャプチャは、送信されたときの SDP 接続行を示すことで残りの半分に答えます。
その接続行のアドレスを、遠端が実際にルーティングできるアドレスと比較してください。この一つの比較が、ほとんどの片方向音声の報告を、どんな設定レビューよりも速く解決します。
暗号化はトンネルの縁で止まる
TLS 上の SIP は設定されたシグナリング区間を保護し、SRTP は双方が交渉したときにメディアを保護し、トンネルは自身の端点間の通信を保護します。どれも他の保護を与えるものではありません。トンネル内で暗号化された通話も、ゲートウェイを出て PBX に向かう区間では平文になり得ますが、これは欠陥ではなく設計上の判断です。
チケットを閉じる前に、登録が新しいこと、SDP が遠端の到達できるアドレスを運んでいること、メディアポートでパケットが双方向に流れていることの三つを順に確認します。どれかが偽なら、問題はトンネルにはありません。失敗した経路を直し、同じキャプチャをもう一度実行して変更を確認します。前後のキャプチャを残しておけば、次回の片方向報告は半日ではなく五分の確認になります。