初めに
SIPを使って内線電話が構築出来たら面白そうだなと思い、さっそく手元でやってみました。
この記事はその時の忘備録です。結果的にクラウド上に構築したSIPサーバーを使って、NAT環境下のAndroid2機間で内線通話を実現する事ができました。手順通り進められれば再現できるはずですが、何かあればコメントくださいませ
Ref: https://www.nic.ad.jp/ja/newsletter/No29/100.html
※本記事は入門記事です。本番環境の利用には想定していません。
SIPサーバー構築手順
ネット上を探していると、Asteriskの古いバージョンでの入門記事だったり英語の記事がたくさんヒットします。英語ではありつつも本家マニュアルが結構参考になりました。
- 筆者環境
- Ubuntu 16.04 (多分Ubuntu 18系でも大丈夫かと思われます)
- さくらクラウド
参考にしたもの: https://wiki.asterisk.org/wiki/display/AST/Hello+World
Asterisk17のビルド
ソースコードから落としてビルドします。
(apt経由でインストールする方法等がありましたが、筆者環境だと起動がうまくいきませんでした)
ubuntu@dev:~$ wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-17.2.0.tar.gz
ubuntu@dev:~$tar -zxvf asterisk-17.2.0.tar.gz
ubuntu@dev:~$ cd asterisk-17.2.0/
ubuntu@dev:~$ ./contrib/scripts/install_prereq install
ubuntu@dev:~$ ./configure --with-jansson-bundled
ubuntu@dev:~$ ./make -j4
ubuntu@dev:~$ ./make install
ubuntu@dev:~$ ./make samples # 初期の設定ファイル等がインストールされる
Asterisk17の設定
今回は内線電話番号6001,6002を構築し、お互いにつながるようにします。
pjsip.confの設定
SIPサーバーに関する設定や内線電話(SIPクライアント)からの認証情報を設定します。
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0
[6001]
type=endpoint
context=from-internal
disallow=all
allow=ulaw
auth=6001
aors=6001
rewrite_contact = yes # 6001がNAT環境下の場合、必要。
[6001]
type=auth
auth_type=userpass
password=unsecurepassword
username=6001
[6001]
type=aor
max_contacts=10
[6002]
type=endpoint
context=from-internal
disallow=all
allow=ulaw
auth=6002
aors=6002
rewrite_contact = yes # 6002がNAT環境下の場合、必要。
[6002]
type=auth
auth_type=userpass
password=unsecurepassword
username=6002
[6002]
type=aor
max_contacts=10
extensions.conf
内線電話(SIPクライアント)からの発着信時のルールをここに記述します。
[from-internal]
exten = 100,1,Answer()
same = n,Wait(1)
same = n,Playback(hello-world)
same = n,Hangup()
# 6001がコールされたらSIPの6001を呼び出す
exten = 6001,1,Dial(PJSIP/6001,30,r)
same = n.Hangup()
# 6001がコールされたらSIPの6001を呼び出す
exten = 6002,1,Dial(PJSIP/6002,30,r)
same = n.Hangup()
UFWの設定 (任意)
SIPサーバーを次のステップで起動しますが、起動してtcpdump等で見てみると、意外と
外国からの攻撃がすごいので、筆者環境ではUFWによるファイアウォールを入れました。
(必須ではないですが、入れておくと安心でしょう)
ubuntu@dev:~$ apt install ufw
ubuntu@dev:~$ ufw enable
ubuntu@dev:~$ ufw default DENY
# SIP用ポートを許可
ubuntu@dev:~$ ufw allow from XXX.XXX.XXX.XXX/32 to any port 5060 proto udp
# RTP用ポートを許可
ubuntu@dev:~$ ufw allow from XXX.XXX.XXX.XXX/32 to any port 10000:20000 proto udp
ubuntu@dev:~$ ufw reload
※XXX.XXX.XXX.XXX
は、SIPクライアントとして接続が想定される元のIPです(SRCIP)
ref: https://qiita.com/yoh-nak/items/46935af3c5c4036e93b3
Asterisk17のサービス起動
ubuntu@dev:~$ systemctl unmask asterisk
ubuntu@dev:~$ systemctl start asterisk
ubuntu@dev:~$ systemctl status asterisk
● asterisk.service - LSB: Asterisk PBX
Loaded: loaded (/etc/init.d/asterisk; bad; vendor preset: enabled)
Active: active (running) since Thu 2020-02-27 23:26:27 JST; 39min ago
Docs: man:systemd-sysv-generator(8)
Process: 1236 ExecStop=/etc/init.d/asterisk stop (code=exited, status=0/SUCCESS)
Process: 1248 ExecStart=/etc/init.d/asterisk start (code=exited, status=0/SUCCESS)
Main PID: 8328 (code=exited, status=0/SUCCESS)
Tasks: 72
Memory: 38.8M
CPU: 19.957s
CGroup: /system.slice/asterisk.service
mq1261 /usr/sbin/asterisk
Feb 27 23:26:27 ootaguro-dev asterisk[1236]: ...done.
Feb 27 23:26:27 ootaguro-dev systemd[1]: Stopped LSB: Asterisk PBX.
Feb 27 23:26:27 ootaguro-dev systemd[1]: Starting LSB: Asterisk PBX...
Feb 27 23:26:27 ootaguro-dev asterisk[1248]: * Starting Asterisk PBX: asterisk
Feb 27 23:26:27 ootaguro-dev asterisk[1248]: ...done.
Feb 27 23:26:27 ootaguro-dev systemd[1]: Started LSB: Asterisk PBX.
Feb 27 23:26:28 ootaguro-dev asterisk[1261]: rc_read_config: can't open /etc/radiusclient-ng/radiusclient.conf: No such file or directory
Feb 27 23:26:28 ootaguro-dev asterisk[1261]: rc_read_config: can't open /etc/radiusclient-ng/radiusclient.conf: No such file or directory
Radius関係のエラーがでますが、一旦無視しても後述のテストはPASSできます。
ERRORという文字が多く出る場合、モジュールのロードや設定に異常があるので確認したほうが良いです。
正常に起動すると、下記のようにSIPやIAXポートがLISTENされます。設定ファイルミスがある場合、systemctl status asterisk
ではactive(running)表示でもLISTENできてないケースがあるので、チェックしておいた方が無難です。
(なんか予想以上に色々LISTENしているので別途調査しておいたほうがよさそうですね)
root@dev:/usr/src/asterisk-17.2.0# lsof -i | grep asterisk
asterisk 1261 root 10u IPv4 10870690 0t0 UDP *:56066
asterisk 1261 root 11u IPv6 10870691 0t0 UDP *:43403
asterisk 1261 root 12u IPv4 10870678 0t0 UDP *:sip
asterisk 1261 root 20u IPv4 10870696 0t0 UDP *:iax
asterisk 1261 root 21u IPv4 10870700 0t0 UDP *:2727
asterisk 1261 root 22u IPv4 10870704 0t0 TCP *:cisco-sccp (LISTEN)
asterisk 1261 root 25u IPv4 10870717 0t0 UDP *:4520
asterisk 1261 root 26u IPv4 10871862 0t0 UDP *:5000
実機テスト
今回は、Android端末を2台手元に用意し、Wifiルーターに接続させて実験しました。(NAT環境下)
ゴールは、SIPクライアントとして動作させる2台のAndroid端末間で内線電話の発着信&通話ができる事です。
MizuDroidのインストール
PlayStoreからSIPクライアントであるMizudroidを2台のAndroid端末に導入します。
iPhoneの場合もいくつか、SIPクライアントがAppleStoreにあるようです。
(GoogleログインしたPCでアクセスすると、リモートでいストールが実行できる模様)
MizuDroidにSIPサーバーの情報を入力
上記の画像では、内線番号6001の認証情報を入力しました。内線番号6001と6002のそれぞれの認証情報を2台のアプリ設定に入れ込みます。正しく認証されると、REGISTEREDという緑色の文字が見れます。Failという文字が出てくる場合は、入力した認証設定が間違えている可能性があります。
内線番号6001 → 内線番号6002への発信
ここまでの設定がうまくいっていれば、もう片方の携帯(内線番号6002に設定)が着信するはずです。
バックグラウンドで動作させないとアプリがフォアグラウンドにいる時しか着信できないので注意しましょう。
余談: TCPDUMPでのパケットキャプチャ
自分自身のSIP理解の為に、やり取りされているパケットを実際に覗いてみました。
認証時の様子 (アプリ立ち上げ時)
サーバーに向かってREGISTERが飛んできている。Digest認証を用いている模様。
それに対して200OKが返却されている。意外とHTTPと似たようなプロトコルの作りっぽい。
XXX.XXX.XXX.XXX => SIPクライアント(MIZUDROID)のGIP (NAT環境なので出口のIP)
YYY.YYY.YYY.YYY => SIPサーバー(Asterisk)のGIP
ubuntu@dev:~$ sudo tcpdump -vni any -s0 port 5060
23:45:24.698632 IP (tos 0x0, ttl 51, id 47054, offset 0, flags [DF], proto UDP (17), length 914)
XXX.XXX.XXX.XXX.14425 > YYY.YYY.YYY.YYY.5060: SIP, length: 886
REGISTER sip:YYY.YYY.YYY.YYY:5060 SIP/2.0
Via: SIP/2.0/UDP XXX.XXX.XXX.XXX:10784;rport;branch=z9hG4bK-49p4241941521357628102r
From: <sip:6002@YYY.YYY.YYY.YYY>;tag=48g693852704041038639m
To: <sip:6002@YYY.YYY.YYY.YYY>
Call-ID: 46e2593884576040101175k8434rmwp
CSeq: 7250 REGISTER
Max-Forwards: 70
Expires: 180
Authorization: Digest username="6002",realm="asterisk",nonce="1582814724/1b2032af1c4a73529219052df1e041d7",uri="sip:YYY.YYY.YYY.YYY:5060",response="ed22cb18e22c2a1c81e8e0bba7ea6fac",opaque="7b404df425a56bb0",cnonce="6228548815293381558",nc=00000001,qop=auth,algorithm=MD5
Contact: <sip:6002@XXX.XXX.XXX.XXX:10784>
X-UT: a
User-Agent: MizuDroid/2.7.0
X-DeviceID: d559a947758b1856
Supported: replaces
Allow: ACK,PRACK,BYE,CANCEL,INVITE,UPDATE,MESSAGE,INFO,OPTIONS,SUBSCRIBE,NOTIFY,REFER
Accept: application/sdp,application/dtmf-relay,text/plain
Content-Length: 0
23:45:24.701050 IP (tos 0x0, ttl 64, id 30505, offset 0, flags [DF], proto UDP (17), length 558)
YYY.YYY.YYY.YYY.5060 > XXX.XXX.XXX.XXX.14425: SIP, length: 530
SIP/2.0 200 OK
Via: SIP/2.0/UDP XXX.XXX.XXX.XXX:10784;rport=14425;received=XXX.XXX.XXX.XXX;branch=z9hG4bK-49p4241941521357628102r
Call-ID: 46e2593884576040101175k8434rmwp
From: <sip:6002@YYY.YYY.YYY.YYY>;tag=48g693852704041038639m
To: <sip:6002@YYY.YYY.YYY.YYY>;tag=z9hG4bK-49p4241941521357628102r
CSeq: 7250 REGISTER
Date: Thu, 27 Feb 2020 14:45:24 GMT
Contact: <sip:6002@XXX.XXX.XXX.XXX:9663>;expires=23
Contact: <sip:6002@XXX.XXX.XXX.XXX:14425>;expires=179
Expires: 180
Server: Asterisk PBX 17.2.0
Content-Length: 0
まとめ
今回、SIPサーバーを構築し、SIPクライアントを導入したAndroid端末間で内線通話をする事ができました。
今後の展望としては、下記の記事のようにTwilioと連携させてPSTN(電話回線網)と発着信したりチャレンジできればと思っています。
https://qiita.com/sgrowd/items/dd1fc682718a2a623e4c
次記事:https://qiita.com/xecus/items/a5e677bb85372e502b37 (追記)
ありがとうございました。