Raspberry Pi 2とSoftEther VPNを使ってVPNサーバーを構築しよう！

# かっこいいから、ただそれだけ
ちょっと前にRaspberry Pi2が発売されました。エンジニアとして仕事をし出してからはLinuxにも触れるようになり、設定の過程で詰まることは無いだろうと思い1つ買ってみたのですが、余ったHDDで簡易的なNASを作れちゃったりと便利ですよね。消費電力も少ないので常時稼働させてもお財布に優しいですし。

そして、今回は単にかっこいいからという理由だけで、ラズパイでVPNサーバーを構築して、外から接続して遊べるようにしてみました。

## ではやってみよう！
まずは、VPNサーバー用にラズパイのネットワーク構成を変更します。次に、SoftEther VPNのビルドを行い、起動スクリプトを用意します。最後に、管理ツールを使ってVPNサーバーのセットアップを行います。

### ネットワーク構成を変更する
まず大まかにどのような構成にするのかを確認していきます。SoftEtherではSoftEtherの中で作成する仮想ハブと、デバイスに認識されているNICをブリッジするのですが、直接LANとつながっているNICとブリッジを設定してしまうと、Linuxの仕様でNICに設定しているIPアドレスに接続することができず[^1]、ラズパイの上で展開しているSambaなどに接続することができなくなってしまいます。

そこで、物理NICの他にVPN用の仮想NIC（tapデバイス）を設定し、その2カ所をブリッジでつないで双方に行き来できるようにします。この状態で仮想NICとVPNサーバーをブリッジしてやると、問題なくSambaなどにも接続することができるようになります。

#### パッケージのインストール
まずは、複数のNICをブリッジするために必要なパッケージをインストールします。

```text:Terminal
sudo apt-get install bridge-utils
```

#### /etc/network/interfacesを編集する
次に、/etc/network/interfacesを編集してネットワークの構成を変えていきます。

```text:/etc/network/interfaces
# loopback
auto lo
iface lo inet loopback

# Ethernet port
auto eth0
iface eth0 inet manual

# Bridge interface
auto br0
iface br0 inet dhcp
bridge_ports eth0

#その他
allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
```

eth0とbr0をデフォルトの状態から変更していきます。eth0がラズパイに接続されている物理NICを指し、br0が新しく追加しているブリッジを指しています。

まず、eth0は初期状態でdhcpによって自動的にIPアドレスが振られるようになっていますが、橋渡しを行うブリッジにIPアドレスを振るようにするため```iface eth0 inet manual```に変更します。

次に、br0にIPアドレスを振るため、```iface br0 inet dhcp```に設定します。そして、```bridge_ports eth0```でeth0とブリッジを張るように設定します。当方の環境ではルーターのDHCPサーバーにて、IPアドレスを固定割り当てするようにしているため、今回はDHCPに設定していますが、環境に応じて任意のIPアドレスを使うよう手動設定することもできます。

なお、この段階では仮想NICをブリッジするように設定はしていませんが、tapデバイスはSoftEtherの起動する段階で毎回作成される都合上、起動スクリプトがブリッジをするように設定するので、ここでの設定は必要ありません。

### SoftEtherのインストール
次に、SoftEtherをインストールしていきます。[SoftEtherのダウンロードページ](http://www.softether-download.com/ja.aspx?product=softether)から最新のパッケージURLを確認して、```wget```でダウンロードします。CPUは"ARM EABI (32bit)"を選択しましょう。解凍してできたフォルダ```vpnserver```を```/usr/local/```に移動し```make```を実行します。ビルドの過程で自動的に環境チェックもやってくれます。最後にパーミッションを変更すれば完了です。

```bash:Terminal
cd /usr/local/vpnserver
chmod 600 *
chmod 700 vpncmd
chmod 700 vpnserver
```

### 起動スクリプトを用意する
次に、```/etc/init.d/vpnserver```へ起動スクリプトを用意します。起動スクリプトは[こちら](http://usicolog.nomaki.jp/engineering/raspberryPi/raspberryPi_VPN.html)を参考にさせていただきました。

```bash:/etc/init.d/vpnserver
#!/bin/sh
### BEGIN INIT INFO
# Provides:                 vpnserver
# Required-Start:           $local_fs $network
# Required-Stop:            $local_fs $network
# Default-Start:            2 3 4 5
# Default-Stop:             0 1 6
# Short-Description:        SoftEther VPN RTM
# Description:              Start vpnserver daemon SoftEther VPN Server
### END INIT INFO

DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/vpnserver

# tun/tapモジュールのロード
sudo modprobe tun

. /lib/lsb/init-functions
test -x $DAEMON || exit 0

case "$1" in
start)
sleep 3
log_daemon_msg "Starting SoftEther VPN Server" "vpnserver"
$DAEMON start >/dev/null 2>&1
touch $LOCK
log_end_msg 0
sleep 3

# SoftEther VPNで追加した仮想tapデバイス名を調べる
tap=`/sbin/ifconfig -a| awk '$1 ~ /^tap/ {print $1}'`
/sbin/brctl addif br0 $tap
;;

stop)
log_daemon_msg "Stopping SoftEther VPN Server" "vpnserver"
$DAEMON stop >/dev/null 2>&1
rm $LOCK
log_end_msg 0
sleep 2
;;

restart)
$DAEMON stop
sleep 2

$DAEMON start
sleep 5
# SoftEther VPNで追加した仮想tapデバイス名を調べる
tap=`/sbin/ifconfig -a| awk '$1 ~ /^tap/ {print $1}'`
/sbin/brctl addif br0 $tap
;;

status)
    if [ -e $LOCK ]
    then
        echo "vpnserver is running."
    else
        echo "vpnserver is not running."
    fi
;;
*)

echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0
```

ここで重要なのが、スクリプトの中でSoftEtherが起動する処理の前に```sudo modprobe tun```を追記することです。仮想NICであるtapデバイスを作成するためには特定のカーネルモジュールがロードされている必要があるのですが、どうやら初期状態のラズパイではこれが起動時にロードされないようになっています[^2]。そのため、こちらでモジュールをロードするように設定してやらないと、tapデバイスの追加に失敗します。

```lsmod```を実行してみて一覧に```tun```というモジュールがない場合、```sudo modprobe tun```を起動スクリプトに組み込んで、SoftEtherの起動時にモジュールがロードされるようにするか、```/etc/modules```を編集してtunを追加することで、OSの起動時にモジュールを自動でロードするようになります。

起動スクリプトの編集が終わったら、スクリプトに実行権限を与えて登録します。その後にラズパイを再起動しましょう。

```bash:Terminal
sudo chmod +x /etc/init.d/vpnserver
sudo update-rc.d vpnserver defaults
sudo reboot
```

### サーバーのセットアップを行う
最後にVPNサーバーのセットアップを行います。```vpncmd```を使ってセットアップしてもいいのですが、めんどくさそうなのでWindows向けに公開されているサーバーの管理マネージャを使いましょう。Macの人でも[EasyWine](http://mattintosh.hatenablog.com/entry/20140706/1404653173)を使えばexeファイルを実行できます。設定手順はすでに詳しく書かれている記事があるため、そちらを参考にして設定しましょう。

* [SoftEther VPN Server Manager for Windows](http://qiita.com/yoshi-naoyuki/items/aab1b3cc0a31dfc3557b)
* [VPNでiPhoneからラズパイに接続する](http://usicolog.nomaki.jp/engineering/raspberryPi/raspberryPi_VPN.html)

### ポートフォワードを設定する
あとは、ルーターからラズパイに対してポートフォワードを設定すれば、外部から接続することができるようになります。ラズパイに対してルーターから固定IPアドレスを振り出すように設定してから、そのIPアドレスに対してUDPの500番と4500番ポートをフォワードするように設定します。

これで、DDNSの設定画面で割り当てられたサブドメインを使って、外部からVPNサーバーにアクセスすることができるようになります。クライアントで接続情報を設定する際、通信プロトコルはL2TPを指定しましょう。


# 脚注
[^1]: [3.6 ローカルブリッジ - SoftEther VPN プロジェクト](http://ja.softether.org/4-docs/1-manual/3/3.6)
[^2]: [Raspberry Pi • View topic - Openvpn client ( Define TUN/TAP device )](https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=33865)