SoftEtherとAWSとstoneを使ってアパート内にあるRaspberry Pi 4Bのマイクラ鯖(Java版)を公開する

アパート内LAN(ポート開放できない)にあるRaspberry Piを電気代以外無料で公開できるか試したかったため検証がてら構築。
また、有線LANを一切使わない縛りを課してやっております。

**構築にあたり、[kei](https://qiita.com/kmikage)さんに知恵をお借りしました。感謝！**

# 使ったもの
- Windows 10 (Raspberry PiとAWSの管理用)
- Raspberry Pi 4B ([Raspberry Pi OS](https://www.raspberrypi.com/software/) 64bit版)
- [AWS EC2](https://aws.amazon.com/ec2/) (Debian)
- [SoftEther](https://ja.softether.org/)
- [stone](http://www.gcd.org/sengoku/stone/Welcome.ja.html) (version 2.4)
- Minecraft [server.jar](https://www.minecraft.net/download/server)
- (オプション)apache2 (ブラウザから接続チェックできる)

# 前提
- Raspberry Piのアドレスを固定(ルーター側で固定するほうが楽)してIPアドレスを把握しておく。
- Raspberry PiでMinecraftの`server.jar`をダウンロードして、`eura.txt`のfalseをtrueに変えて起動を確認する。
- AWSアカウントを作る。
- 「SoftEther VPN Server Manager」をWindowsまたはMacにインストールする。
- `sudo apt install screen`をRaspberry Piで実行して、screenをインストールしておく。
- (オプション)Raspberry Piで「apache2」をインストールして起動する。

# 構築

## (AWS) とりあえずAWS EC2インスタンスを作る
1. [EC2コンソール](https://console.aws.amazon.com/ec2/v2/)を開き、名前の横のリージョン名(写真では大阪)をクリックして所在地に一番近いリージョンを選ぶ(なおここからの説明は大阪にしたときの説明となるため東京など他のリージョンでは異なる可能性があります)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/ab391b1b-aa75-2a2f-579d-16cee1f98c17.png)
1. 右上の「インスタンスを起動」をクリックする。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/8dfd29a9-d68b-e964-44f3-058e9061b9f8.png)
1. 「名前とタグ」の「名前」を自由に入力する(minecraft等)
1. 「アプリケーションおよび OS イメージ (Amazon マシンイメージ)」でその他のLinuxを選ぶ(自動でDebianが選択されます)。(追記: Ubuntuでも可)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/eed9d947-6f9d-1e64-bfd4-761738801cf1.png)
1. 「インスタンスタイプ」で「t2.micro」を選ぶ。
1. 「キーペア(ログイン)」で「<font color="blue">新しいキーペアの作成</font>」をクリックし、「キーペア名」を自由に入力して「キーペアを作成」をクリックする。(WindowsからAWSを設定する場合は「.ppk」を選ぶ)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/5fc4e864-96e9-0106-b677-46e44079bdd3.png)
1. 「ネットワーク設定」の右にある「詳細」をクリックする。
    1. 「セキュリティグループルールを追加」 をIPv4だけ設定する場合を1回クリックする。
    1. 「セキュリティグループルール1」の「ソースタイプ」を「自分のIP」に変更する(「タイプ」を「すべてのトラフィック」にも設定してもいいかも...？)。
    1. 1以外の「セキュリティグループルール」の「タイプ」を「カスタムTCP」にする。
    1. 「セキュリティグループルール2」の「ポート範囲」を25565にする。
    1. 「セキュリティグループルール2」の「ソースタイプ」を「カスタム」にして、「0.0.0.0/0」(IPv6も対応させるなら「::/0」も)を登録する。
    1. (オプション)apache2を使う場合、ポート範囲を80に変えて登録する。
1. 「ストレージを設定」で「gp2」か「gp3」を選び、特に他のインスタンスを作る予定がなければ「30GB」に設定する。
1. (オプション)「高度な詳細」の「シャットダウン動作」を「停止」、「終了保護」を「有効化」にする。
1. 「インスタンスを起動」をクリックする。
1. 多分インスタンスに戻ってくるので、作ったインスタンスをクリックして下部に表示されているセキュリティタブのセキュリティグループをクリックする。
1. 右上の「アクション」をクリックして、アウトバウンドのルールを編集をクリックして、「ルール追加」をクリックする。
1. アウトバウンドルール2のタイプを「すべてのトラフィック」に変更して、送信先に「::/0」を選んで、ルールを保存をクリックする。

(追記)次の章で固定アドレスにする
## (AWS) 固定アドレスにする
**※取得した固定アドレスと連携したインスタンスが実行されていない、または連携されていないとお金がかかるらしいので注意！**
1. 画面左のなんかいっぱい英語が書いてあるところの「Network & Security」カテゴリ内の「Elastic IPs」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/aaab119f-8ba4-0ce7-7e21-8960b48e3031.png)
1. 右上の「Elastic IP アドレスを割り当てる」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/e5786877-8861-22ec-523a-a2d1dc0670f5.png)
1. 右下の「割り当て」をクリックする。
1. Elastic IP アドレスに戻ってくる。
1. 取得したアドレスが書いてある欄をクリックした後、右上の「アクション」をクリックして「Elastic IP アドレスの関連付け」をクリックする。
1. 「<font color=gray>インスタンスタイプを選択します</font>」をクリックして1つ前で作ったインスタンスを選ぶ。
1. 「<font color=gray>プライベートIPアドレスを選択します</font>」をクリックしてIPアドレスを選ぶ(1つしか出てこないはず)。
1. 「関連付ける」をクリックする。
## (AWS) インスタンスの起動
1. Elastic IPアドレス画面左のなんかいっぱい英語が書いてあるところの「Instances」カテゴリ内の「Instances」をクリックする。
1. 最初の方で作ったインスタンスをクリックして右上の「インスタンスの状態」をクリックして「インスタンスを開始」または「インスタンスの再起動」を行う。
## (AWS&Raspberry Pi) SoftEtherをそれぞれにインストールする
基本的に[公式ドキュメント](https://ja.softether.org/4-docs/1-manual/7/7.3)を見て設定してください。ライブラリのインストールを忘れずに！
[22.04(日本語Remix)](https://www.ubuntulinux.jp/download/ja-remix)だと、**make, gcc, openssl**を入れれば良かった気がする。
### AWS
1. [Tera Term](https://ja.osdn.net/projects/ttssh2/releases/)等SSH接続ができるソフトウェアを管理用PCにダウンロードする。
1. ソフトを開き、「ホスト名」にさっき作った固定IPアドレスを入力して「OK」をクリックする。
1. 「ユーザー名」にadmin、「パスフレーズ」は入力せず、下の「認証方式」から「RSA/DSA/ECDSA/ED25519鍵を使う」をクリックして秘密鍵横の「…」をクリックしてインスタンスを作ったときにダウンロードしたキーペアファイルを選択して「OK」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/eadd846b-2e18-c563-115e-e6a4132caf70.png)
1. 接続できるはず(接続できなかったらもう一度最初からやってみてください)。
1. この後は文章にすると長すぎるので省略(CPUにあったものをダウンロード&展開&フォルダ移動&chmodでの権限設定&vpnserver.service作成+サービスの起動+サービスの自動起動有効化をしておいてください(ググれば出てくる))
これとか見るとわかりやすいかもしれない
https://qiita.com/katonux/items/beeef8b88e4be6698a34
### Raspberry Pi
1. AWSと同じようにIPアドレスを入力して、「ユーザー名」(デフォルトはpi)と「パスフレーズ」を入力して「OK」をクリックする。
1. この後は文章にすると長すぎるので省ry(((AWSの5と同じ状況にしてください)
## (AWS&Raspberry Pi) SoftEtherをそれぞれ設定する
### 共通
(前準備) SoftEtherを起動するためのsystemdファイルを作成し、`sudo systemctl start vpnserver`と`sudo systemctl enable vpnserver`を実行する。
```systemd:sudo nano /etc/systemd/system/vpnserver.service
[Unit]
Description=SoftEther VPN Server
After=network.target network-online.target

[Service]
ExecStart=/usr/local/vpnserver/vpnserver start
ExecStop=/usr/local/vpnserver/vpnserver stop
# tapデバイスを作ったらExecStartPostのコメントを外す
#ExecStartPost=/bin/sleep 3
#ExecStartPost=/usr/bin/ip address add (IPアドレス)/24 dev tap_(tapデバイス名)
Type=forking
RestartSec=3s

[Install]
WantedBy=multi-user.target
```
IPアドレスの部分は
AWSなら`192.168.30.0`
Raspberry Piなら`192.168.30.10`
にしてください(tapデバイス名は後で触るのでそのままでいいです)。
1. Windowsで「SoftEther VPN Server Manager」を開き、新しく接続設定を加える。
    1. 「新しい接続設定」をクリックする。
    1. 「接続設定名」を分かりやすい名前に変える(Raspberry PiやAWS等)。
    1. 「ホスト名」にアドレスを一つ入力する。
    1. 「OK」をクリックする。
1. 接続先を選んで「接続」をクリックする。
1. 何も入力せずにOKをクリックする。
1. 管理者パスワードを設定する。
1. 「SoftEther VPN Server / Bridge 簡易セットアップ」画面が出たら右下の「閉じる」をクリックする。
1. 仮想HUB「DEFAULT」を消して、「仮想HUBの作成」をクリックして、「仮想HUB名」を決めて、管理用パスワードを設定後「OK」をクリックする。
1. 作った仮想HUBをダブルクリックしてその仮想HUBの管理画面を開く。
1. 「ユーザーの管理」をクリックして、「新規作成」をクリックして「ユーザー名」と「パスワード」を入力して「OK」をクリックする。
1. ユーザーの管理画面と仮想HUBの管理画面を閉じる。
1. 「ローカルブリッジ設定」をクリックする。
1. 仮想HUBの欄からさっき作った仮想HUB名を選んだ後、「新しいtapディバイスとのブリッジ接続」を選び、新しいtapデバイス名の欄に適当な名前を入力して「ローカルブリッジを追加」をクリックして状態が動作中になったことを確認してローカルブリッジ設定を閉じる。
1. 前準備で作った`vpnserver.service`の(tapデバイス名)にそれぞれ、自身のtapデバイス名を入れて`ExecStartPost`のコメントアウトを外す。
1. `sudo systemctl daemon-reload`と`sudo systemctl restart vpnserver`を実行する。
### AWS
1. 作った仮想HUBをダブルクリックして仮想HUBの管理を開き、「仮想NATおよび仮想DHCP機能(SecureNAT)の設定」をクリックする。
2. 「SecureNATの設定」をクリックしてドメイン名の欄を空白にし、「OK」をクリックする。
3. 「SecureNAT機能を有効にする」をクリックした後、閉じる。
4. 「ダイナミックDNS設定」をクリックして、接続先のホスト名を適当なものに変更して、「上記のDNSホスト名に変更する」をクリックする。
5. **DNS鍵を保存して、** 閉じる(ダイアログが出たら「はい」→「いいえ」の順でクリックする)。
6. SSHでログインし、stoneをインストールする。(Debian 12.0/Ubuntu 22.04以降はaptでインストールできます)
    -- ここからが手動インストールの説明 --
    1. [stone](http://www.gcd.org/sengoku/stone/Welcome.ja.html)をダウンロードする。
    2. ダウンロードしたファイルのある場所にcdで移動し、`tar -xvf stone-2.4.tar.gz`を実行する。
    3. 展開したフォルダに入る。
    4. `nano Makefile`を実行して「linux:」の欄の最後の方にある`-DUSE_EPOLL`と`$(FLAGS)"`の間に`-D_GNU_SOURCE`を入れて保存する。
    5. `make linux`を実行する。
    6. 作業フォルダを`/usr/local/bin`に移動させる。
    7. `sudo reboot`を実行する。
    7-1. もし正常に動かない場合は`chmod -x *`を実行してください。それでも動かない場合は[ここ](https://eldorado-of.info/wiki/linux/stone)を参考にしてください。
    -- ここまで --
    8. `sudo nano /usr/local/bin/stone-start.sh`を実行して以下のコマンドを入力して保存する(# Apacheとその下の1行はapache2入れている人向け)。
```bash:/usr/local/bin/stone-start.sh (手動インストール)
#!/bin/bash
# Apache
/usr/bin/screen -dm -S stone-http /usr/local/bin/stone-2.4/stone 192.168.30.10:80 80
# minecraft
/usr/bin/screen -dm -S stone-minecraft /usr/local/bin/stone-2.4/stone 192.168.30.10:25565 25565
```
```bash:/usr/local/bin/stone-start.sh (apt)
#!/bin/bash
# Apache
screen -dm -S stone-http stone 192.168.30.10:80 80
# minecraft
screen -dm -S stone-minecraft stone 192.168.30.10:25565 25565
```
※なお、ここで指定しているポートはTCPポートのみなので、他のサーバーを開く際にUDPポートを使いたい場合はポート番号の後ろに`/udp`をつけてください。
    9. `sudo chmod 700 /usr/local/bin/stone-start.sh`を実行する。
    10. `sudo nano /etc/systemd/system/stone.service`を実行して、以下の文章を入力する。
```systemd:/etc/systemd/system/stone.service
[Unit]
Description=PortRedirecter-
After=network-online.target
[Service]
ExecStart=/usr/local/bin/stone-start.sh
ExecStop=/usr/bin/pkill stone
Type=forking
RestartSec=3s
[Install]
WantedBy=multi-user.target
```
11.`sudo systemctl start stone`と`sudo systemctl enable stone`を実行する。
12. `sudo systemctl restart vpnserver`を実行する。

### Raspberry Pi
1. 作った仮想HUBをダブルクリックして仮想HUBの管理を開き、「カスケード接続の管理」をクリックしてカスケード接続を設定する。
    1. 「新規作成」をクリックして、新しい接続設定のプロパティを開く。
    1. 、接続設定名の欄を適当なものに変更する。
    1. ホスト名欄に、AWSの4で設定したDDNSホスト名を入力する。
    1. 仮想HUB名に、共通の5でAWSの方で作った仮想HUB名を入力する。
    1. ユーザー名欄とパスワード欄はAWSの仮想HUB内に作ったユーザーのユーザー名とパスワードを入力して、「OK」を押す。 
    1. 作った接続設定をクリックして、下の「オンライン」をクリックする。
1. SoftEther VPN Server Managerを閉じる。
1. `sudo systemctl restart vpnserver`を実行する。
---
以上のことが終わるとおそらくこのような形で接続されると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/1c82e662-c050-18ac-7837-84a0892de237.png)
# 実際に接続してみる
- apache2も実行している場合はブラウザの入力欄にAWSのSoftEtherで設定したDDNSホスト名を入力して、以下の画面が出れば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915128/5f816c1a-6053-cc97-bacc-59133b449254.png)
- minecraft serverのみ実行している場合はserver.jarを動かして、起動を確認した後、クライアント側でサーバーアドレスにAWSのSoftEtherで設定したDDNSホスト名を入力して接続できたら成功です。

できなかった場合、`sudo systemctl status vpnserver.service`を実行して正しく実行されているか確認したり、`ip a`を実行してtap_(tapデバイス名)に関連付けられたipアドレスが正しいか確認したりしてください(特に再起動時)。
# おわりに
　これまで説明してきた内容の他に、ラズベリーパイのスリープモードの無効化及びwifiのpower saveの無効化もすることをお勧めします。
　また、今回説明したサーバー公開システムを実現するために4日間付き合っていただいた、[kei](https://qiita.com/kmikage)さんに重ねてお礼申し上げます。