Flexisip : B2BUA (Back-to-back User Agent)

Flexisip : SIPネットワークと電話網との相互接続について

https://linphone.org/news/flexisip-allows-interconnection-pstn-networks



ubuntu-flexisipコンテナ内でデバックモードで起動

$ docker compose -p project exec ubuntu-flexisip bash
# bin/flexisip --server b2bua --debug

[b2bua-server]のapplicationでsip-bridgeを指定(デフォルトはtrenscrypter)し、関連セクションを設定。[b2bua-server::sip-bridge], [module::B2bua]

flexisip.conf

##
## Flexisip back-to-back user agent server parameters.
##
[b2bua-server]

# The type of application that will handle calls bridged through
# the B2BUA. Possible values:
# - `trenscrypter` Bridge different encryption types on both ends
# transparently.
# - `sip-bridge` Bridge calls through an external SIP provider.
# (e.g. for PSTN gateways)
# Default: trenscrypter
application=sip-bridge

# SIP uri on which the back-to-back user agent server is listening
# on.
# Default: sip:127.0.0.1:6067;transport=tcp
#transport=sip:127.0.0.1:6067;transport=tcp

# Directory where to store b2bua core local files
# Default
# Default: /var/opt/belledonne-communications/flexisip/b2b
#data-directory=/var/opt/belledonne-communications/flexisip/b2b

# The Flexisip proxy URI to which the B2bua server should send all
# its outgoing SIP requests.
# Default: sip:127.0.0.1:5060;transport=tcp
#outbound-proxy=sip:127.0.0.1:5060;transport=tcp

##
## External SIP Provider Bridge parameters.
##
[b2bua-server::sip-bridge]

# Path to a file containing the accounts to use for external SIP
# bridging, organised by provider, in JSON format.
# Here is a template of what should be in this file:
# [{"name": "<user-friendly provider name for CLI output>",
#   "pattern": "<regexp to match callee address>",
#   "outboundProxy": "<sip:some.provider.example.com;transport=tls>",
#   "registrationRequired": true,
#   "maxCallsPerLine": 42,
#   "accounts": [{
#     "uri": "sip:[email protected]",
#     "userid": "<optional (e.g. an API key)>",
#     "password": "<password or API token>"
#   }]
# }]
# Default: example-path.json
providers=providers=/path/to/your/providers-file.json

##
## This module is in charge of intercepting calls and route them
## to the back-to-back user agent server
##
[module::B2bua]

# Indicate whether the module is activated.
# Default: false
enabled=true

# A request/response enters module if the boolean filter evaluates
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
# && (user-agent == 'Linphone v2'). You can consult the full filter
# documentation here : https://wiki.linphone.org/xwiki/wiki/public/view/Flexisip/Configuration/Filter%20syntax/
# Default: 
#filter=

# A sip uri where to send all the relevent requests.
# Default: sip:127.0.0.1:6067;transport=tcp
#b2bua-server=sip:127.0.0.1:6067;transport=tcp

Transcrypterモード

メディア(RTP)暗号化の方式が異なるSIPクライアント同士の通信を中継・変換

たとえば、以下のような異なる暗号方式を使う SIP クライアント間で通話を成立させたいときに使います:

  • 発信者(leg A):DTLS-SRTP
  • 受信者(leg B):SDES-SRTP

このとき、Flexisipが間に立って、異なる暗号化方式を変換しながらRTPを中継

  • Leg A:発信側
  • Leg B:着信側
  • Transcrypter:Leg A ↔ Leg B間でRTP暗号化方式の変換を行う中継機能

Leg Aの暗号化方式

Flexisip(B2BUA)は、発信者(Leg A)からの接続に対して、以下の暗号化方式を受入:

  • 暗号なし(unencrypted RTP)
  • SDES-SRTP
  • DTLS-SRTP
  • ZRTP

発信側がどの方式を使ってきても、B2BUAは受け入れて通話を確立。

Leg Bの暗号化方式の選択方法

通話のもう一方(Leg B)の暗号化方式は、次のようにしてFlexisipが選択:

1. 受信者のSIP URI(またはGRUU)に基づく

sip:[email protected] などの宛先アドレスや、GRUU(Globally Routable User URI)に基づいて、b2bua-server::trenscrypter セクションに定義されたルールにマッチさせて、受信者に使う暗号化方式を決定。

2. SDES(SDP Security Descriptions)方式の場合

さらに細かく、使用する SRTP crypto suite(例:AES_CM_128_HMAC_SHA1_80)に基づいて、適切な暗号設定を行うことが可能。

flexisip.confの設定については、下記のセクションを調整(IPv6のみで対応する場合)

注) 44000ユーザのみに適用するフィルタを設定。
ネットワークをIPv6限定にしたため、STUNサーバとMediaRelayは無効とした。

[global] ---> transports=sip:127.0.0.1:5060;transport=tcp sip:sip.example.com:5060;transport=tcp sips:sip.example.com:5061
[global] ---> rtp-bind-address=0.0.0.0 PUBLIC_IPV6_ADDRESS
[stun-server] ---> false
[conference-server] ---> nat-addresses=sip.example.com
[b2bua-server] ---> application=trenscrypter 
[b2bua-server::trenscrypter] ---> outgoing-enc-regex=none .*@sip\.example\.com(;.*)?
[module::NatHelper] ---> ??? should be checked!
[module::B2bua] ---> filter=(to.uri.user contains '44000') || (from.uri.user contains '44000')
[module::Router] ---> ???
[module::MediaRelay] ---> enabled=false

負荷試験

通話品質を損なうことなく処理できる同時通話数。

表の見方
5 call/s renewing rate —> 365 calls – 64% CPU

365通話を同時接続した状態で、1秒あたり5回のINVITE/BYEリクエストが来ても、サービス劣化なく通話品質を維持できる

Performance With Audio Transcoding

Codec scenario: G.711 ↔ G.729

Flexisip version 1 call/s renewing rate 5 call/s renewing rate
2.4.0-alpha-347 415 calls – 75% CPU 365 calls – 64% CPU
2.5.0-beta-34 460 calls – 78% CPU 385 calls – 65% CPU

Performance Without Transcoding

Codec scenario: G.729 ↔ G.729

Flexisip version 1 call/s renewing rate 5 call/s renewing rate
2.4.0-alpha-347 Unavailable 445 calls – 40% CPU
2.5.0-beta-34 790 calls – 59% CPU 550 calls – 40% CPU

LinphoneがSDES-SRTP(a=crypto: は SDES 方式)で標準的に提示する4種類の暗号スイート

Linphoneデスクトップからのログ参照

a=crypto:1 AEAD_AES_128_GCM inline: 
a=crypto:2 AES_CM_128_HMAC_SHA1_80 inline:
a=crypto:3 AEAD_AES_256_GCM inline:
a=crypto:4 AES_256_CM_HMAC_SHA1_80 inline:
  • AEAD_AES_128_GCM
  • AES_CM_128_HMAC_SHA1_80
  • AEAD_AES_256_GCM
  • AES_256_CM_HMAC_SHA1_80

Linphoneで暗号スイートを指定する場合は、プロビジョニングに以下を追加すること。

[sip]
media_encryption = srtp 
srtp_crypto_suites=AES_CM_128_HMAC_SHA1_80,AES_192_CM_HMAC_SHA1_80,AES_256_CM_HMAC_SHA1_80
media_encryption_mandatory=1

注) CMと128、192、256の順序は正しいようです。media_encryption_mandatory=1にしないとFreeSwitchのビデオ通話がSRTPで確立されません。

B2BUAとLIME認証

user-agentをLinphoneでフィルタリングしてLIMEを有効にすると、LIMEの公開鍵が取得できない問題が発生します。

  • b2bua-server : VoIP・インターコムとの接続で使用
  • b2bua-server::trenscrypter : メディアコーデックと暗号化のマッチング
  • module::B2bua : フィルタリングはForwardで指定
  • module::Router : 自プロキシ宛の Route ヘッダーをスキップ。外部向けの Route ヘッダーがあれば module::Forward に委譲
  • module::MediaRelay : ICE,STUNのみでメディアポートをデプロイするため未使用
  • module::Forward : B2BUAサーバのフィルタリングをここで指定

Forward

B2BUAサーバへの経由条件は、module::B2buaで指定するよりもmodule::Forwardの方がルート条件を細かく指定できるため、こちらで指定(条件にはuser-agent必須)。設定ファイルを新規に作成し下記ルールに従い条件を記述。

routes-config-path

Path to a file describing a set of ‘Route’ headers to be prepended before forwarding an out-of-dialog request. Headers are prepended only if the related conditions are met by the request.The conditions are described using Flexisip’s filter syntax, as described on
Filter syntax - XWiki
The configuration file comprises lines using the following syntax:

Comments are allowed with ‘#’.
Conditions can spread over multiples lines provided that the continuation line starts with either spaces or tabs.
The special condition ‘*’ matches every request.
The conditions are matched in the order they appear in the configuration file. The first fulfilled condition determines the route that is prepended. If the request does not match any condition, no route is prepended.
The file may be empty, or no path may be specified, in which case no route is preprended either. Here is a an example of a valid routes configuration file:
sip:example.org;transport=tls request.uri.domain == ‘example.org’
sip:10.0.0.2:5070;transport=tcp request.uri.params contains ‘user=phone’

Beware: that is not just a SIP URI, but a route. As a result, when the URI has parameters, brackets must enclose the URI, otherwise the parameters will be parsed as route parameters.

Router

IP電話(インターホン含む)との接続

LinphoneなどのクライアントでICE機能を無効にすれば接続が確立されますが、トレードオフとして、他のLinphoneクライアントとの接続エラーが発生します。

旧式インターホンにはICE機能が備わっていない機種が多く、B2BUAサーバかTurnサーバを介在させる必要があります。

Linphone < ----- > VoIP Phone
ICE/STUN TURN B2BUA MediaRelay Established
○ ○ - - OK
○ - - ○ NG
- - ○ - OK
Filter / Configuration External Server / Listening IP : IPv6 Filter with Module::Forwarding / Restricted with only the IP Phone (with No ICE Function Instruments) Except B2BUA