Jitsi MeetとAsteriskをIBM Cloud (Classic)の仮想マシンに移行

[前々日](https://qiita.com/rk05231977/items/a8e627d87767ee4ec5ac)、[前日](https://qiita.com/rk05231977/items/0ea9289605ff9682d2ac)と、IPフォンでJitsi Meetにつなぎたかったわけだが、一方だけ発声可能とかの問題がNATが絡むとSIP/RTPは良くわからなさ過ぎる。
そういえばIBM Cloudの（クラシックの）仮想マシンが、仮想マシンにパブリックIPが直接ついてNATしないタイプだったのというのを思い出し、そちらで検証継続。

# 仮想マシン
IBM Cloudの「Virtual Server for Classic」で仮想マシンを２台作成。
https://cloud.ibm.com/gen1/infrastructure/provision/vs

仮に、１つはjm.example.com(Jitsi Meet)、１つはpbx.example.com(Asterisk)と名前を付ける。

スペックはどちらも最小のU1.1x2（CPU 1、RAM 2GB、HDD 25GB）。OSはUbuntu 18.04。
時間$0.02と、月にすると1500円ほどでちょっと高いのだが、時間課金なら飽きたらすぐ消せばいい。
ファイアウォールも、デフォルトでは全部空いているので今回の検証用途ではありがたい。

サーバーを注文するとパブリックIPが付いてくるので、そのAレコードをDNSサーバー（AWSのRoute 53）に登録する。

# Jitsi Meetをインストール
ついでなので、[前の記事](https://qiita.com/rk05231977/items/a8e627d87767ee4ec5ac)で実行したコマンドのまとめ。
jmサーバーで実施する。

```
（OS準備）
# sudo apt update
# sudo apt install apt-transport-https
# sudo apt-add-repository universe
# sudo apt update
# sudo apt install openjdk-8-jdk
# curl https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
# echo 'deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list > /dev/null
# sudo apt update

（Jitsi Meetインストール）
# sudo apt install jitsi-meet
　→ 途中で入力するhostnameは、例えば「jm.example.com」
　→ とりあえず自己署名証明書を作る。サービスの再起動はYES。

（Let's Encrypt証明書作成）
# sudo /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
```

# Asteriskをインストール
同じく、[前の記事](https://qiita.com/rk05231977/items/0ea9289605ff9682d2ac)のまとめ。
pbxサーバーで実施する。

```
（Asteriskのビルド）
# apt-get update
# apt-get install build-essential
# git clone https://github.com/asterisk/asterisk
# cd asterisk
# apt-get install libedit-dev
# apt-get install uuid-dev
# apt-get install libjansson-dev
# apt-get install libxml2-dev
# apt-get install libsqlite3-dev
# ./configure
# make
# make install
# make samples
```

ファイルを作る。

```:/etc/asterisk/pjsip.conf
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0

[6001]
type=endpoint
disallow=all
allow=ulaw
auth=6001
aors=6001

[6001]
type=auth
auth_type=userpass
password=＜パスワード＞
username=6001

[6001]
type=aor
max_contacts=1

[6002]
type=endpoint
disallow=all
allow=ulaw
auth=6002
aors=6002

[6002]
type=auth
auth_type=userpass
password=＜パスワード＞
username=6002

[6002]
type=aor
max_contacts=4

```

ファイルを作る。

```:/etc/asterisk/extensions.conf
[general]
static=yes
writeprotect=no
clearglobalvars=no

[globals]

[default]
exten => _600X,1,Dial(PJSIP/${EXTEN},30)
 same => n.Hangup()
```

```
（Asterisk起動）
# make config
# systemctl enable asterisk
# systemctl start asterisk
```

# Jitsi MeetをAsteriskに接続する
jmサーバーで実施する。

```
# sudo apt install jigasi
　→ SIP username: 6001@pbx.example.com
　→ SIP password: ＜パスワード＞
```

ファイルを編集する。

```:/etc/jitsi/jigasi/sip-communicator.properties
（最終行に追加）
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.AUTHORIZATION_NAME=6001
net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED=true
```

```
（JigasiとJicofoを再起動）
# systemctl stop jicofo
# systemctl stop jigasi
# systemctl start jigasi
# systemctl start jicofo
```

# どうだったか
クライアントからの接続構成としては、前回記事のPCからWebブラウザでJitsi Meetにアクセスする以降の手順と同じ。
以下の２つのクライアントがJitsi Meetの会議室に接続するという環境で検証。

・NAT経由でインターネットに接続したPCが、Webブラウザで接続
・スマホのSIPクライアント（MizuDroid）がAsterisk経由で接続

前回構成では、スマホ側からの音声はPC側でクリアに聞こえるのだが（一旦保留にして解除すると音声が聞こえだすという不思議動作だったが）、PC側の音声がどうしてもスマホ側には届かないという状態で、多分原因はJitsiサーバーがNAT経由でAsteriskに接続（Asterisk側はパブリックIPを接続口として公開）しているところが悪いんだろう、という事で今回の構成に至る。

では今回（Jitsi、Asteriskの２台とも直接インターネットのパブリックIPを持つ）はどうだったかというと、PC->スマホ(SIP)、スマホ(SIP)->PCのどちらから発声した音も、どちらへも届いて音は鳴った。それは素晴らしい。
しかし残念ながら、聞き取れたのだが、今度はPC側で発声した声にえらくノイズが乗ってしまい、スマホ側で聞こえる音質がすこぶる悪い、、！
PC<->PC間でどちらもWebブラウザで参加した場合の音質は普通なので、PC側のマイクに問題があるというわけではなく、Jitsi->AsteriskのSIP(RTP)伝送時にノイズが乗っている可能性が高い。

これはまあ、ちょっとこれ以上は追及する気にもならないので諦める感じである。うまくしたらJitsi MeetサーバーをNAT接続のPCで使う用のSIPクライアント（プロキシ）として使えたりするんじゃねーかと目論んではいたのだけど、まあこの音質ではだめだ。将来に期待。


（追記）サーバーがパブリックIPを直接持っているため、外からやってくるsshのログイン失敗やSIPのRegister失敗がうざい。
ufwで制限をかけようとするも、ちょっと動作が分からずSIPの接続を制限できなかったため、直接iptablesで制限することにした。

Jitsi Meetサーバー、Asteriskサーバーの両方で以下を実施。

```
（ufwを止めて、iptables-permanentをインストール）
# systemctl stop ufw
# systemctl disable ufw
# apt-get install iptables-persistent
```

iptablesのルールファイルは両サーバー以下で共通でいいだろう。
Ateriskサーバーは、Jitsi Meet、TwilioのSIPクライアントのみ受付けるようになる。

```:/etc/iptables/rules.v4
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -s localhost -j ACCEPT
-A INPUT -s ＜踏み台サーバーのIPアドレス＞ -j ACCEPT
-A INPUT -s ＜Jitsi MeetサーバーのIPアドレス＞ -j ACCEPT
-A INPUT -s ＜AsterikサーバーのIPアドレス＞ -j ACCEPT
-A INPUT -s 0.0.0.0/0 -d ＜Jitsi MeetサーバーのIPアドレス＞ -p tcp --dport 80 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -d ＜Jitsi MeetサーバーのIPアドレス＞ -p tcp --dport 443 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -d ＜Jitsi MeetサーバーのIPアドレス＞ -p tcp --dport 5349 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -d ＜Jitsi MeetサーバーのIPアドレス＞ -p udp --dport 3478 -j ACCEPT
-A INPUT -s 0.0.0.0/0 -d ＜Jitsi MeetサーバーのIPアドレス＞ -p udp --dport 10000 -j ACCEPT
COMMIT
```

```
# ip a
# iptables-restore < /etc/iptables/rules.v4
```