MacBook(ノートPC)のみで行うRaspberry Pi 4 VPNサーバー構築


# 概要
キーボードなしマウスなしのMacBookしかない状況で、Raspberry PiをVPNサーバとして構築してみました。
その時行った初期設定からVPNサーバー構築までの手順を書いていきます。  

尚ここでのRaspberry Pi はスターターキットで購入したものを利用します。  
OSのインストールも必要なく最低限必要なものも含まれているので、Raspberry Pi を動作させるために何が必要かわからない場合や、まずは動作確認したいという場合に適しています。  

## 背景
ネットワークの学習も兼ねて、Raspberry Piを利用した、VPNやSSHなどのサーバーを自宅に設置してみたいと考えていましたが、USB接続マウス、USB接続キーボードを持っていませんでした。  
購入するにしても、サーバーとして利用する予定なので、初期設定以降は利用する機会がなくなるだろうと思い、また余計なものを購入したくないので、気が進みません。  

そういうわけで、何とか手元にあるMacBookだけで動かすことができないかと模索していましたが、結論としては、スターターキットを利用することで、特に追加購入することなくVPNサーバー構築まで行うことができました。  

しかし知らなかったことも多く構築に苦心したので、この経験を無駄にしないように手順を残しておこうと思いました。  

### 利用したスターターキットの内容

- Raspberry Pi 4B (4GB)
- Raspberry Pi 用ケース
- MicroSD(OSプリインストール済)
- SDカードリーダー(USB-A/C)
- 電源アダプター
- ヒートシンク
- 冷却ファン
- HDMIケーブル

# 構築の過程
1. SSH接続設定
2. ラズパイ初期設定
3. SoftEther(VPNサーバー)インストール
2. VPNサーバー設定
3. ルータ設定

# 実施環境

- Raspberry Pi 本体 (Raspbian GNU/Linux 10)
- 電源アダプター
- MicroSDカード
- カードリーダー(必要に応じて)
- MacBookPro (Catalina)  

# SSH接続
まずはラズパイをMacBookで操作するため、SSH接続を行います。  

## 手順
1. SSH接続の設定をMicroSDに加える
2. Wi-Fi接続の設定をMicroSDに加える
3. SSH接続する

これだけでSSHまではできるようになります。  
ここまで手順は以下の記事を参考に進めました。  
[macしかない状況でRaspberry Piに接続してみた - Qiita](https://qiita.com/murs313/items/81757bf8bc74b6b76cdf)

### SSH接続用の設定
以下の手順で、MicroSDに設定を加えていきます。  

1. MicroSDをMacBookに挿入
2. `ssh`の名で空ファイル作成
3. `wpa_supplicant.conf`にWi-Fi設定記述  

順に見ていきます。まずはMicroSDをMacBookで操作します。
私の環境ではType-Cに変換する必要があったので、カードリーダーを利用しました。  

問題なくMicroSDを認識したら`/Volumes/boot/`というディレクトリが見つかると思います。
(もし認識しなかった場合は再起動してみます)  

その配下に`ssh`という空ファイルを作成します。
Raspberry Pi はデフォルトではSSHを受け付けていないようなのですが、このファイルによってそれを変更しています。  

```Shell
$ touch /Volumes/boot/ssh
```

次に、`wpa_supplicant.conf`を作成し、Wi-Fi用の設定を記述していきます。  
以下のダブルクォーテーションの中に、SSIDとパスワードを記入してください。  

```Shell:/Volumes/boot/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP
network={
	ssid="(SSID)"
	psk="(パスワード)"
}
```

以上で、設定は完了です。ラズパイにMicroSDを入れ替え、電源に繋ぎましょう。起動が始まります。

### SSH接続確認
電源を入れて暫くすると、Wi-Fiに接続された状態で起動するはずです。  
以下のコマンドで接続できるか確認します。  

```Shell
$ ssh pi@raspberrypi.local
```
パスワードには `raspberry`と入力しましょう。  
プロンプトが変わっていれば接続完了です。  

## 初期設定
接続が確認できたら追加で設定を加えます。  
今の状態では使いづらさやセキュリティの不安があるので、それを改善していきます。  
この部分は以下のサイトが分かりやすいと思います。  
[【Buster対応】Raspbianのインストールと最強の初期設定 | 純規の暇人趣味ブログ](https://jyn.jp/raspbian-setup/)  

まずはパッケージ更新を行いますが初めは15分程時間がかかりました。 
 
```Shell 
$ sudo apt update && sudo apt upgrade
```

無事完了したら以下の設定をしていきます。

- システム時間変更(日本時間に合わせる)
- locale変更(日本語を使えるようにする)
- IPアドレスの固定
- ユーザー名の変更
- ユーザーパスワードの変更
- ホスト名の変更
- SSHのセキュリティ関連
  - rootログインの禁止
  - パスワード認証の禁止
  - 公開鍵認証設定
  - ポートの変更
- ファイアウォール
- sudoにパスワードを強制

ここで行う設定は一部、`$ sudo raspi-config`コマンドで行うことができます。画面に従って設定を行っていくことができるので何を設定できるかが分かりやすいと思います。  
ただコマンド履歴に実行の過程を残したいので、今回はCLIで行っていきます。
  
#### 日本時間に合わせる
```Shell
$ sudo timedatectl set-timezone Asia/Tokyo
```
#### 日本語を有効にする
```Shell 
#en_USとja_JPを有効化する
$ sudo localedef -f UTF-8 -i en_US en_US
$ sudo localedef -f UTF-8 -i ja_JP ja_JP
#localeを変更する
$ sudo localectl set-locale LANG=en_US.utf8
```
#### IPアドレスを固定する
`$ sudo vi /etc/dhcpcd.conf`を実行して、ファイルを編集していきます。  
以下のIPアドレス部分を自分の環境に合わせて変更し、SSIDを入力してください。  

```Shell:/etc/dhcpcd.conf
... 
interface wlan0
ssid # ここにSSID
static ip_address=192.168.0.2/24 # ラズパイのIP
static routers=192.168.0.1 # ルータのIP
static domain_name_servers=192.168.0.1 # ルータと同じ
```
ついでにWi-Fiパスワードを暗号化しておきます。
`$ sudo wpa_passphrase (SSID) (パスワード)`と入力すると暗号化されたパスワードが出力されるので、それを以下のファイルに転記します。  

```Shell:/etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP
network={
	ssid="" # ここにSSID
	# psk= # 平文のパスワードは削除する
	psk= # ここに暗号化されたパスワード 
}
```
#### ユーザ名の変更
SSHで利用したように、デフォルトのユーザー名は"pi"となっています。  
これがそのままにしているとセキュリティ上好ましくないということで変更するわけですが、方法としては、"pi"を削除して新たなユーザーを作成する方法と、"pi"を残し、名前を変更して利用できるようにする方法があります。  

私は以下の記事を参考に、デフォルト名を変更する方を選びました。  
[[Raspbian]ユーザー名変更の個人的に「正しい」と思うやり方 | 純規の暇人趣味ブログ](https://jyn.jp/raspberrypi-username-change/) 
 
以下手順です。ユーザー名変更のため別のユーザを作成し、管理者権限で実行する必要があります。  

1. "pi"を操作するユーザーを作成
2. このユーザにsudo権限を与える
3. 自動ログインユーザー(pi)を削除する
4. このユーザーでログインし直す
5. "pi"ユーザー名を変更する
6. ホームディレクトリ、グループ名を変更する
7. 作成したユーザーを削除する

```Shell 
# 操作用ユーザー作成(例: tmp)
pi@raspberrypi:~ $ sudo adduser tmp 
# sudoグループに追加
pi@raspberrypi:~ $ sudo gpasswd -a tmp sudo 
# 自動ログインユーザー設定を削除する
# 以下コマンドの後、Boot Options -> Desktop / CLI -> Console の順に選択
pi@raspberrypi:~ $ sudo raspi-cofig
# ログインユーザーを変更する
pi@raspberrypi:~ $ exit
mac@local: $ ssh tmp@raspberrypi.local
# ユーザー名"pi"を変更する(例: pi2)
tmp@raspberrypi:~ $ sudo usermod -l pi2 pi 
# ホームディレクトリを更新する
tmp@raspberrypi:~ $ sudo usermod -d /home/pi2 -m pi2
# グループ名を更新する
tmp@raspberrypi:~ $ sudo groupmod -n pi2 pi
#更新したユーザー名でログイン後、ユーザー"tmp"を削除
pi2@raspberrypi:~ $ sudo userdel tmp
```

#### ユーザーパスワードの変更
ユーザー名と同様に、デフォルトのままではやはり問題があるので変更します。

```Shell 
$ passwd # 新しいパスワードに変更する
```

#### ホスト名の変更
`/etc/hostname`に現在の設定が記述されているのでこれを変更します。

```conf:/etc/hostname
# raspberrypiを削除
raspberrypi2 # 任意の名前に変更する
```

#### SSHのセキュリティ設定

デフォルトの状態でSSHを利用すると危険な部分があり、攻撃を許す恐れが高くなります。
そこでセキュリティを保つために、最低限行うべき設定をしていきます。

`$ sudo vi /etc/ssh/sshd_config`と入力すると既に設定が記述されているので、コメントアウトされている場合はコメントを外してから、以下のように変更します。

```conf:/etc/ssh/sshd_config
...
# ポートを変更する
Port 55555 # 49152番 - 65535番の範囲で任意の値
...
# rootログインを禁止する
PermitRootLogin no
...
# 公開鍵認証を利用する
PubkeyAuthentication yes
...
# パスワード認証を禁止する
PasswordAuthentication no
ChallengeResponseAuthentication no
```

ポートの変更は攻撃の可能性や頻度を減らすために簡単でそれなりに有効な対策です。
22番のままだと攻撃を試みる形跡が比較的多く確認できることから、変更したほうが懸命でしょう。

ルート権限を持ったユーザーはシステムに致命的なダメージを与える恐れがあるので、ルートログインはたとえ自分であっても許可しません。

パスワード認証は容易に突破される恐れがあるので禁止します。
代わりに公開鍵認証を利用するようにします。

**注意! 設定を有効化する前にラズパイに公開鍵を登録しておきましょう。**
これを忘れるとログインができなくなるので別のシェルで公開鍵認証できるか事前確認するのが安心です。

```Shell
# 公開鍵秘密鍵を生成(オプションは任意) '-C'でコメント、'-f'でファイル名指定
mac@local:~ $ ssh-keygen -C you@example.com -f raspberrypi
# 生成した公開鍵をラズパイに登録 '-i'は公開鍵のパス指定
mac@local:~ $ ssh-copy-id -i ~/.ssh/raspberrypi.pub pi2@raspberrypi2
# ログインを確認 '-i'は秘密鍵のパス
mac@local:~ $ ssh -i ~/.ssh/raspberrypi pi2@raspberrypi2
# 公開鍵でのログインを確認したら設定を反映させます。
pi2@raspberrypi2:~ $ sudo systemctl restart sshd
```

#### ファイアウォール
不要なポートを開放することによるセキュリティの穴をなくすため、ファイアウォールを設定します。
これには`ufw`コマンドを利用しますが、デフォルトでは使用できないのでまずはインストールから始めていきます。
インストールが終了したら以下の手順でファイアウォールを構築します。

1. 全てのポートを遮断する
2. 設定したportを許可する
3. 設定を有効化する

```Shell
$ sudo apt install ufw # インストール
$ sudo ufw default deny # 全てのポートを閉じる
$ sudo ufw allow 55555 # sshd_configで設定した値
$ sudo ufw enable # 設定を有効化する
$ sudo ufw status # 現在の設定を確認する
```

#### sudoコマンドにパスワード設定
今までsudoコマンドを利用するときにパスワードを入力しなくても実行できていました。
これは便利ではありますが同時にセキュリティのリスクを伴うものでもあります。サーバーを外部に公開する前にここの設定も修正しておきましょう。

`/etc/sudoers.d/010_pi-nopasswd`に設定が記述されているので、これをコメントアウトするか、またはファイルごと削除します。再起動後、設定が反映され、パスワードを要求されるようになるはずです。
再起動は`$ sudo reboot`で行います。

以上で、SSHのための最低限の設定が完了しました。ここでルータの設定を変更し、ポートマッピング(ポート開放)を行えば外部から接続できるようになります。  

[Raspberry Piに外部ネットワークからアクセスできる様にして携帯でペットを遠隔監視する方法 - Qiita](https://qiita.com/kinpira/items/c9e6dc910e8d96e8c19b)


# VPNサーバー接続
次にVPNサーバーの設定を行い、外部から接続できるようにしていきます。

参考サイト

- [7.3 Linux へのインストールと初期設定 - SoftEther VPN プロジェクト](https://ja.softether.org/4-docs/1-manual/7/7.3)  
- [Raspberry PiでVPNサーバ構築 | くらばのメモ帳](https://memo.kuraba.com/2019/12/raspberry-pi%E3%81%A7vpn%E3%82%B5%E3%83%BC%E3%83%90%E6%A7%8B%E7%AF%89/)
- [Linuxmania:SoftEtherでVPN環境を作ろう](https://www.linuxmania.jp/softether-vpn.html)
- [【Centos7】SoftEther Server 構築手順【L2TP/IPsec】 - Qiita](https://qiita.com/nobu-maple/items/61f51baa9965dbd6fb04#-vpn-server-%E3%81%AE%E3%83%98%E3%83%AB%E3%83%97%E7%A2%BA%E8%AA%8D)


## 手順
1. Softether インストール
2. 初期設定
3. ネットワーク設定 

公式サイトよりVPN server manager をインストールしてGUIで操作することもできますが、現時点では、macOS Catalinaで利用ができないようです。  

よって今回は、CLIで設定を行うことがてきる。`vpncmd`コマンドを利用しています。

## Softether インストール
まずはVPNサーバソフトウェアであるSoftetherをインストールしていきます。基本的に公式ドキュメントの手順に従います。

```Shell
# 公式サイトより現時点での最新版をダウンロード
$ wget https://github.com/SoftEtherVPN/SoftEtherVPN_Stable/releases/download/v4.34-9744-beta/softether-vpnserver-v4.34-9744-beta-2020.03.20-linux-arm_eabi-32bit.tar.gz
# インストール用パッケージファイルの展開
$ tar xzvf softether-vpnserver-*.tar.gz
# vpnserver 実行可能ファイルを生成
$ cd vpnserver && make
# 表示される利用規約を読んで同意する

# vpnserver ディレクトリの移動
$ sudo mv vpnserver /usr/local/vpnserver/
# 権限の変更
$ cd /usr/local/vpnserver
$ sudo chmod 600 *
$ sudo chmod 700 vpncmd
$ sudo chmod 700 vpnserver
```

## 初期設定
続けてサービスへの登録をしていきます。  
まず下記のようなスクリプトを作成します。

```conf:/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
WorkingDirectory=/usr/local/vpnserver/
Type=forking
RestartSec=3s

[Install]
WantedBy=multi-user.target
```
このスクリプトを有効にします。  

```Shell
# 権限の変更
$ sudo chmod 755 /etc/systemd/system/vpnserver.service
# サービスの設定ファイル読み込み
$ sudo systemctl daemon-reload
# サービスの自動起動を有効化
$ sudo systemctl enable vpnserver.service
# サービスを起動
$ sudo systemctl start vpnserver.service
```

## ネットワーク設定
以上でVPNサーバーとして起動している状態を作ることができましたがまだ接続はできないので、ネットワーク設定を行います。  

### 仮想ブリッジ
仮想ブリッジを設定しないとラズパイ上の他のサーバーに接続できなくなるようなので、これを導入します。  
必要なパッケージのインストール後、2つのファイルに設定を記述します。  

```Shell 
$ sudo apt install bridge-utils
```
```Shell:/etc/network/interfaces
...
auto br0
 iface br0 inet manual
 bridge_ports eth0
```

```Shell:/etc/dhcpcd.conf
... 
interface br0
static ip_address=192.168.0.xxx/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
```
```Shell
# インターフェースの再起動
$ sudo ifdown br0
$ sudo ifup br0
```
### VPN Server 設定
`$ sudo /usr/local/vpnserver/vpncmd`と入力すると、対話型の設定画面が表示されます。

```Shell
...
Select 1, 2 or 3: # 1: VPNserver 及び VPN bridge を選択
... 
# 設定するサーバーのIPとポートを指定
Hostname of IP Address of Destination: # 例: 192.168.0.2:443
... 
Specify Virtual Hub Name: # 指定せず空欄でreturn
... 
VPN server> # プロンプトが表示される
```
これで設定を加える準備が完了したので、実際に変更していきたいと思います。今回設定する箇所は以下の通りです。  

#### 設定項目
- ダイナミックDNSホスト名
- デフォルト仮想ハブ削除
- 新規仮想ハブ作成
- ユーザー作成
- DHCP
- IPsec
- ポート変更

```Shell
# 動的DNSホスト名の設定
VPN server> DynamicDnsSetHostname # 任意のホスト名
... 
# 仮想ハブを生成
VPN server> HubDelete DEFAULT # デフォルトハブ削除
VPN server> HubCreate vhub # 任意のハブ名(例: vhub) 
Password: # 仮想ハブのパスワード設定
... 
# ユーザ設定
VPN server> Hub vhub # ハブの操作に移る
VPN server/vhub> UserCreate # 仮想ハブユーザー作成
User Name: # ユーザー名、パスワードを設定
... 
VPN server/vhub> Hub # ハブ選択解除
 
# DHCP有効化
VPN server> DhcpGet
VPN server> DhcpEnable
VPN server> SecureNatEnable
...
#IPsec有効化
VPN server> IPsecEnable
Enable L2TP over IPsec Server Function:  yes 
Enable Raw L2TP Server Function: no
Enable EtherIP / L2TPv3 over IPsec Server Function: no
Pre Shared Key for IPsec: # 事前共有鍵の設定
Default Virtual HUB~: vhub
... 
# ポート変更
VPN server> ListenerCreate 55550 # 任意のポートを追加
# デフォルトポートの削除
VPN server> ListenerDelete 443 
VPN server> ListenerDelete 992
VPN server> ListenerDelete 1194
VPN server> ListenerDelete 5555

# サーバー再起動
VPN server> Reboot 
```

VPN server の設定はこれで完了です。  

### ファイアウォール設定
SSHの設定を行ったときと同様に、ファイアウォールの許可ポートを追加する必要があります。  

許可するのは、任意で設定した値(例: 55550)と、IPsecを利用するために必要なポート(UDP/500, UDP/4500)です。  

```Shell 
sudo ufw allow 55550 # VPNサーバーのポート番号
sudo ufw allow 500 # IPsec用
sudo ufw allow 4500 # IPsec用
sudo ufw enable # 設定を反映
```

最後に、ルータのポートマッピングで上記ポートをラズパイに転送する設定を行います。  

これで、外部からVPN接続できるはずですので、クライアントの端末で設定を行い、動作確認をしましょう。  

### Android での接続
動作確認はAndroid端末のみで行いました。
最後にその設定だけ記述します。  

端末の設定から、ネットワーク、VPNと進んでVPNの追加を行い、以下のように入力します。

- 名前: 任意の名前
- タイプ: L2TP/IPSec PSK
- サーバーアドレス: 動的DNSホスト名
- IPsec事前共有鍵: 仮想ハブ作成時の事前共有鍵
- 転送ルート: 0.0.0.0/0 
- ユーザー名: 仮想ハブユーザー名@仮想ハブ名
- パスワード: 仮想ハブユーザーのパスワード

残りは空欄にしておきます。これで完了です。  

# まとめ
以上により、ディスプレイ、キーボード、マウスがない状況でも、初めにMicroSDに設定さえ記述できれば、Raspberry Pi を操作しサーバーを起動させることができると確認できました。  

Raspberry Pi はそれ自体誰でも容易に扱えることを目指した製品とのことですが、今回のようなスターターキットを利用することで、導入へのハードルを更に数段階引き下げていると感じます。
一方で学習のためには物足りないという側面もあるとは思いますが、まずは少しでも触れてみることで実践のスタートを切ることができるという意味では良い選択だったと思いました。