Minecraftサーバー（Spigot）の謎通信の原因を突き止めた

Spigot[^1]を使い始めて3年近く経つのに、まだよくわかっていなかったという話。
[^1]: MinecraftのMODサーバーの一つ。url: https://www.spigotmc.org/

# 何が起きたか
セキュリティ強化などの目的でSpigotを動かしているサーバーの通信を調査していたところ、見知らぬコネクションが...

```
>> netstat -ntu
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
~中略~
tcp6       0      1 xx.xx.xx.xx:35260    198.27.66.94:80         ESTABLISHED
```

`198.27.66.94:80` と何やら通信している...

lsofでポートを使用しているプロセスを確認したところSpigotで間違いなし。

# `198.27.66.94` は何者？
## とりあえずcurl
```
>> curl 198.27.66.94:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx on Debian!</title>
~中略~
</html>
```
nginxのデフォルトページのようである。
何も情報なし。

## IP逆引き
```
>> nslookup 198.27.66.94
Server:         xx.xx.xx.xx
Address:        xx.xx.xx.xx

Non-authoritative answer:
94.66.27.198.in-addr.arpa       name = ns511765.ip-198-27-66.net.
```

うーむ。設定してないっぽい。

## プラグインが犯人だと踏み、遠回り
ダメ元でプラグインのjarをgrep

```
>> unzip -c '*.jar' | grep '198\.27\.66\.94'

28 archives were successfully processed.
>> unzip -c '*.jar' | grep 'ns511765\.ip\-198\-27\-66\.net'

28 archives were successfully processed.
```
何もわからず。

### 実はSpigot自身が犯人
最終手段として、プラグインを徐々に外していって犯人を特定しようとしたところ、そもそも何もプラグインを入れない状態でも通信が発生していることに気が付く。

## tcpdump
（最初にやっとけばよかった。）

```
>> tcpdump dst host 198.27.66.94 -A
~中略~
User-Agent: Java/1.8.0_191
Host: mcstats.org
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-type: application/x-www-form-urlencoded
Content-Length: 261
```

接続先のホスト名が判明。

```
>> nslookup mcstats.org
Server:         xx.xx.xx.xx
Address:        xx.xx.xx.xx

Non-authoritative answer:
Name:   mcstats.org
Address: 198.27.66.94
```

ということで、`198.27.66.94` の正体が半分くらい判明。

# コードの該当箇所の特定
Spigotサーバーそのものが犯人であることと、ホスト名がわかったところでコードの該当箇所を特定する。

BuildToolsで生成される中間ファイルをgrep

```
>> grep -r 'mcstats.org' .
./Spigot/CraftBukkit-Patches/0015-Metrics.patch:+    private static final String BASE_URL = "http://mcstats.org";
./Spigot/CraftBukkit-Patches/0015-Metrics.patch:+            configuration.options().header("http://mcstats.org").copyDefaults(true);
./Spigot/Spigot-Server/src/main/java/org/spigotmc/Metrics.java:    private static final String BASE_URL = "http://mcstats.org";
./Spigot/Spigot-Server/src/main/java/org/spigotmc/Metrics.java:            configuration.options().header("http://mcstats.org").copyDefaults(true);
Binary file ./Spigot/Spigot-Server/target/classes/org/spigotmc/Metrics.class matches
```

`Spigot/Spigot-Server/src/main/java/org/spigotmc/Metrics.java` に関係する記述があるようだ。

該当箇所のパッチの内容はここで確認できる。
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/browse/CraftBukkit-Patches/0015-Metrics.patch?at=refs%2Fheads%2Fversion%2F1.12.2

ちなみに、今回使用したSpigotサーバーのバージョンは1.12.2であるが、1.13にアップデートされる際にホスト名が `mcstats.org` から `mcstats.spigotmc.org` に変更に（そしてhttpからhttpsに）なったようである。コミットはここで確認できる。
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/commits/ed1cec9ae9ee07f1b51bdda14dfe14b40e92c9ed#CraftBukkit-Patches/0014-Metrics.patch

# このコードは何をしているのか
統計情報送信に使われているようである。
現在は、何かのサービスとしては機能していないようである。

## かつての名残と将来に向けた準備
パッチの中身を見てもらえばわかると思うが、サーバーのOSの情報、Spigotのバージョン、プレイヤー数などの統計情報が上で示したホストへ送信されるようになっている。

かつて、 `mcstats.org` には、Minecraftサーバーの情報を収集しGUIで表示するサービスが運営されていたようである。現在はbStats ( https://bstats.org/ ) が代替のサービスになっている。
https://www.spigotmc.org/threads/mcstats-down.193444/

1.13へのアップデートの際に、ホスト名が `mcstats.org` から `mcstats.spigotmc.org` に変更されたのは、将来的に使用する考えがあるからだそうだ。
https://hub.spigotmc.org/jira/browse/SPIGOT-4203

# オプトアウト
現在使用されていない機能であるため、不要な通信が発生するのは避けたいところ。
`plugins/PluginMetrics/config.yml` のopt-outをtrueにすると、この機能をoffにできる。

```conf:plugins/PluginMetrics/config.yml
# http://mcstats.org
# opt-out: false
opt-out: true
guid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
debug: false
```
# まとめ
3年近くもSpigotサーバーを触っていたら、それくらい知っとけよという話でした。
（一方で、このこと知らない人意外と多いんじゃないかな？と考えてみたり...）

原因がわかってスッキリ。今日はよく眠れそうです。