Raspberry Pi 3にOpenVPNをインストールする(サーバー編)

Raspberry Pi 3にOpenVPNをインストールする手順。ほとんどの作業がroot権限を必要とするのでrootで作業する。カレントディレクトリは最初に/etc/openvpn/easy-rsaに移動して、そのままの前提なので作業途中で他に移動しないように注意する。各OSのVPNクライアントからの接続方法については以下の通りなので、必要に応じてご参照を。
サーバーで証明書や秘密鍵を作成する
必要なパッケージをインストールする
easy-rsaは依存関係があるのか指定しなくても自動的にインストールされた。easy-rsaのファイル一式をOpenVPN用としてOpenVPNディレクトリにコピーしておく。
$ su -
# apt-get install openvpn openssl
# cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa
環境設定ファイルを編集する
証明書作成のコマンドを実行した時の初期値となる内容を設定しておく。必須作業ではないけど、ここで設定しておくと何回も同じ内容を入力しなくてもEnterでスルー出来る。設定する内容はお好みで。KEY_SIZEはデフォルトで2048になってたけど、1024だったら2048にしておく。
# cd /etc/openvpn/easy-rsa
# nano vars
/etc/openvpn/easy-rsa/varsexport EASY_RSA="/etc/openvpn/easy-rsa/"

export KEY_COUNTRY="JP"
export KEY_PROVINCE="Tokyo"
export KEY_CITY="Chiyoda"
export KEY_ORG="MyOffice"
export KEY_EMAIL="admin@example.com"
export KEY_OU="VPNServer"

# Increase this to 2048 if you
# are paranoid.  This will slow
# down TLS negotiation performance
# as well as the one-time DH parms
# generation process.
export KEY_SIZE=2048
環境変数をシステムに反映する
上で設定した内容が有効になるように反映させる。
# source ./vars
証明書と鍵作成先ディレクトリを初期化する
証明書や鍵は/etc/openvpn/easy-rsa/keys/に作成されていく。
# ./clean-all
認証局証明書と秘密鍵を作成する
上で設定した内容がデフォルトで表示されるのでEnterで進める。
# ./build-ca
VPNサーバー証明書と秘密鍵を作成する
Enterで進めて以下の選択肢はyにする。
# ./build-key-server server
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
DHパラメータを作成する
これは作成に時間がかかるのでのんびりと待つ。多分、数十分かかる。公開鍵交換以外にOpenVPNはDH鍵交換と言うのを使っていてそれに必要なパラメータらしい。暗号化は奥が深いので難しいね。
# ./build-dh
TLS認証鍵を作成する
OpenVPNが送受信するすべてのパケットに署名を付加するための鍵だとか。署名が一致しないパケットは即座に破棄されるとのこと。これはオプションなので使わなくてもいいみたいだけど、ここでは使っておくことにした。
# openvpn --genkey --secret /etc/openvpn/easy-rsa/keys/ta.key
VPNクライアント証明書と秘密鍵を作成する
Enterで進めて以下の選択肢だけyにする。
# ./build-key client1
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
VPNクライアントを追加する場合は、その都度以下のように証明書と秘密鍵を新しく作成する。
VPNクライアント2台目のとき
# ./build-key client2

VPNクライアント3台目のとき
# ./build-key client3
rootを抜ける
そろそろrootでなくても大丈夫なので、ここでrootは抜けておく。
# exit
OpenVPNの設定ファイルを編集する
サンプルの設定ファイルは.gzで圧縮されているので解凍して、OpenVPNのディレクトリにコピーする。以下、コメントを除いた設定の部分のみの内容。詳細は環境に合わせて設定を煮詰めるという事で。
$ sudo gzip -d /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz
$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/server.conf
$ sudo nano /etc/openvpn/server.conf
/etc/openvpn/server.conf;local a.b.c.d

port 1194

;proto tcp
proto udp

;dev tap
dev tun

;dev-node MyTap

ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/server.crt
key /etc/openvpn/easy-rsa/keys/server.key  # This file should be kept secret

dh /etc/openvpn/easy-rsa/keys/dh2048.pem

server 10.8.0.0 255.255.255.0

ifconfig-pool-persist ipp.txt

;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100

;server-bridge

push "route 192.168.0.0 255.255.255.0"
;push "route 192.168.20.0 255.255.255.0"

;client-config-dir ccd
;route 192.168.40.128 255.255.255.248

;client-config-dir ccd
;route 10.9.0.0 255.255.255.252

;learn-address ./script

;push "redirect-gateway def1 bypass-dhcp"

;push "dhcp-option DNS 208.67.222.222"
;push "dhcp-option DNS 208.67.220.220"

client-to-client

;duplicate-cn

keepalive 10 120

tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0 # This file is secret

;cipher BF-CBC        # Blowfish (default)
;cipher AES-128-CBC   # AES
;cipher DES-EDE3-CBC  # Triple-DES
cipher AES-256-CBC

comp-lzo

;max-clients 100

user nobody
group nogroup

persist-key
persist-tun

status /var/log/openvpn-status.log

log /var/log/openvpn.log
log-append /var/log/openvpn.log

verb 3

;mute 20
ここまでの作業で出来たファイルのまとめ
例としてVPNクライアントを3台まで使用する場合の各ファイルの配置場所は以下の通り。ここでは認証局=VPNサーバー(Raspberry Pi 3)になる。
以下のファイルの格納場所 /etc/openvpn/easy-rsa/keys/
ファイル名 内容 VPNサーバー VPNクライアント1 VPNクライアント2 VPNクライアント3
ca.crt 認証局証明書
ca.key 認証局秘密鍵
server.crt VPNサーバ証明書
server.key VPNサーバ秘密鍵
dh2048.pem DHパラメータ
ta.key TLS認証鍵
client1.crt VPNクライアント1証明書
client1.key VPNクライアント1秘密鍵
client2.crt VPNクライアント2証明書
client2.key VPNクライアント2秘密鍵
client3.crt VPNクライアント3証明書
client3.key VPNクライアント3秘密鍵
Raspberry Pi 3の設定を変更する
ここではufwでファイヤーウォールを設定しているのでその例。使用するポートやプロトコルなど、上で設定したサーバーの設定ファイルの内容と合わせる。
OpenVPNで使用するポートを許可する
$ sudo ufw allow 1194/udp
IPフォワーディングを有効にする
以下の行のコメントを外す。
$ sudo nano /etc/ufw/sysctl.conf# Uncomment this to allow this host to route packets between interfaces
net/ipv4/ip_forward=1
ufwのルールを編集する
$ sudo nano /etc/ufw/before.rules
以下の内容をファイルの先頭に追加する。
# rules for NAT Table of iptables
# required line for ufw
*nat
:POSTROUTING ACCEPT [0:0]

# Forward traffic from OpenVPN through eth0.
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

# tell ufw to process the lines
COMMIT
以下の内容をファイルの最後の行のCOMMITの前に追加する。
-A ufw-before-input -i tun+ -j ACCEPT
-A ufw-before-output -i tun+ -j ACCEPT
-A ufw-before-forward -s 10.8.0.0/24 -j ACCEPT
-A ufw-before-forward -d 10.8.0.0/24 -j ACCEPT
ufwを再起動する
$ sudo ufw disable
$ sudo ufw enable
ポートが許可されているか確認する。
$ sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
1194/udp                   ALLOW       Anywhere
OpenVPNを再起動する
[ ok ]になるか確認する。
$ sudo /etc/init.d/openvpn restart
[ ok ] Restarting openvpn (via systemctl): openvpn.service.
OpenVPNサーバーの状態がactiveになっているか確認する。
$ sudo /etc/init.d/openvpn status
が、しかしこれだけでは実は起動していなかった。以下のコマンドで起動する。これでハマって随分と時間を取られてしまった。
$ sudo systemctl enable openvpn
ちなみに、そのときのVPNクライアントのログを見るとこういうエラーだった。そりゃまぁOpenVPNが完全に起動してなかったら認証も出来ないでしょうけども!疲れた。
TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
TLS Error: TLS handshake failed
VPNクライアント用の設定ファイルを作成する
以下の場所にあるサンプルファイルをコピーして、上で作った各種証明書ファイルと共にクライアントに持って行く。可能であればUSBメモリなど安全な方法で。もちろんそのUSBメモリの取り扱いには注意が必要。使った後は決してその辺に置き去りにせず、すぐにクイックフォーマットじゃない方法で初期化しておく。内容はサーバーに合わせて編集する。以下、コメントを除いた設定の部分のみの内容。なお、サンプルはclient.confになっているけど、OpenVPNクライアントの設定ファイルの拡張子は.ovpnなので、1台目のクライアントならclient1.ovpnとしておく。
/usr/share/doc/openvpn/examples/sample-config-files/client.confclient

;dev tap
dev tun

;dev-node MyTap

;proto tcp
proto udp

remote example.com 1194
;remote my-server-2 1194

;remote-random

resolv-retry infinite

nobind

user nobody
group nogroup

persist-key
persist-tun

;http-proxy-retry # retry on connection failures
;http-proxy [proxy server] [proxy port #]

;mute-replay-warnings

ca ca.crt
cert client1.crt
key client1.key

ns-cert-type server

tls-auth ta.key 1

cipher AES-256-CBC

comp-lzo

verb 3

;mute 20
ルーターの設定を行う
Raspberry Pi 3で行う作業はここまで。あとは忘れずにルーターのポート開放などを行っておく。NECのルーターなら 詳細設定 > ポートマッピング > NATエントリの画面で。それについては、環境によるので以下略。
    この記事で書かれている製品やソフトについて
  • Raspberry Pi 3 Model B
  • RASPBIAN JESSIE LITE(September 2016)
  • OpenVPN 2.3.4
  • easy-rsa 2.2.2-1