VPSをゲートウェイにして自宅サーバーで443番ポートを公開しhttpsを利用する

## はじめに

この記事では自宅LAN内に設置したUbuntu ServerにWEBサーバーを構築し、VPSとの間にVPNを構築して、VPSを経由してインターネットに公開する方法を紹介する。

## この記事が刺さるであろう人

自宅に設置したサーバーを公開したい人でかつ以下の条件に当てはまる人

- 自宅回線がv6プラスで443番ポートを開放できない
- 自宅回線が非固定IP
- 自宅のポートを開放したくない

## 最終形のイメージ

![最終形のイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275790/a4e87966-8e9e-f552-bdde-d92aeed37a46.png)

## 筆者のモチベーション

ネット回線の遅さにうんざりしていたが、v6プラスを導入したことで速度は出るようになった。
しかし、速度と引き換えに公開できるポートが限られてしまい、一般的なポートが使えなくなってしまった。
WEBサーバーを公開するにあたって443ポートが使えないので、別のポートを使用してhttpsしようとするが、Let's Encryptが使えなかったり、開発が煩雑になってしまったり、問題が尽きない。
そこでこの問題を解消するためにこの記事で紹介する環境を構築した。

## 環境

- 自宅サーバー
    - [Raspberry Pi 4 Model B 4GB](https://www.amazon.co.jp/dp/B08GSG1KYB/ref=cm_sw_r_li_dp_9v1RFbT2J9PTB)
    - Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-1021-raspi aarch64)
- VPS
    - [Ablenet VPS](https://www.ablenet.jp/vps/)のV0 SSDプラン
        - 月713円(税込)で200Mbpsの回線を転送量無制限で使えるのでおすすめ（ステマではない）
    - Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-52-generic x86_64)

## 構築

### 自宅サーバーの構築

自宅にサーバーとして動作するマシン（ラズパイでも本格サーバーでも仮想マシンでも良い）を用意し、OSインストールを完了させる。
ここではRaspberry Pi 4 Model B 4GB上でUbuntu Server 20.04が動作していることを前提とする。

### VPSのセットアップ

お好みのVPSを契約し、OSインストールを完了させる。
ここではUbuntu Server 20.04が動作し、固定IPを持っていて、デフォルトのFQDNが付与されていることを前提とする。

### WireGuardのセットアップ

[WireGuard](https://www.wireguard.com/) とは、比較的新しいVPN技術で、OpenVPNに比べてシンプルかつ高速である。
また、OpenVPNクライアントはDockerのネットワーク構築と干渉しdocker-composeが動作しなくなるが、WireGuardにはそのような問題がないので都合が良い。

[WireGuardを使って爆速でVPNトンネルを構築する(Qiita)](https://qiita.com/kniwase/items/52d45d618edccbb914ca) を参考にWireGuardをセットアップする。
ここではVPSから自宅サーバーへは `10.0.0.2` で接続できる状態になっていることを前提をする。

### VPSから自宅サーバーへのポートフォワードのセットアップ

VPSの443番ポートに来た通信を自宅サーバーへの443番ポートに転送するように設定する。
ポートフォワードはiptablesやufwを使って行うのがセオリーなのだろうが、ここでは [SSLH](https://github.com/yrutschle/sslh) を使って転送することにする。

[SSLHでHTTPS, SSH, OpenVPNを443番ポートに共存させる(Qiita)](https://qiita.com/kniwase/items/9fb294c8d7eadee4aebf) を参考にSSLHをセットアップする。
ここではVPSの443番ポートへのSSL通信を、自宅サーバーの443番ポート（つまり `10.0.0.2:443` ）に転送するように設定する。
SSHやOpenVPN等はお好みで設定する。

```:VPS上の/etc/default/sslh
RUN=yes
DAEMON=/usr/sbin/sslh
DAEMON_OPTS="--user sslh --listen [VPSのIPアドレス]:443 --ssl 10.0.0.2:443 (その他の設定) --pidfile /var/run/sslh/sslh.pid"
```

### ファイアウォールの導入

ファイアウォールを導入し、443番ポートとSSHのポート以外をブロックするように設定する。
ここではufwを使用し、自宅サーバー、VPSともに同じ設定で導入する前提で進める。

```bash:ufwのインストールと設定
# ufwのインストール
sudo apt update
sudo apt install ufw
# ufwの設定
sudo ufw allow 443/tcp
sudo ufw allow [SSHのポート]/tcp
sudo ufw ebable
sudo ufw reload
```

### SSL証明書の発行

Let's Encryptを使って無料でSSL証明書を発行する。
SSL証明書を発行する際には、VPSのFQDNを指定する。
具体的な方法は様々な記事で紹介されているので、ここでは省くこととにする。

### WEBサーバーのセットアップ

自宅サーバー上にWEBサーバーをセットアップする。
NginxやApacheなどを使い、443番ポートでsslを受け付ける設定にする。
具体的な方法は様々な記事で紹介されているので、こちらもここでは省くこととにする。

### 疎通確認

WEBブラウザを開き、 `https://[VPSのFQDN]` でアクセスして正しくレスポンスが返ってくれば完了。

## 言い訳コーナー

そもそもの話、なぜこのような面倒な構成になったのか、突っ込まれそうな点を先に言い訳しておく。

### VPSを使うならVPSでWEBサーバーを動かせばいいのでは

その通りある。
しかし、筆者が作りたいものはは自宅LAN内にある別のデバイスと通信する必要があるので、なんとしても自宅にサーバーを設置したい。

### IPv4 PPPoEとv6プラスを併用すればいいのでは

その通りある。
しかし、残念ながら筆者が契約しているプロバイダ（GMOとくとくBB ドコモ光）ではv6プラスとIPv4 PPPoEを併用することができない。
仮にできたとしても、筆者が使用しているルーターにはデュアルWANもPPPoEパススルーもないのでルーターの買い替えが必要になる。

### v6プラスをやめてIPv4 PPPoEに戻せばいいのでは

その通りある。
しかし、以前のあの遅さにはもう耐えられない...
1Mbps以下って何だよ...
格安SIMの方が場合によってはずっと速いぞ...

### 非固定IPなだけなら、固定IPオプションを付けたりDDNSを設定すればいいのでは

その通りある。
しかし、固定IPオプションやDDNSサービスには利用料がかかる場合が多く、無料DDNSサービスには制限がつきものだ。
その点VPSなら月1000円以下で固定IPが使えるし、デフォルトのFQDNを付与してくれる。
デフォルトのFQDNは多少不格好かもしれないが、趣味で使う程度なら問題はないはずだ。

### VPSにWEBサーバーを置いて、リバースプロキシしてもよいのでは

その通りある。
しかし、自宅LAN内の他のデバイスからアクセスするためにわざわざインターネットとVPSとVPNを経由させるのは無駄なので、自宅サーバー側に設置した。

### その他

他にもご指摘、ご提案などがあれば（優しく）ご教示くださると幸いです。

## おわり

この記事では恵まれない環境でも自宅サーバーを設置してインターネットに公開する方法を紹介した。
みなさんの自由な開発活動の助けになると嬉しい。