0から始める安全な自宅Minecraftサーバーの立て方

#概要
　某散財系youtuber様の影響でサーバーに興味を持ち、ちょうどPCが1台余ってるし（？）、私自身、ネットワーク関係には苦手意識があったのでMinecraftのサーバーを構築してみようと思い、行動に移してしまいました。
　何も考えずにサーバーを公開すると、悪い人がサーバーを乗っ取ったり、自宅の回線が使い物にならなくなったりするため、これらの対策が必要ですが、以外に大変だったので、それらをまとめておくことにしました。
　この記事は、OSI参照モデルが言えたり、Linuxのコマンドがある程度わかっていれば、サーバーの構築までを簡単にできるように書いていくつもりです。
#この記事での「安全」の定義
　サーバーを公開すること自体が危険な行為なのに、安全とはどういうことなのか、というキツイお言葉が飛んできそうなので、この記事で言う「安全」とは「サーバーが攻撃されても家庭のLAN上の機器に被害が及ばなこと」、「自宅のグローバルIPアドレスがばれて、回線が使い物にならなくなることの回避」です。
　なので、今回の構成では、DDOS攻撃を防げませんし、ソフトの自動更新のしくみも必要なので、さらに対策が必要です。
　個人的に、「これくらいはやっておいた方がいい」と思ってることを書いています。

#必要なもの

1. PC 1台
2. VPS 1契約
3. ルータ 2台（すでに家庭にある物も含めて） 

#大まかな作業の流れ
　まずは、二重ルーターの状態にし、疑似的にDMZを作成し、その中にUbuntuが入ったPCを配置し、Dockerを用いて、Minecraftサーバーを作成します。
　これにより、Minecraftサーバーに不正に侵入された場合に、家庭内のLANにまで被害が及ぶことを防ぐことができます。
　その後、VPS上でHAProxyの設定を行い、VPSから自宅サーバーにアクセスできるようにします。
　これにより、自宅に振られているIPアドレスを隠すことができ、また、面倒なDOSの対策をVPS側に押し付けることができます。（超迷惑らしいですが…）
　ネットワークの構成を多少変えるので、ネットワークを共有している方がいるならば、事前に、これから行うことの説明をしておきましょう。
　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033231/8bf3a4e9-fc96-9da5-098c-8ac39dc775f0.png)

#ルーターの設定について
　ルータのメーカーによって、設定の方法が違うので、ここに関しては各自で調べてください。（おそらく付属の説明書があるので、その通りにやれば大丈夫です。）
　ただし、古いルータがある場合は、そのルータ側にインターネットに接続するための設定が行われているので、自分で設定できないのであれば、以下の図のように古いルータに新しいルータを接続するようにしてください。
　今後、この「古いルータ」側を「DMZ側ルータ」と呼び、「新しいルータ」側を「内部ネットワーク側ルータ」と呼びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033231/923fbf94-0db4-34d6-13ad-cf85101ebb1a.png)

　ルータのファイアウォールがオフになってしまう場合があり、その場合は、必ずオンにしてください。
　ファームウェアも最新でない場合があるので、2つのルータで更新を必ず行ってください。
　2台のルータには、パスワードが設定できるので、必ず、8桁以上の強固なパスワードを設定してください。
　「内部ネットワーク側ルータ」に設定しているプライドIPアドレスのネットワーク部と「DMZ側ルータ」に設定しているプライベートIPアドレスのネットワーク部が一緒にならないように設定します。
　その後、「DMZ側ルータ」を使用している方に事情を説明し、「内部ネットワーク側ルータ」につないでもらってください。
　「内部ネットワーク側ルータ」への移行が完了して、もし、「DMZ側ルータ」にWi-Fiの機能がついているのならばOFFにしておきましょう。

　実は、[RTX1220](https://network.yamaha.com/products/routers/rtx1220/index)などの「高級ルータ」には、今回構築したDMZを1台で構築できる機能が存在しますが、高価ですし、上記とは比べ物にならないくらい、初心者には設定が難しすぎるので、おすすめはしません。
　ただし、「サーバー立てるだけでなく独自プラグインとか使いたい！」みたいな高度なことをしたい場合は、「高級ルータ」があると便利なので、中古品を買うといいかもしれません。（ほとんど企業の方が使った後なので、中古でも綺麗です。）

#自宅サーバー上の作業
##Dockerの設定
　MiectaftサーバーをDockerを用いて立ち上げるので、Dockerをインストールします。
　インストール方法は[公式サイト](https://docs.docker.com/engine/install/ubuntu/)をそのまま使用します。
　最初に古いバージョンのDockerをアンインストールします。 

```bash
sudo apt-get remove docker docker-engine docker.io containerd runc
```

　aptパッケージインデックスを更新し、パッケージをインストールして、HTTPS経由でリポジトリを使用できるようにします。

```bash
 sudo apt-get update
 sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
```
　Dockerの公式GPGキーを追加します。

```bash
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```

　次のコマンドを使用して、安定したリポジトリを設定します。

```bash
 echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

　aptパッケージインデックスを更新し、Docker Engineとcontainerdの最新バージョンをインストールします。

```bash
 sudo apt-get update
 sudo apt-get install docker-ce docker-ce-cli containerd.io
```

　hello-world イメージを実行して、DockerEngineが正しくインストールされていることを確認します。

```bash
sudo docker run hello-world
```

<a id="#ファイアウォールの設定"></a>
##ファイアウォールの設定
　基本的に不正な通信はルータではじかれるはずですが、一応、ufwでファイアウォールの設定も行っておきます。
 以下のコマンドで、ufwを起動し、特定の通信のみ受信を許可する設定にします。

```bash
sudo ufw enable
sudo ufw default DENY
```

　次にJava版のMinecraftの通信が入ってこれるように、以下のように25565番のポートを開けておきます。
　SSHを使うのであれば、この時点でSSHのポートもあけておいてください。

```bash
sudo ufw allow 25565
```

　設定を適応するため以下のコマンドを実行します。

```bash
sudo ufw reload
```

##IPアドレスの固定
　サーバーのIPアドレスを固定するには「/etc/netplan/99-netcfg.yaml」を以下のように設定します。
　ルーターによって設定する値が異なるため、設定する値については各自で調べてください。

```yaml
network:
    version: 2
    ethernets:
        enp0s3:
            addresses: [設定したいIPアドレス/サブネットマスク]
            gateway4: ゲートウェイ
            nameservers:
                addresses: [特殊な事情がない限りゲートウェイと同じ]
                search: []
            optional: true
```

　例えば、ゲートウェイが192.168.11.1で192.168.11.0のネットワークに192.168.11.10として設定したいのであれば、以下のように設定します。（小さい番号は「内部ネットワーク側ルータ」が取っている危険性があるので注意してください。）

```yaml
network:
    version: 2
    ethernets:
        enp0s3:
            addresses: [192.168.11.10/24]
            gateway4: 192.168.11.1
            nameservers:
                addresses: [192.168.11.1]
                search: []
            optional: true
```

##Minecraftサーバーを立てる

https://github.com/itzg/docker-minecraft-server

　上記のDockerイメージを使用して、マイクラサーバーを構築します。
　構築方法は以下のコマンドを実行するだけです。
　この状態で「内部ネットワーク」からアクセスできるようになっているはずなので確認してみましょう。

```bash
docker run -d -it -p 25565:25565 -e EULA=TRUE itzg/minecraft-server
```

　今回は問題になりませんが、Dockerはufwに黙って勝手にポートを開けるので、同じPC上で複数のサーバーを立てる場合は注意してください。

https://qiita.com/jqtype/items/9574ef74868b73323939

#VPS上での作業
　契約方法は、サービスによって異なるため、各自で調べてください。
　ここでは、Ubuntuが入ったVPSで共通する、最初にやっておかないといけない設定と、HAProxyの設定方法について説明します。
　
##VPSを契約したらやること
　まず最初に、以下のコマンドで、ソフトウェアの更新を行って再起動を行っておきましょう。

```bash
sudo apt update
sudo apt upgrade
sudo reboot
```
　
　次にSSHを公開鍵認証のみ接続できるようにし、ポート番号を変えます。
　公開鍵認証の設定は長くなってしまうので、以下のサイトを参考にしてください。

https://www.rem-system.com/sshd-pubkey/

　ポート番号を変更する方法は「cat /etc/ssh/sshd_config」の「Port 22」をコメントアウトし、以下のように設定したいポート番号を追加してください。


```bash:sshd_config
#Port 22
Port "設定したSSHのポート番号"
```

　変更を適応するために、sshdを再起動します。

```bash
sudo /etc/init.d/ssh restart
```


　次に「[ファイアウォールの設定](#ファイアウォールの設定)」と同じようにufwを設定します。
　ただし、先ほど設定したSSHのポートを閉じてしまうと、接続できなくなるので、同じ番号を設定しておきましょう。

```bash
sudo ufw allow "設定したSSHのポート番号"
```

##HAProxyの設定
　最初に、以下のコマンドで、HAProxyをダウンロードしてください。

```bash
sudo apt-get install haproxy
```

　「/etc/haproxy/haproxy.cfg」を以下の内容に書き換えます。
　以下の設定では、「Minecraftサーバーに同じIPで複数アクセスできない」、「短時間に何度もアクセスできない」、「50人まで接続できる」の3つの制限がかけられています。
　「”あなたの自宅に振られたIP”」には[IPアドレスを調べるサイト](https://www.cman.jp/network/support/go_access.cgi)などで調べた値を入力してください。
　動的IPの場合はIPアドレスが変わる危険性があるため、DDNSの設定を行い、「”あなたの自宅に振られたIP”」にDDNSで設定したアドレスを入力してください。

```bash:/etc/haproxy/haproxy.cfg
global
   #
    # 2) configure local2 events to go to the /var/log/haproxy.log
   #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #

    log         127.0.0.1 local2

    chroot      /etc/lib/haproxy
    pidfile     /etc/run/haproxy.pid
    #
    maxconn     50
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /etc/lib/haproxy/stats



#---------------------------------------------------------------------
# gateway server settings
#---------------------------------------------------------------------
defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend per_ip_connections
    stick-table type ip size 1m expire 1m store conn_cur,conn_rate(1m)


frontend fe_mcsv
    mode tcp
    bind *:25565
    option tcplog
    timeout client 1m
    tcp-request content track-sc0 src table per_ip_connections
    tcp-request content reject if { sc_conn_cur(0) gt 1 } || { sc_conn_rate(0) gt 5 }
    default_backend be_mcsv

backend be_mcsv
    mode tcp
    timeout server 1m
    option tcp-check
    server mcsv1 ”あなたの自宅に振られたIP”:25565 maxconn 50 check
```

　以下のコマンドでスペルチェックを行い、ちゃんと実行ができるかの確認を行います。
　ちゃんと動いていると、HAProxyが動き続けて、何も入力できない状態になってると思うので、Ctrl＋CでHAProxyを止めます。

```bash
haproxy -f /etc/haproxy/haproxy.cfg -c
haproxy -f /etc/haproxy/haproxy.cfg -db -V
```

　以下のコマンドでHAProxyをバックグラウンドで実行できるので、以下のコマンドを使用してHAProxyを実行します。

```bash
haproxy -f /etc/haproxy/haproxy.cfg -V
```

#ルーターのポート開放

　ポートを開放する前にDHCPリースができるルータの場合は、設定を行っておくことをお勧めします。
　これはIPが別の機器にとられることで、その機器にサーバーへの攻撃が降り注ぐ、という事故を予防するためです。
　ほぼ危険性はないですが念のため設定しておきます。

https://www.buffalo.jp/support/faq/detail/15917.html

　ポート開放の方法はメーカーによって異なるため、各自で調べてください。

https://www.buffalo.jp/support/faq/detail/8346.html

　ポートを開放するとVPSのIPアドレスでMinecraftのサーバーにアクセスできるはずです。

#まとめ
　Minecraftのサーバーを公開する上で最低限必要の設定方法について説明しました。
　ソフトウェアの自動更新は、Dockerの扱い方とかの説明が長くなるので省きました、DDOSの対策なんてそもそも個人ではできないので説明していません。
　そのため、大規模なサービスを展開したいという方は、この記事だけでなく、多くの方の意見を参考にしてください。
#目次
[RTX1220](https://network.yamaha.com/products/routers/rtx1220/index)：高額、高性能、高温耐性の3高そろったルーター。
[Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/)：Dockerのインストール方法。
[docker-minecraft-server](https://github.com/itzg/docker-minecraft-server)：Minecraftのサーバーを簡単に立てられる、すごいDockerイメージ。MODサーバーも簡単に立てられる。
[dockerとufwの設定が独立なせいで無駄にポートが開いてしまう件と、解決するためのdocker runオプションの記法について](https://qiita.com/jqtype/items/9574ef74868b73323939)：気を付けてないと、公開しちゃいけないやつまで公開しちゃうヤバい仕様。
[Windows10からLinuxへのSSHに安全性の高いSSH公開鍵認証を設定](https://www.rem-system.com/sshd-pubkey/)：これやっておかないと、サーバーを乗っ取られるのでやっておきましょう。
[多機能なロードバランサとして使える多機能プロクシサーバー「HAProxy」入門](https://knowledge.sakura.ad.jp/8078/)：HAProxyのインストールと起動方法。
[Application-Layer DDoS Attack Protection with HAProxy](https://www.haproxy.com/blog/application-layer-ddos-attack-protection-with-haproxy/)：HAProxyの設定で参考にしたサイト。
[DHCPサーバー機能を使用し、特定の端末に常に同じIPアドレスを割り当てる方法](https://www.buffalo.jp/support/faq/detail/15917.html)：buffaloにはDHCPリースという機能がついている。
[ポート開放の設定方法/アドレス変換の設定方法](https://www.buffalo.jp/support/faq/detail/8346.html)：buffaloのポート開放の方法、これであなたも逸般人。