BigBlueButtonでWEB会議システムを構築＝NAT環境編＝

# はじめに

WebRTCを使ったWEB会議システムが無料で作れちゃうオープンソースWEB会議システム  [BigBlueButton](https://bigbluebutton.org/) のインストール方法をご紹介します。

BigBlueButton の以前のバージョンは Flash を使う仕様でしたが、執筆時点の最新バージョン `2.2` になってから WebRTC と HTML5 に対応したので、WebRTCに対応しているブラウザがあれば PC でも スマートフォン でも タブレット でも、デバイスを選ばずにWEB会議ができるようになっています。

実際には、BigBlueButton はWEB会議のプラットフォームを提供しているだけなので、別途フロントエンドとして Greenlight を導入し BigBlueButton はバックエンドとして利用することになります。

## BigBlueButton について

### 主な機能

- WEB会議・WEBセミナー
- グループチャット
- 共有メモ
- 資料アップロード
- ホワイトボード
- デスクトップ共有

### メリット

- WebRTC対応のブラウザさえあればつながる
- HTML5対応なのでスマホやタブレットでも使える

### デメリット

- skype や zoom のような専用クライアントを使うタイプのものより通話品質が劣る
- 画面レイアウトのカスタマイズ性が低い


# BigBlueButton の導入

ここから BigBlueButton 2.2 と Greenlight 2.5.6 をインストールしていきますが、ポイントを先に説明しておきます。

## BigBlueButton インストールのポイント

### インストールスクリプトを使ったほうが楽

BigBlueButton は多くのコンポーネントが相互連携して動いているので、それらを個別にインストールすることもできますが公式のインストールスクリプトを使ったほうが簡単です。

[公式インストールスクリプト](https://github.com/bigbluebutton/bbb-install) 

BigBlueButton をインストールするサーバーにグローバルIPアドレスが割り当てられている場合はインストールスクリプトを実行するだけで簡単に導入ができます。

### Firewall や NAT の内側にある場合はひと手間必要

AWS や Azure のような IaaS だと BigBlueButton をインストールするサーバーにグローバルIPアドレスが割り当てられているが Firewall や NAT の内側にあってサーバー本体はプライベートIPアドレスしか持っていない場合はいろいろと設定を変更したり追加したりしないと動きません。

ここでは `Firewall や NAT の内側にあってプライベートIPアドレスしか持っていない場合` について解説しますが、基本的には BigBlueButton のインストールスクリプトが自動的にインストールや設定変更をしてくれます。 もしインストールスクリプトでうまくいかない場合は公式ドキュメントの [Configure Firewall](http://docs.bigbluebutton.org/2.2/configure-firewall.html) に記載されているような設定変更を手動でやっていけばちゃんと動きます。

**(2020/5/21追記)**
先日会社で使っているNTTPCコミュニケーションズの[WEB ARENA VPSクラウド](https://web.arena.ne.jp/vps-cloud/)の「6G-SSDタイプ」で動かしてみたところ、5人目が会議に参加したあたりで **Blocked because of DoS Attack** というメッセージとともに通信が一時的に遮断されるという事態に遭遇。
クラウドで利用する際はそのあたりもチェックしないとダメっぽいです。

cf. [Web/FTPでアクセスしたら「Block because of DoS attack」と表示されました](https://help.arena.ne.jp/hc/ja/articles/360040569614-Web-FTP%E3%81%A7%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%97%E3%81%9F%E3%82%89-Block-because-of-DoS-attack-%E3%81%A8%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F-)



### IPv6は使わなくても有効にしておいたほうが楽

BigBlueButton をインストールするサーバーでは IPv6 は使わなくても有効にしておいたほうが楽です。
サーバーの仕様や大人の事情で IPv6 が使えない環境だとインストールスクリプトが中断してしまうので、そのあたりは [※IPv6が使えない場合※](https://qiita.com/hatayan1126/items/df167125c1dd888ed934#ipv6%E3%81%8C%E4%BD%BF%E3%81%88%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88) で補足します。


### グローバルIPアドレスとそれに対応するホスト名は決めておく

インストールする過程で https で通信できるようにするために無料のSSL証明書を生成する certbot が組み込まれます。 この certbot はSSL証明書を発行するサーバーから BigBlueButton のサーバーのグローバルIPアドレスとそれに対応するホスト名宛に HTTP で通信確認をしてからSSL証明書が発行されるので、DNSで名前解決ができていることと、Firewallで HTTP(TCP:80) と HTTPS(TCP:443) の通信を許可しておくことが必要になります。

## 必要なもの

- BigBlueButtonをインストールするサーバー(4Core/8GB以上、8Core/16GB推奨)
- OS は Ubuntu 16.04 のみ
- BigBlueButtonが使うグローバルIPアドレス1個
- グローバルIPアドレスに対応するホスト名
- インターネットアクセス環境
- LinC/LPICレベル2相当のLinux基礎知識

## インストール手順

以降、`EXTERNAL_IP_ADDRESS`の部分はグローバルIPアドレスに、`INTERNAL_IP_ADDRESS`の部分はプライベートIPアドレスに、`EXTERNAL_HOSTNAME`の部分はグローバルIPアドレスに対応するホスト名に読み替えてください。

### 1. Firewall に通信許可ルールを追加する

Firewall がある場合は BigBlueButton を動作させるために下記の通信を許可します。

| プロトコル | ポート番号     |
|-----------|---------------|
| TCP       | 80            |
| TCP       | 443           |
| UDP       | 16384 - 32768 |

この通信許可設定は、BigBlueButton のサーバー側はもちろんですが、クライアント側も BigBlueButton からの UDP 通信を許可するように設定しておいてください。


### 2. ダミーのIPアドレスを割り当てる

BigBlueButton のインストールスクリプトはグローバルIPアドレスを持っていないとエラーになるので、ローカルループバックインターフェース `lo` にダミーでグローバルIPアドレスを割り当てます。 

```:/etc/network/interfaces
 :
auto lo
iface lo inet loopback
    post-up ip addr add EXTERNAL_IP_ADDRESS/32 dev lo
    pre-down ip addr del EXTERNAL_IP_ADDRESS/32 dev lo
 :
```

**=(2020/5/20追記)=**
インストールが完了するとダミーのIPアドレスは `/lib/systemd/system/dummy-nic.service` にも書き込まれているので、サーバー移転などでグローバルIPアドレスが変更される場合は際はここも設定変更する。

```:
[Unit]
Description=Configure dummy NIC for FreeSWITCH
After=network.target

[Service]
ExecStart=/sbin/ip addr add EXTERNAL_IP_ADDRESS dev lo

[Install]
WantedBy=multi-user.target
```

### 3. インストールスクリプトをダウンロードする

インストールスクリプトをダウンロードして実行権限を付与します。

```console
root@bbb-svr:~#
root@bbb-svr:~# wget https://ubuntu.bigbluebutton.org/bbb-install.sh
root@bbb-svr:~# chmod +x bbb-install.sh
root@bbb-svr:~#
```

### 4. インストールスクリプトを実行する

インストールスクリプトを実行します。インストールが完了するまでに数十分はかかりますので気長に待ちます。

```console
root@bbb-svr:~# ./bbb-install.sh -v xenial-22 -s EXTERNAL_HOSTNAME -e root@EXTERNAL_HOSTNAME -g -c 173.194.77.127:19302
```

指定するオプションは以下の通りです。

| オプション                 | 内容                     |
|---------------------------|--------------------------|
| -v xenial-22              | BigBlueButtonのバージョン |
| -s EXTERNAL_HOSTNAME      | ホスト名                  |
| -e root@EXTERNAL_HOSTNAME | 管理者メールアドレス       |
| -g                        | Greenlight インストール   |
| -c 173.194.77.127:19302   | stunサーバーとポート番号(*) |
(*)stunサーバーはNAT環境では必須

stunサーバーについては下記サイトを参考にしてください。
- [【初心者向け】STUN/TURNサーバをざっくり解説してみた](https://qiita.com/okyk/items/a405f827e23cb9ef3bde)
- [壁を越えろ！WebRTCでNAT/Firewallを越えて通信しよう](https://qiita.com/okyk/items/a405f827e23cb9ef3bde)


### 5. インストール後の確認

インストールが完了したら `bbb-conf --status` ですべて **active** になっていれば OK 。
**faile** になっているサービスがあれば `systemctl status` や `journalctl -xe` などで個別に調査してください。

```console
root@bbb-svr:~#
root@bbb-svr:~# bbb-conf --status
nginx ―――――――――――――――――? [? - active]
freeswitch ――――――――――――? [? - active]
redis-server ――――――――――? [? - active]
bbb-apps-akka ―――――――――? [? - active]
bbb-transcode-akka ――――? [? - active]
bbb-fsesl-akka ――――――――? [? - active]
red5 ――――――――――――――――――? [? - active]
tomcat7 ―――――――――――――――? [? - active]
mongod ――――――――――――――――? [? - active]
bbb-html5 ―――――――――――――? [? - active]
bbb-webrtc-sfu ――――――――? [? - active]
kurento-media-server ――? [? - active]
etherpad ――――――――――――――? [? - active]
bbb-web ―――――――――――――――? [? - active]
root@bbb-svr:~#
```

インストール後の設定内容は `bbb-conf --check` で確認できます。

```console
root@bbb-svr:~#
root@bbb-svr:~# bbb-conf --check

BigBlueButton Server 2.2.10 (1916)
                    Kernel version: 4.15.0-20-generic
                      Distribution: Ubuntu 16.04.6 LTS (64-bit)
                            Memory: 4039 MB
                         CPU cores: 4

/usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties (bbb-web)
       bigbluebutton.web.serverURL: https://EXTERNAL_HOSTNAME
                defaultGuestPolicy: ALWAYS_ACCEPT
                 svgImagesRequired: true

/etc/nginx/sites-available/bigbluebutton (nginx)
                       server name: EXTERNAL_HOSTNAME
                              port: 80
                              port: 443 ssl
                    bbb-client dir: /var/www/bigbluebutton

/var/www/bigbluebutton/client/conf/config.xml (bbb-client)
                Port test (tunnel): rtmp://EXTERNAL_HOSTNAME
                              red5: EXTERNAL_HOSTNAME
              useWebrtcIfAvailable: true

/opt/freeswitch/etc/freeswitch/vars.xml (FreeSWITCH)
                       local_ip_v4: INTERNAL_IP_ADDRESS
                   external_rtp_ip: EXTERNAL_IP_ADDRESS
                   external_sip_ip: EXTERNAL_IP_ADDRESS

/opt/freeswitch/etc/freeswitch/sip_profiles/external.xml (FreeSWITCH)
                        ext-rtp-ip: $${external_rtp_ip}
                        ext-sip-ip: $${external_sip_ip}
                        ws-binding: :5066
                       wss-binding: EXTERNAL_IP_ADDRESS:7443

/usr/local/bigbluebutton/core/scripts/bigbluebutton.yml (record and playback)
                     playback_host: EXTERNAL_HOSTNAME
                 playback_protocol: https
                            ffmpeg: 4.2.2-1bbb1~ubuntu16.04

/etc/bigbluebutton/nginx/sip.nginx (sip.nginx)
                        proxy_pass: EXTERNAL_IP_ADDRESS

/usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml (Kurento SFU)
                        kurento.ip: EXTERNAL_IP_ADDRESS
                       kurento.url: ws://127.0.0.1:8888/kurento
                    kurento.sip_ip: INTERNAL_IP_ADDRESS
                    localIpAddress: INTERNAL_IP_ADDRESS
               recordScreenSharing: true
                     recordWebcams: true
                  codec_video_main: VP8
               codec_video_content: VP8

/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml (HTML5 client)
                             build: 908
                        kurentoUrl: wss://EXTERNAL_HOSTNAME/bbb-webrtc-sfu
                  enableListenOnly: true


# Potential problems described below
# IP does not match:
#                           IP from ifconfig: 172.17.0.1
#   /etc/nginx/sites-available/bigbluebutton: EXTERNAL_HOSTNAME

.
# Warning: The setting of INTERNAL_IP_ADDRESS for bbb.sip.app.ip in
#
#    /usr/share/red5/webapps/sip/WEB-INF/bigbluebutton-sip.properties
#
# does not match the local IP address (172.17.0.1).
# (This is OK if you've manually changed the values to an external
# FreeSWITCH server.)

# Warning: The setting of EXTERNAL_IP_ADDRESS for proxy_pass in
#
#    /etc/bigbluebutton/nginx/sip.nginx
#
# does not match the local IP address (172.17.0.1).
# (This is OK if you've manually changed the values)

# Warning: The setting of INTERNAL_IP_ADDRESS for local_ip_v4 in
#
#    /opt/freeswitch/etc/freeswitch/vars.xml
#
# does not match the local IP address (172.17.0.1).
# (This is OK if you've manually changed the values)

root@bbb-svr:~#
```


## Greenlight の導入

Greenlight は BigBlueButton のフロントエンドでユーザー管理、ミーティングルームの作成、録画管理などができます。

BigBlueButton はAPI連携を前提としたWEB会議システムのプラットフォームを提供するツールのようで、利用者はブラウザから Greenlight や [Moodle](https://moodle.org/)(オープンソースLMS) や [Wordpress](https://wordpress.org/)(オープンソースCMS) や [Mattermost](https://mattermost.com/)(オープンソースチャットツール)といったWEBフロントエンドを通じて利用します。

Greenlight は BigBlueButton のインストールスクリプトで `-g` オプションをつければ BigBlueButton と同時にインストールされます。 Greenlight の実態は Docker コンテナです。


### 6. 管理者アカウント作成

```console
root@bbb-svr:~#
root@bbb-svr:~# docker exec greenlight-v2 bundle exec rake admin:create
Account succesfully created.
Email: admin@example.com
Password: administrator
Role: admin
PLEASE CHANGE YOUR PASSWORD IMMEDIATELY
root@bbb-svr:~#
```

### 7. BigBlueButton と Greenlight の連携設定

BigBlueButton の API エンドポイントURLとシークレットを取得

```console
root@bbb-svr:~#
root@bbb-svr:~# bbb-conf --secret

    URL: https://EXTERNAL_HOSTNAME/bigbluebutton/
    Secret: **abcdefghijklmnopqrstuvwxyz1234567890**

    Link to the API-Mate:
    https://mconf.github.io/api-mate/#server=https://EXTERNAL_HOSTNAME/bigbluebutton/&sharedSecret=**abcdefghijklmnopqrstuvwxyz1234567890**

root@bbb-svr:~#
```

`bbb-conf --secret` で入手したURLとシークレットを `.env` に設定し、Greenlight を再起動する。

```console
root@bbb-svr:~#
root@bbb-svr:~# cd ~/greenlight
root@bbb-svr:~/greenlight# vi .env
　：
BIGBLUEBUTTON_ENDPOINT=https://EXTERNAL_HOSTNAME/bigbluebutton/
BIGBLUEBUTTON_SECRET=**abcdefghijklmnopqrstuvwxyz1234567890**
　：
root@bbb-svr:~/greenlight#
root@bbb-svr:~/greenlight#
root@bbb-svr:~/greenlight# docker-compose down
Stopping greenlight-v2   ... done
Stopping greenlight_db_1 ... done
Removing greenlight-v2   ... done
Removing greenlight_db_1 ... done
Removing network greenlight_default
root@bbb-svr:~/greenlight#
root@bbb-svr:~/greenlight#
root@bbb-svr:~/greenlight# docker-compose up -d
Creating network "greenlight_default" with the default driver
Creating greenlight_db_1 ... done
Creating greenlight-v2   ... done
root@bbb-svr:~/greenlight#

```

### 8. 動作確認

https://EXTERNAL_HOSTNAME/ にアクセスするとログイン画面になるので `admin@example.com` と `administrator` でログインできます。

ログイン後はユーザーごとに「Home Room」という会議室が割り当てられていますので、セッションを開始することでWEB会議が始められます。

会議室に接続後マイクとイヤホンの接続確認画面になりますが、ここで「1007: ICE negotiation failed」というエラーが発生することがよくあります。 `bbb-conf --status`ですべてのコンポーネントが **active** になっているようであればサーバー側かクライアント側の Firewall でUDP通信が遮断されていない可能性が高いのでチェックしてみてください。


# 環境によって対応が必要なもの

## ※IPv6が使えない場合※

### nginx 設定変更
IPv6が無効になっていたり、サーバーの仕様で使えない場合はインストール途中で Nginx が起動できずにインストールスクリプトが中断してしまうので、そのときは Nginx の設定ファイルでIPv6の設定をコメントアウトしてから再度インストールスクリプトを実行します。

```:/etc/nginx/sites-enabled/default
server {
        listen 80 default_server;
        listen [::]:80 default_server;
　　　　　↓ コメントアウト
        #listen [::]:80 default_server;

　：
```

```:/etc/nginx/sites-available/bigbluebutton
server {
  listen 80;
  listen [::]:80;
　　↓ コメントアウト
  #listen [::]:80;
  server_name EXTERNAL_HOSTNAME;

  listen 443 ssl;
  listen [::]:443 ssl;
　　↓ コメントアウト
  #listen [::]:443 ssl;
```

###  FreeSWITCH 設定変更
IPv6が無効になっていたり、サーバーの仕様で使えない場合はインストール途中で FreeSWITCH が起動できずにインストールスクリプトが中断してしまうので、そのときは FreeSWITCH の設定ファイルでIPv6の設定をコメントアウトし、IPv6関連の設定ファイルの名前を変更してから再度インストールスクリプトを実行します。

```:/opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml
　：
<param name="listen-ip" value="::"/>
　　　　　　　　　　　　　　　↓ 変更
<param name="listen-ip" value="127.0.0.1"/>
　：
```

IPv6に関連する設定ファイルの名前を変更

```
root@bbb-svr:~#
root@bbb-svr:~# mv /opt/freeswitch/etc/freeswitch/sip_profiles/internal-ipv6.xml /opt/freeswitch/etc/freeswitch/sip_profiles/internal-ipv6.xml_
root@bbb-svr:~# mv /opt/freeswitch/etc/freeswitch/sip_profiles/external-ipv6.xml /opt/freeswitch/etc/freeswitch/sip_profiles/external-ipv6.xml_
root@bbb-svr:~# ./bbb-install.sh -v xenial-22 -s EXTERNAL_HOSTNAME -e tsr-adm01@tsr-company.com -g -c 173.194.77.127:19302
root@bbb-svr:~#
```

### kurento-media-server 設定変更 

```:/etc/kurento/kurento.conf.json
　　　：
    "net": {
      "websocket": {
        "//ipv6": false,
　　　　　　↓ 変更
        "ipv6": false,
        "port": 8888,
　　　：
```

## ※LXDコンテナで動かしている場合※

### Greenlight がインストールできない

lxc コンテナで docker を動かすために `lxc launch` する際に `-c security.nesting=true` と `-c security.privileged=true` をつける。

```console
admin@xld-svr:~$
admin@xld-svr:~$ lxc launch images:ubuntu/16.04 bbb-svr -c security.nesting=true -c security.privileged=true
admin@xld-svr:~$
```

出来上がったコンテナで docker-ce をインストールして docker が使えることを確認してから BigBlueButton のインストールスクリプトを実行する。


### redis-server が起動しない

```:/etc/systemd/system/redis.service
　：
PrivateTmp=yes
PrivateDevice=yes
ProtectHome=yes
　↓ 変更
PrivateTmp=no
PrivateDevice=no
ProtectHome=no
　：
```

### FreeSwitch が起動しない

```:/lib/systemd/system/freeswitch.service
　：
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=60000
LimitSTACK=250000
LimitRTPRIO=infinity
LimitRTTIME=7000000
IOSchedulingClass=realtime
IOSchedulingPriority=2
CPUSchedulingPolicy=rr
CPUSchedulingPriority=89
　↓ 変更
#LimitCORE=infinity
#LimitNOFILE=100000
#LimitNPROC=60000
#LimitSTACK=250000
#LimitRTPRIO=infinity
#LimitRTTIME=7000000
#IOSchedulingClass=realtime
#IOSchedulingPriority=2
#CPUSchedulingPolicy=rr
#CPUSchedulingPriority=89
　：
```

[Running within an LXD Container](http://docs.bigbluebutton.org/2.2/troubleshooting.html#running-within-an-lxd-container)


# 補足
- 公式ドキュメントより
  - インストール：[Install](http://docs.bigbluebutton.org/2.2/install.html)
  - BigBlueButtonの内部構造： [Architecture ](http://docs.bigbluebutton.org/2.2/architecture.html) 
  - Firewall や NAT 環境での設定：[Configure Firewall](http://docs.bigbluebutton.org/2.2/configure-firewall.html)
  - トラブルシューティング：[Troubleshooting ](http://docs.bigbluebutton.org/2.2/troubleshooting.html)
  - 設定ファイルやログファイルの場所：[Configuration Files](https://docs.bigbluebutton.org/admin/configuration-files.html)
  - 通信要件：[Bandwidth Requirements](http://docs.bigbluebutton.org/support/faq.html#bandwidth-requirements)


# 最後に
本記事は新型コロナウイルス感染予防に貢献できるよう急いで執筆したので至らない部分があるかと思いますが、お気づきの点はコメントしていただければ幸いです。

コロナに負けないぞ！