Ubuntu Server 14.04をVPNサーバーにしてみた。

折角家に自宅サーバーがあるので、VPNサーバー機能組み込んでみました。

# 目的
* 勉強も兼ねて自宅のネットワークを外で使いたい。
* STBの番組（WA-7000）で撮った番組を外で見たい。
* MarkdownとQiitaの練習

# 結果
* うまい事ルーティング出来て接続できた。
* STBの番組が見れない！（WA-7000自体認識されなかった。 同じネットワーク下として認識されてないのかも？)

# 方法
## 必要なソフトを用意
次をaptでgetする
`sudo apt-get install openvpn libssl-dev openssl easy-rsa`

## 認証モノを発行する
aptでgetした後スーパーユーザーに切り替え、
`make-cadir /etc/openvpn/easy-rsa`
でRSAディレクトリを作成した後に、varsを修正する。
だいたいは64行目以降のこの部分を修正するだけで十分だと思う。

```lang:vars
export KEY_COUNTRY="(国)"
export KEY_PROVINCE="(都市)"
export KEY_CITY="(街)"
export KEY_ORG="(組織名)"
export KEY_EMAIL="(メールアドレス)"
export KEY_OU="(組織単位らしいので適当に)"
```

先ほどのvarsをソースにし、一旦綺麗にした後にCAを作成。
`source vars && ./clean-all && ./build-ca`
varsの値が読み込まれているはずなので、基本Enter連打で大丈夫。
次にpkitoolを通す。
`./pkitool --initca && ./pkitool --server server`

次にサーバー用の鍵を生成する
`./build-key-server (サーバー用鍵の名前。サーバー名でいいかも？)`
ここまで出来たら共有鍵を生成する
`./build-dh`
どうやら「Diffie-Hellman」という方式らしい。生成に結構時間がかかるので軽くストレッチでもしましょう。
（Celeron j1900で2分弱)
出来上がった鍵はkeysディレクトリに保存されているので、そのうち

* crt
* key
* ca.crt
* dh2048.pem

を、一つ上のディレクトリ(`/etc/openvpn`)にコピーしておく。
（後のOpenVPNの設定ファイルでは絶対参照できるけど書くのが面倒なので）

コピーしたら続いてVPN接続させたい機械の数だけ鍵を生成。
`./build-key (鍵の名前)`
生成された鍵ファイルは同じkeysの中にあるので、これを安全な方法でそれぞれのマシンにコピーしましょう。

最後にVPN自体の鍵(TLS)を作るために
`openvpn --genkey --secret ta.key`
と実行し、出来上がった`ta.key`を同じく`/etc/openvpn`の中に入れておく。

## OpenVPNの設定
`/etc/openvpn/server.conf`を編集・・・したいけどインストールしたての状態だとないため、

* サンプルをコピー
`cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/`

* そして解凍
`gzip -d server.conf.gz`


server.confの中身はだいたいこんな感じで動きました。より詳しいことは別途調べましょう。

```lang:server.conf
mode server
tls-server
tls-cipher DHE-RSA-AES256-SHA
cipher AES-256-CBC
keysize 256
auth SHA256

port 443
proto tcp

dev tun # iOS/Androidと繋げたかったためTUN方式

ca ca.crt
cert (build_key_serverにて作成したファイル名).crt
key (build_key_serverにて作成したファイル名).key
dh dh2048.pem

server (VPNにて使いたいIPアドレス 例:192.168.1.0) (ネットマスク)
ifconfig-pool-persist ipp.txt
push "route (実際にサーバーが使用しているネットワーク 例:192.168.0.0) (ネットマスク)"
push "redirect-gateway def1 bypass-dhcp"

push "dhcp-option DNS (DNSサーバのIPアドレス)"
push "dhcp-option DNS (必要であればサブDNSサーバのIPアドレス)"

client-to-client
tls-auth ta.key 0
comp-lzo
user nobody
group nogroup
persist-key
persist-tun

verb 3

# 必要ならばログをとる
status openvpn-status.log
log         openvpn.log

management localhost 17505 # telnetで入ると強制切断やステータスが確認できる
```

この状態で`openvpn --config server.conf`と実行してエラーが出ないか確認をする。
`Initialization Sequence Completed`で待機中になったら成功。


## ルーティング設定
iptablesで
`iptables -t nat -A POSTROUTING -s (VPNで使用するIPアドレス)/24 -o (使用するNICの名前) -j MASQUERADE`
でそのままパケットをリレーさせる状態にし、
`/sbin/iptables-save -c > /etc/iptables.rule`
で保存。
`/etc/network/if-pre-up.d/`にiptablesを読み込ませるために適当なファイルを作成する

```lang:iptables_restore
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.rule
exit
```

同じく`/etc/network/if-up.d`にroute用のシェルスクリプトを作成しておく。

```lang:routes
#!/bin/bash
/sbin/route add -net (VPNで使用するIPアドレス) netmask (ネットマスク) gw (ルーターのIPアドレス)
exit
```

作成後、忘れずに`chmod +x`で2つに実行権限を付けておく。
最後に`sysv-rc-conf openvpn on`をして起動時に実行するよう設定したら完成。

## クライアントの設定
コピーしてきたファイルをひと通り揃え、適当な設定ファイルを作成する。

```myvpn.ovpn
client
tls-auth ta.key 1
dev tun
proto tcp
remote (サーバーへのグローバルアドレスかドメイン) 443
ca ca.crt
cert (build_keyで使用した名前).crt
key (build_keyで使用した名前).key
resolv-retry infinite
nobind
persist-key
persist-tun
comp-lzo
verb 3

tls-cipher DHE-RSA-AES256-SHA
cipher AES-256-CBC
keysize 256
auth SHA256
```

といった内容で作成し、MacOSXならTunnelBrick、iOS/AndroidならOpenVPN for iOS/Androidを使用する。
TunnelBrickの場合は`~/Library/Application Support/Tunnelblick/Configurations/`の中に一式を入れ、起動して変換する。
iOS/Androidの場合は一式をそれぞれの端末に入れて読み込ませる。

上手くつながれば大成功です。お疲れ様でした。