OpenVPN 2.5.0 構築メモとネットワーク構成解説（ぜんぶ Windows）

この記事は「[NEXTSCAPE Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nextscape)」の22日目です。
個人ブログにでも保存しておこうかと思ってたけど、三日坊主のままどこに作ったかも忘れたのでこちらに寄稿することに。

# TL;DR
要点だけ見たい方はこちら。ただし、TUN の章では TAP と重複する部分は記述していません。

- [鍵生成](#鍵生成)
- [TAP 構成](#tap-構成)
- [TUN 構成](#tun-構成)

有名なプロダクトなのでググれば情報はあるんですが、歴史もあるので情報の新旧を見極めないとバージョン差異でハマります(ました)。ここでは 2.5.0 で記録を残します。あと Windows でない情報も混在してきて切り分けガー！ ここではサーバー/クライアント共に Windows だけです。Googleability 的に Windows でない OS の名前は書きません。

# インターネット接続の IPoE 化により...
フレッツ回線の PPPoE 接続はもう使い物にならない話は有名ですね。ピークタイムにもなるとギリギリひとけたMbpsを維持している程度まで落ち込みます。それなんて言うADSL？
対応機材も必要ですが IPoE (IPv4 over IPv6) へ移行すると快適です。ピークタイムでも 500MBps 以上を維持できてます。 
ところがこの IPoE はお高いプランでないと IPv4 アドレスを占有できず共有となり、使えるポートに厳しい制約が発生します。うちでは VNE が JPNE なので MAP-E 割り当ての 240 ポートしかありません。当然これ以外の任意のポート開放などできません。外から Home LAN に接続するために運用していた PPTP が使えなくなってしまったのです。（知ってた）
... と言うワケで OpenVPN の環境を構築した記録です。OpenVPN ではポート番号も自由に選べるので IPoE でも問題なく運用できるのです。

# 環境条件など
- [OpenVPN](https://www.openvpn.jp/) 2.5.0 I601 (2020-10-29)
- ぜんぶ Windows10 (20H2)
- YAMAHA RTX1210
    - [1220](https://www.yamaha.com/ja/news_release/2020/20121601/) [ぐぬぬ](https://www.google.co.jp/search?ei=YyzgX6mSGIG6wAOg5ZuoCg&q=%E3%81%90%E3%81%AC%E3%81%AC&oq=%E3%81%90%E3%81%AC%E3%81%AC&gs_lcp=CgZwc3ktYWIQAzICCAAyAggAMgIIADICCAAyAggAMgIIADICCAAyAggAOggIABCxAxCDAToFCAAQsQM6CggAELEDEIMBEAQ6BAgAEAQ6BwgAELEDEAQ6CAgAELEDELEDOgYIABAEEANQ5mJYlWdg1m1oAHABeACAAWiIAZIEkgEDNS4xmAEAoAEBqgEHZ3dzLXdpesABAQ&sclient=psy-ab&ved=0ahUKEwjpz77qpd7tAhUBHXAKHaDyBqUQ4dUDCA0&uact=5)
    - 買うなら民生機でも Static Route 設定が可能な機種を探しましょう
- 逸般の誤家庭

# インストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/997e3f19-0823-baf9-1a9c-814687e4f704.png)
あまり説明する事もないですが、Custom でインストールしましょう。デフォルトで OpenVPN Service はインストールされないのでご注意。

# ポート開放
OpenVPN サーバーのIP宛に、適当なポートを割り当てます。パケットフィルターの除外設定も必要かもしれません。
設定方法は Home Gateway 次第です。

```text:YAMAHA-Command
# NAT
nat descriptor masquerade static 1000 40001 192.168.111.10 udp 62015

# IPv4 Filter
ip filter 400004 pass * 192.168.111.10 udp * 62015
tunnel select 1
  ip tunnel secure filter in 400004 # 他省略
```

# 鍵生成
OpenVPN の認証はクライアント証明書が標準で、その他は面倒なので忘れます。
CA作って鍵作って、といくのですが、巷では `easy-rsa` のコマンドで... と紹介されてます。が、なにそれ？ 動かないし。。。
もっと便利な GUI ツールがあるので `easy-rsa` も忘れちゃいましょう。

## [vpnux PKI Manager](https://www.openvpn.jp/download/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/9d0cb2c3-9750-b1e5-88fe-09d6771b0a32.png)

順番にポチポチするだけで必要な鍵やら証明書が作れます。


# TAP 構成
L2接続です。
インターネットを超えて無線LANケーブルを挿しに来るかんじ。
DHCP も Home LAN にあるものが使われ、VPN クライアントも同一サブネットの端末になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/590572fc-c256-2d20-5548-9abe6733759d.png)

## サーバー構成
### 構成ファイルと証明書配置
`.ovpn` なファイルを認識してくれます。
`%ProgramFiles%\OpenVPN\sample-config` にサンプルがあるので加工して作りましょう。


```text:server.ovpn
# UDP ポート指定
port 62015
proto udp

# TAP モード
dev tap

# OSのNIC名
dev-node OpenVPN-TAP

# CAとサーバー証明書（鍵生成で作ったファイル）
ca ca.crt
cert vpnserver.crt
key vpnserver.key
dh dh2048.pem

server-bridge
keepalive 10 120
cipher AES-256-GCM

persist-key
persist-tun
log         openvpn.log
verb 3
explicit-exit-notify 1
```
- dev-node `OpenVPN-TAP`
    - NIC の名前に合わせておきます。省略しても良いらしい。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/3d3d195e-e417-0830-b33b-6bd09889c378.png)
- CAとサーバー証明書
    - 必要なものは鍵生成で生成済み
    - サーバー側で使用するもの（ルートCAの証明書、Diffie Hellman パラメーター、サーバーの証明書、サーバーの鍵）  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/6c013d36-85de-5632-e249-d48b28760848.png)
- cipher `AES-256-GCM`
    - [2.5 から CBC は外されてる](https://github.com/OpenVPN/openvpn/blob/release/2.5/Changes.rst)そうですが、サンプルファイルは`AES-256-CBC`のまま...
    - `AES-256-GCM`に書き換えておきます。

### NIC のブリッジ接続
TAP インターフェイスとイーサネット側の接続を選択してネットワークブリッジ接続を構成します。
ブリッジインターフェイスにされるとき IP アドレスの設定も変わります。 IP アドレス接続のリモートデスクトップでこれをやると詰みます(ました)のでご注意。サーバー名で接続してるなら何とかなる、かも。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/e6eb03e3-a1b8-7e39-e887-cdd15297d735.png)


### 動作チェック
動作チェックは GUI ツールでやります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/f88e81e8-da20-5b6b-7140-be1a5b95fa40.png)

ついでにスタートアップは切っておきましょう。サーバー側の運用ではサービス実行なので。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/b8787503-3f69-009f-acf2-f4a976a643eb.png)

ファイル一式を
`%ProgramFiles%\OpenVPN\config`
に配置します。`config`ですよ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/96c87990-7f93-3a01-c533-4d436043c332.png)

タスクトレイから「接続」する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/2be9ce6b-1cf2-e80e-72f8-9b461a076566.png)

### サービス起動
動作チェックが上手くいったらサービス起動に切り替えます。
クライアント接続まで試してからの方がいいでしょう。

ファイル一式を
`%ProgramFiles%\OpenVPN\config-auto`
に移動します。`config-auto`ですよ。
サービス実行時は`config-auto`を読みに来ます。2.5～ の改変っぽく、ハマリどころだった。

こちらはお馴染み、サービスの自動起動を設定しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/a52b5dce-2b07-ef3a-e3c7-36b1547acf56.png)

### ファイアーウォールについて
ファイアーウォールどうしようかなーと思ったのですが、インストーラーが自動構成してくれているみたいです。TAP 構成をする限りは気にしなくても大丈夫でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/c7bc84f8-18a0-e64f-aeba-d9a22128f838.png)


## クライアント構成
### 構成ファイルと証明書
こちらも `%ProgramFiles%\OpenVPN\sample-config` にサンプルがあるので加工して作りましょう。
サーバー側の構成にあわせて書いていけるでしょう。

```text:client.ovpn
client

# TAP モード
dev tap

# OSのNIC名
dev-node OpenVPN-TAP

# 接続先
proto udp
remote ************.**ddns.jp 62015

resolv-retry infinite
nobind
persist-key
persist-tun

# CAとクライアント証明書（鍵生成で作ったファイル）
ca ca.crt
cert client_SurfacePro5.crt
key client_SurfacePro5.key

remote-cert-tls server
cipher AES-256-GCM
verb 3
```
- CAとクライアント証明書
    - 必要なものは鍵生成で生成済み
    - クライアント側で使用するもの（ルートCAの証明書、クライアントの証明書、クライアントの鍵）  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/127b3a62-ca5b-f44c-4192-9510d8b0c364.png)
- cipher `AES-256-GCM`
    - サーバーと同じ。サンプルもGCMで書いといてほしかった。

### ファイルの配置
`%ProgramFiles%\OpenVPN\config` でも動かせますが、証明書はユーザー単位の発行となるハズなので、`%USERPROFILE%\OpenVPN\config` が良いでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/aa64c192-24df-7a51-d31e-3fd2febaa28c.png)


GUI ツールの設定もあわせておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/cec054bb-ed55-e650-c6cd-aa3818f84eb8.png)

### 接続
あとはタスクトレイのアイコンをダブルクリックするだけです。
クライアントでは GUI ツールをスタートアップさせておくと、いつでもサクッと接続できて便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/60ba896f-933e-3338-edb3-fdd5b8305e17.png)


## BSoD
TAP での運用を始めてすぐ、サーバーが BSoD するようになってしまいました。2～3日に1回くらいのハイペース。OpenVPN のサービスを止めてみたくらいでは解消しませんでした。
初めは何事かわからなかったですが、MEMORY.DMP を WinDbg で解析してみると `SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e)` `bridge.sys` といったキーワードを発見。ネットワークブリッジか！
ここまでわかるとググれますね。

[BSoD on Windows in Bridged Mode](https://community.openvpn.net/openvpn/ticket/1283)
> fixed in the release of OpenVPN-2.5.0

いやー 治ってないんじゃないかなー (^_^;)

これ以外でも、Windows のネットワークブリッジは色々と問題を起こしている様子。上記リンク先にもあるように
> 長い間、Windows上でブリッジネットワークを使用している人を見たことがありません。

確かに。

...というあたりで TAP は諦めました。

# TUN 構成
L3接続です。
OpenVPN により Home LAN とは異なるバーチャルなサブネットが構成され、その間をルーティングするカタチを取ります。
TAP よりもネットワーク的に複雑化してきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/7b5a5f39-ddf7-9885-9539-dac1df694347.png)


## サーバー構成
### 構成ファイル
```text:server.ovpn
# UDP ポート指定
port 62015
proto udp

# TUN モード
dev tun

# OSのNIC名
dev-node OpenVPN-TUN

# Wintunデバイス設定
windows-driver wintun

# CAとサーバー証明書（鍵生成で作ったファイル）
ca ca.crt
cert vpnserver.crt
key vpnserver.key
dh dh2048.pem

# VPN サブネット
server 192.168.222.0 255.255.255.0

# Home LAN サブネットをクライアントへ配信
push "route 192.168.111.0 255.255.255.0"

keepalive 10 120
cipher AES-256-GCM
persist-key
persist-tun
log         openvpn.log
verb 3
explicit-exit-notify 1
```

- `windows-driver wintun`
    - [2.5 から Wintun を使う](https://www.openvpn.jp/2020/09/29/1320/)ようになっているとのこと
    - 標準でインストールされた仮想 NIC はコレで構成されているっぽい
- VPN サブネット
    - Home LAN 側に存在しないアドレス空間で設定しましょう
    - .1 が仮想 NIC に割り当てられる
    - .5 以降がクライアントに割り振られる様子
- Home LAN サブネットをクライアントへ配信
    - クライアントから見て VPN Gateway の先にあるサブネットを、クライアントへ伝えるための記述

### ファイアーウォール設定
仮想 NIC はパプリックネットワークとして認識されるようで、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/715e20dd-281c-f243-2cd9-3f862fe235e7.png)
変更できなさそうでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/11dba5d2-b4e3-ca27-2eed-a954f468af3b.png)

この状態ではファイアーウォールによってパケットが止められてしまうので、必要に応じて穴開けをします。
例えば ICMPv4 (ping とか) なら既存の規則を有効化したり編集したりします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/c66b0e19-77cb-7be3-7c36-c409cd2daf0b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/aa926d25-8af4-10db-8897-3cbeab42de1c.png)

#### ここまでの設定で以下のような疎通ができています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/eee488f8-7d3b-48ed-3a57-e9f5b09c0ec1.png)
まだ VPN のサブネットアドレスのみの疎通なので Home LAN に居る時とは異なるアドレスでサーバーを指定しなければなりません。（Home LAN では `192.168.111.10` なのに VPN からは `192.168.222.1` になります。）また、Home LAN 側に居る他の機器にアクセスすることもできません。

### OS のルーティング機能を有効化
通常、OS は複数の NIC を持っていても、複数のネットワークに同時に接続している状態になるだけです。その間のパケット中継はしません。ルーティング機能を有効化すると、サブネット間でパケットを中継するようになります。
方法は以下の 2 パターンあるそうですが、1 だけでは機能せず... 2 も行うと機能しました。

1. `HKLM\SYSTEM\CurrentControlSet\services\Tcpip\Parameters IPEnableRouter` の値を 1 にする（要再起動）
1. Routing and Remote Access サービスを起動する（自動起動化も忘れずに）

有効にできているかどうかは、`ipconfig /all` で確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/d3d631a2-a05e-475e-8da5-6dcd27000e65.png)

#### 以下のような疎通が追加されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/b135d039-0450-e6ca-9929-b00ced70bead.png)

VPN 側から Home LAN 側へパケットを送信できますが、Home LAN 側から見ると VPN 側の IP アドレスは未知のサブネットに属しています。IP ネットワークの標準仕様として、その様なパケットは DefaultGateway 宛に送信することになりますが、そこでも宛先不明となりパケットは破棄されます[※]。唯一、VPN サブネットとの接続を持っている OpenVPN をホスティングしている OS だけは、適切にパケットを送信することができます。（VPN からも `192.168.111.10` でアクセスできるようになりました。）
※一般的に、プライベート IP アドレス宛なので破棄する。宛先不明でもグローバル IP アドレス宛の場合は WAN 側へ中継される。されないと超困る。

### Home LAN 側から VPN サブネットへのパケット送信を可能にする
これには 2 つの方法があります。Home Gateway の Static Route 設定がオススメですが、民生機では非対応なものもあります。

#### ① Home Gateway の Static Route 設定
設定方法は Home Gateway 次第です。
OpenVPN をホスティングしている OS が VPN サブネットへの Gateway になっているので、ルートをひとつ追加すれば良いです。

```text:YAMAHA-Command
ip route 192.168.222.0/24 gateway 192.168.111.10
```

完成形はこんなイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/160ec630-ef26-2cac-a9cb-a7aec85c2f2d.png)

#### ② Home LAN 側機器のルーティングテーブルに VPN サブネットを登録する
VPN 側から使いたい機器すべてのルーティングテーブルに VPN サブネットへの Gateway を登録します。とても面倒です。

```text:Windows-CMD
route -p add 192.168.222.0 mask 255.255.255.0 192.168.111.10
```

完成形はこんなイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218556/6b0d079e-738d-4881-1514-2b0e4874a18f.png)

### ファイアーウォール設定（Home LAN 側のその他の機器）
VPN サブネットは自身が所属しているサブネットとは異なるため、Windows クライアント OS でも外部扱いされています。ファイアーウォールへの穴開けをしないと `SMB` どころか `ping` すら応答しません。必要に応じて設定を行ってください。
Windows Server 系は大丈夫だったような気がします。

## クライアント構成
### 構成ファイル
```text:client.ovpn
client

# TUN モード
dev tun

# OSのNIC名
dev-node OpenVPN-Wintun

# Wintunデバイス設定
windows-driver wintun

# 接続先
proto udp
remote ************.**ddns.jp 62015

resolv-retry infinite
nobind
persist-key
persist-tun

# CAとクライアント証明書（鍵生成で作ったファイル）
ca ca.crt
cert client_SurfacePro5.crt
key client_SurfacePro5.key

remote-cert-tls server
cipher AES-256-GCM
verb 3
```