極北別世界通信

2020-5 Blog Entry List

Apache OpenMeetings

世の中リモートワークばやりでございますが、捻くれ天邪鬼な性格の自分としてはすぐ「zoom使いたくねぇ」とか始まってしまうんですね。

いやまぁなんだかんだ言って仕事なら使うんですがね。

で、オープンソースのWeb会議ツールは敷居が高くてちょっと敬遠してたんですが、まぁせっかくだし流行りに乗って構築してみようかなと。

ただ、当方の場合最終的に「自宅で作ってDDNSでアドレス取ってNginxのリバースプロキシで振り分ける」という単なる構築以上に面倒くさい構成が待っているのでそこはちょっと辛いとこなんですが。

ちなみにNginxはまだ全然ド素人なので、いっかいちゃんと勉強しないといけませんな。

閑話休題

 

とりあえず単純に構築するなら、だいたいはオフィシャルサイトの手順に沿ってコマンドをつらつら入れていけば難しいことはありません。

ただ個々のコマンド、項目で何をやってるのかある程度理解してないとどうしようもないですが。

 まず今回の前提条件について記載します。

実運用上の最適スペックは確認してないのでそこはまた別途。

・環境

Windows上のvirtualbox仮想マシン

ディスク:100GB
メモリ:8GB
CPU:2

あとネットワークはブリッジ接続にしています。

・OS

今回はUbuntu18.04.4Serverにて構築しています。

 ・インストール

基本的には オフィシャルサイト の構築手順と、ググって見つけた こちらの「ろっひー ~ ITが気になる毎日」 さんのブログ記事「Ubuntu18.04 まっさらな環境にOpenMeetings5.0.0-M4をインストール」をほぼ丸パクリする勢いです。
大変お世話になりました。

・OSを最新化

$ sudo apt update; sudo apt -y dist-upgrade; sudo apt -y autoremove
$ sudo reboot

・各種ライブラリインストール

■OpenJavaのインストール

$ sudo apt install openjdk-11-jdk openjdk-11-jdk-headless
$ java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment (build 11.0.7+10-post-Ubuntu-2ubuntu218.04)
OpenJDK 64-Bit Server VM (build 11.0.7+10-post-Ubuntu-2ubuntu218.04, mixed mode, sharing)

■LibreOfficeのインストール

アップロード資料をPDFに変換するためのライブラリ

$ sudo apt install libreoffice

■ImageMagic,sox,ffmpegと関連ライブラリのインストール

イメージや動画の変換用のライブラリ

$ sudo apt install -y imagemagick libjpeg62 zlib1g-dev sox ffmpeg vlc

ImageMagickの設定ファイルを書き換える。
過去のGhostScriptバグの対策で変換ができなくしてあるので、その設定をコメントアウトして外しています。
参考

$ sudo vi etc/ImageMagick-6/policy.xml

上記ファイルの下のほう、★を付けた2行をコメントアウト

<!-- disable ghostscript format types -->
★ <!-- <policy domain="coder" rights="none" pattern="PS" /> -->
<policy domain="coder" rights="none" pattern="PS2" />
<policy domain="coder" rights="none" pattern="PS3" />
<policy domain="coder" rights="none" pattern="EPS" />
★ <!-- <policy domain="coder" rights="none" pattern="PDF" /> -->
<policy domain="coder" rights="none" pattern="XPS" />
</policymap>

■データベースのインストール

ここではMariaDBを使っているが他のDBでも構築は可能なようです。

$ sudo apt install mariadb-server
$ sudo mysql

MariaDB [(none)]> create database openmeetings default character set 'utf8';

MariaDB [(none)]> grant all privileges on openmeetings.* to 'openmeetings'@'localhost' identified by 'om_password' with grant option;

MariaDB [(none)]> quit

データベース openmeetings
ユーザー openmeetings
パスワード om_password

。。。すみません、丸パクリです。

■Kurento Media Serverのインストールと設定

基本的にはここを参考に。今最新Versionは6.13.2みたいですが、OpenMeetingsのオフィシャルと揃えています。

カメラ、マイク、録画、画面共有に必要なライブラリ。リポジトリのキーをインストールする

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83

リポジトリのソースファイルを新規作成。

sudo vi /etc/apt/sources.list.d/kurento-dev.list

中身は以下

deb [arch=amd64] http://ubuntu.openvidu.io/6.13.0 bionic kms6
deb [arch=amd64] http://mirror.yandex.ru/ubuntu/ bionic main restricted
deb [arch=amd64] http://mirror.yandex.ru/ubuntu/ bionic universe

Kurento Media Serverのインストール

$ sudo apt update
$ sudo apt install -y kurento-media-server

設定ファイルを変更。

sudo vi /etc/default/kurento-media-server

上記ファイル内の

DAEMON_USER="kurento" # User as whom Kurento Media Server will run

の行をコメントアウトし

DAEMON_USER="nobody"

を追加してサーバを走らせるユーザーを変更

サービスの登録と開始

$ sudo systemctl start kurento-media-server
$ sudo /lib/systemd/systemd-sysv-install enable kurento-media-server

■OpenMeetingsのインストール

ようやく本体のおでまし。
まずはダウンロード

$ wget https://downloads.apache.org/openmeetings/5.0.0-M4/bin/apache-openmeetings-5.0.0-M4.tar.gz

展開して配置 場所はこれまた丸パクで /usr/share/openmeetings としてます。

$ tar xzvf apache-openmeetings-5.0.0-M4.tar.gz
$ mv apache-openmeetings-5.0.0-M4 openmeetings
$ mkdir -p openmeetings/webapps/openmeetings/data/streams/{1,2,3,4,5,6,7,8,9,10,11,12,13,14}
$ mkdir -p openmeetings/webapps/openmeetings/data/streams/hibernate
$ sudo chmod -R 750 openmeetings/webapps/openmeetings/data/streams
$ sudo chown -R nobody:root openmeetings/
$ sudo mv openmeetings/ /usr/share/

mysql-connectorをダウンロードして配置

$ wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.20.tar.gz
$ sudo chown nobody:root mysql-connector-java-8.0.20/mysql-connector-java-8.0.20.jar
$ sudo mv mysql-connector-java-8.0.20/mysql-connector-java-8.0.20.jar /usr/share/openmeetings/webapps/openmeetings/WEB-INF/lib/

※バージョンが変わると適宜修正が必要になるのでご注意を。

■OpenMeetingsの自動起動スクリプトを作成

上手くいっているものをパクれの精神で、これまた丸パクリです。
OpenMeetingsのオフィシャルにも「tomcat3」という起動スクリプトがあるので、環境に合うように書き換えて使います。

sudo vi /etc/init.d/openmeetings

#!/bin/sh
### BEGIN INIT INFO
# Provides: Openmeetings
# Required-Start: mysql apache2 kurento-media-server
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Apache Openmeetings Service
# Description: Openmeetings provides video conferencing, instant messaging,
# white board, collaborative document editing and other groupware
# tools using API functions of the Red5 Streaming Server for
# Remoting and Streaming.
### END INIT INFO

# set the environment
# JAVA_OPTS=""
# CATALINA_OPTS=""
CATALINA_HOME=/usr/share/openmeetings
RUN_USER=nobody

# set TIME OUT values
# TIMELIMIT=10
# SLEEPTIME=40

# Function to wait until all Tomcat processes are killed
waitForTomcatToDie()
{
PROCESSES=`ps auxwww | grep $HOME | grep 'java' | grep 'tomcat' | grep -v 'grep'`
while [ ! -z "$PROCESSES" ] && [ $SECONDS -lt $TIMELIMIT ] && [ $TIMELIMIT -ne 0 ]; do
echo -n "."
sleep $SLEEPTIME
PROCESSES=`ps auxwww | grep $USER | grep 'java' | grep 'tomcat' | grep -v 'grep'`
done
echo ""
if [ ! -z "$PROCESSES" ]; then
PROCESS_ID=`echo $PROCESSES | awk '{ print $2 }'`
echo "Killing process: $PROCESS_ID"
kill -9 $PROCESS_ID
fi
}

# See how we were called.
case "$1" in
start)
$CATALINA_HOME/bin/startup.sh -u $RUN_USER -Dcatalina.base$CATALINA_BASE
;;
# debug)
# DEBUG_PORT=10001
## export JAVA_OPTS="${JAVA_OPTS} -Xdebug -Xrunjdwp:transport=dt_socket,address{DEBUG_PORT},server=y,suspend=n"
# $CATALINA_HOME/bin/startup.sh -Dcatalina.base{CATALINA_BASE}
# ;;
stop)
# $CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/shutdown.sh
waitForTomcatToDie
echo "...Tomcat stopped."
;;
restart)
$0 stop
echo "...Restarting..."
sleep 8
$0 start
;;
status)
status $PROG -p $PIDFILE
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
RETVAL=1
esac

exit $RETVAL

作成したファイルを有効化

$ sudo chmod 755 /etc/init.d/openmeetings
$ sudo systemctl daemon-reload
$ sudo /lib/systemd/systemd-sysv-install enable openmeetings
$ sudo systemctl start openmeetings

■OpenMeetingsのWeb UIによる初期設定

以降、WebUIでの設定となります。

 http://【インストールホスト】:5080

 

■アクセスすると次の画面が表示されるので[NEXT >]を押下。

Openmeetings_01

データベースユーザーとパスワードを入力し、[接続試験]をクリック。問題なければ[NEXT >]を押下。

Openmeetings_02

■最初のユーザーの生成。管理者アカウントですがうっかり会社のアドレス情報いれてしまったので見た目汚くて申し訳ない
けっこう制約があるようです。
(パスワードには大文字、小文字、数字、記号(!@#$%^&*][)を含める必要あり、名前と一緒だとNG等)

設定が済んだら[NEXT >]を押下

Openmeetings_03

■自己登録の拒否を設定して、管理者のみがユーザー追加をできるように設定。
 メール送信用のサーバも会社のサーバ名とか入れてるのでこれまた汚くて申し訳ないです。
 設定したら[NEXT >]を押下

■ライブラリが使えるかどうかの確認。
 [接続試験]のボタンを全部クリックしてOKであることを確認したら、[NEXT >]を押下

■このページはこのままで[NEXT >]を押下

■[FINISH]を押下してインストール。なおインストールボタンというものはない

■インストール処理が完了したら以下の画面になる。なお、「再起動」はしないでも一応ログイン後の画面には遷移した。

SSL設定は別途するので、この時点では

 http://【インストールホスト】:5080

に再接続する。

ログイン後の画面イメージ

・Nginxでのリバースプロキシ

この状態だと、ローカルPCからのアクセスしかできず、またSSL設定も行っていない状態です。

当方が試験用に自宅で構築しているものは、どれもNginxでのリバースプロキシを用いて、DDNSでIPアドレスを割り当てた各種サブドメインごとに異なる仮想マシンに転送する構成になっています。

また、その際にNginxでLet's EncryptのSSL通信を終端しています。

このOpenmeetingsも、リバースプロキシで外部から使おうとしたんですがまぁなかなかにハマりました。

そのへんも書いていこうと思います。

■構成

基本的に当方が自宅で外部向け公開(といっても、試験用のものが多いので頻繁に変わったりしてますが)は、以下のように構成している。

インターネット -> ルータ(80/443 ポート開放済み) -> Nginx(リバースプロキシ)  -> 各種サーバ

Let's Encryptの証明書発行のためのアクセスも受け付ける必要があるので80番ポートも開けているが、基本的なアクセスはすべてSSLで行っている。

常時5.6個ほどのドメインに対してDDNSで(同一)IPを割り当てて、URLアクセスをNginx でリバースプロキシしている。

これまでもShirasagi、Odoo、NextCloud、など毎回厄介そうなものをリバースプロキシで試験含め運用してきたが、今回はさらにハマった。
それでもググることで2、3日で答えが見つかるんだからネットはすごいなー(小並感)

簡単に言うと、以下設定をせずにリバースプロキシ経由でアクセスした場合、リクエスト元がhttpsなのに、NginxとTomcat間の接続はhttpなので、TomcatのCSRF対策によりBad Requestとして処理されてしまう、という問題が発生します。

海外のフォーラムなどでもこの問題にハマっている方は多いようでしたが、Openmeetings関係のところでは以下の設定は貼られてませんでした。

ただ、stackoverflowのこのページが引っ掛かりまして、結局Tomcat側の設定を変更しないとダメだというのが判明しました。難しいもんですね。

インターネット ->https-> Nginx ->http-> Openmeetings

となっているので、Openmeetings側で上記を検出し、リダイレクトの際にhttp通信であることからCSRFとしてはじかれる。

インターネット ->★https-> Nginx ->http-> Openmeetings

★の部分がhttpsであることをNginxからOpenmeetingsに通知するが、さらにそれを処理するための設定をTomcat側にも実施することで、プロキシ経由の通信であることが正常に処理され、問題なく通信ができるようになる。

■Nginx側の設定

本設定をnginxのconf.dディレクトリ配下に置いてnginx.confにIncludeさせてます。なのでhttpセクションは未記載。
ホスト名とIPアドレスは書き換えてます。

map $http_upgrade $connection_upgrade { ★1
default upgrade;
'' close;
}

server {
server_name openmeetings.mydomain.com;
listen 443 ssl;
listen [::]:443 ssl;

ssl_certificate /etc/letsencrypt/live/openmeetings.mydomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/openmeetings.mydomain.com/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;

access_log /var/log/nginx/openmeetings.access.log;

location / {
proxy_pass http://xxx.xxx.x.xxx:5080;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;     ★2
proxy_http_version 1.1;              ★2   
proxy_set_header Upgrade $http_upgrade;      ★2 
proxy_set_header Connection $connection_upgrade; ★2
}
}

★1
mapディレクティブを使って、$http_upgrade、$connection_upgradeを定義します。

$http_upgrade $connection_upgrade {

default upgrade;
'' close;
}

$http_upgradeの値が空('')の場合は、
$connection_upgrade = close

それ以外の場合は、
$connection_upgrade = upgrade

という処理になります。

 

SSL処理の部分は通常のものと変わらないので割愛させてください。

★2
proxy_set_headerで以下の値を指定します。
他のProxyヘッダももちろん必要ですが、以下は今回のOpenmeetingsのリバースプロキシ化に必要なので特記します。

proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;              
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

proxy_set_header X-Forwarded-Proto

を用いて、前段の通信がhttps通信であることを伝えます。

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

http1.1であることを明示的に宣言し、NginxのWebSocketプロキシ機能を有効にして、Upgradeヘッダとコネクションヘッダをプロキシからバックエンドに伝えます。

ただし、Openmeetingsの場合、Nginx側の設定だけではダメで、Tomcat(Openmeetings)側のSever.xmlファイルも変更する必要があります。

server.xmlの

<Host name="localhost" appBase="webapps"
unpackWARs="false" autoDeploy="true">

の後ろに以下を追記します。

<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for"
remoteIpProxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto"
/>

org.apache.catalina.valves.RemoteIpValve

というClassはProxy経由でのアクセスの際にリモートの情報を取得するためのものになります。

なお、上記は

remoteIpHeader="x-forwarded-for"
remoteIpProxiesHeader="x-forwarded-by"

を含めていますが、おそらく今回の設定の場合は

protocolHeader="x-forwarded-proto"

だけ設定されていれば問題ないはずです。

NginxとServer.xmlを変更し、両方とも再起動をかけて(サービス再起動でもいいとは思います)
上記設定ファイル上での「https://openmeetings.mydomain.com」

にアクセスすれば、Nginxでのリバースプロキシを介したOpenmeetingsへの接続ができているはずです。

 

0

直接的には

被害があるわけではないけど、やはり間接的には影響がありますなあ

新コロ関連でバタバタしてあっという間にいろいろやる時間がごっそり無くなっていました。

コミケも中止になってその後のことはまだまだ予断を許しませんし、どうなることやらですね。

また気を取り直していろいろやっていきたいです。

0