Apache
minecraft
HTTPS
mod_proxy
Dynmap

【mod_proxy】Dynmapをhttpsで見る


やりたいこと

タイトル通り、Dynmapをhttpsで見たい。


前提

DynmapはMinecraftのサーバプラグインで、ゲームの内部状況をブラウザから確認できるようになる、人気のプラグインです。

【Dynmap】Overview

image.png

普通に実装するなら、ポート周りはこんな感じになります。

server-image.png

ソフトウェア
ポート番号
通信プロトコル

Apache
80, 443
http, https

Minecraft server
25565
独自プロトコル

Dynmap
8123
http

大雑把な図ですが、おおよそこのような関係になります。ポート番号はデフォルト値です。

問題はDynmapです。Dynmapは内部にスタンドアローンなWebサーバを内蔵していますが、Apacheとの競合を防ぐため、8123番ポートを利用します。そのため、サーバは80, 443, 25565の他に8123番ポートも開放しなければなりません。

他のポートは開放する他ありませんが、Dynmapのポートは開放したくありません。

もっといえば、httpsで通信したいです。

さて、どうしましょう。


リバースプロキシ(Reverse Proxy)を使う

リバースプロキシを使うことで解決できます。

リバースプロキシとは、外部ネットワークの接続に対し、何らかの処理を行い、内部サーバに引き渡す、いわば中継機能を果たす機器のことです。

とても分かりやすい図があったので、お借りしました。


image.png

【ITSakura】プロキシサーバとリバースプロキシサーバの違い


リバースプロキシが外部の受付役となっていることが分かりますね。今回、ハード的にサーバは1つですが、やることは同じです。

Apacheに対するリクエストはApacheに、Dynmapに対するリクエストはDynmapにそれぞれ内部で振り分けることで、開放ポートを減らすことができます。


リバースプロキシ適用

リバースプロキシを使った図が以下になります。(8123番ポートはイメージです)

reverse-proxy

リバースプロキシはApacheに備わっている機能なので、リバースプロキシはApache内部にあります。

リバースプロキシが受け取ったリクエストのうち、Dynmapに関するものだけ8123番ポートに向けて、リクエストを送ります。

Dynmapの応答はリバースプロキシを通じて、外部に送信されます。

このように、リバースプロキシを使うと内部サーバを隠蔽し、無用なポート開放を防ぐことができます。


リバースプロキシの実装

Apacheであれば、mod_proxyを使って簡単に実装できます。

今回はhttpsの通信に対して実装するので、VirtualHostを使います。(https化はすでにされているものとします)


ssl.conf

...

# スラッシュ補完(後述)
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} /dynmap$
RewriteRule /* %{REQUEST_URI}/ [R=301,L]
</IfModule>

# リバースプロキシ
<VirtualHost *:443>
ServerName sample.com:443
<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPass /dynmap http://localhost:8123
</IfModule>
...
</VirtualHost>


ProxyRequestsはフォワードプロキシをオンにするかどうかの記述なので、今回はoffにします。

ProxyPassの使い方は、


ProxyPass <外部からのリクエスト> <内部サーバ先>


です。非常にシンプルですね。

sample.com:443/dynmapへのリクエストは内部のlocalhost:8123に投げるようにしています。

これで、https://sample.com/dynmapにアクセスすると、Dynmapの画面が表示されます。

これでポートを開放をせず、外部からhttpsを使ってDynmapにアクセスすることができました。


補足:スラッシュ補完

リバースプロキシの前にmod_rewriteモジュールを使ってスラッシュ補完を行っています。

つまり、

https://sample.com/dynmaphttps://sample.com/dynmap/

に書き換えるということです。

スラッシュ補完をしないと、真っ白な画面が表示されてしまいます。

一方、https://sample.com/dynmap/https://sample.com/dynmap/#であれば、正しく表示されます。

ではなぜ、スラッシュ/を保管しなければならないのか。

これは推測なのですが、DynmapのWebサーバのルートディレクトリを明示する必要があるのでは?と考えています。

通常、ドメイン名のみでアクセスするとき、ブラウザはスラッシュを補完してサーバにリクエストを投げます。

URLバーがhttps://sample.comであっても実際はhttps:/sample.com/としてリクエストを送っているということです。

最後のスラッシュがルートを示しています。

ですが、今回の場合リバースプロキシを経由しているので、スラッシュ補完が行われません。

ディレクトリを一切指定されなかったWebサーバは、困って真っ白な画面を返したのではないでしょうか。

何か詳細あれば、教えていただきたく思います。


Minecraftサーバのポートもリバースプロキシ経由にできないのか?

ごもっともだと思います。

ですが、Minecraftが扱っているプロトコルはゲーム独自のものです。

mod_proxyモジュールでは対応できないプロトコルなので、今回の例のようにはいきません。

ですので、Dynmapのみリバースプロキシを適用することにしました。


まとめ

どうでしたか?

他のマルチサーバをのぞくと、http://xxxxxx:8123でアクセスしているものがいくつかあったので、記事にしてみました。

ポートを閉じるためにも、httpsで通信するためにも、リバースプロキシを使ってみてはいかがでしょうか。


参考リンク