ConoHa VPS に Docker で OpenVPN サーバを構築する

:::note info
この記事は [ConoHa Advent Calendar 2023](https://qiita.com/advent-calendar/2023/conoha) の11日目の記事です。10日目は[Ayutsukiさん](https://ayutsuki.net/introduction/conoha-gpu-sdwui/)でした。12日目は[めんどい 太郎さん](https://qiita.com/mendoitarou_/items/f8cb185194d4f863b403)です。
:::

本記事では，ConoHa VPS 上に Docker で OpenVPN サーバを構築する手順を解説します。

# 前提

1. ConoHa VPS 上に Linux サーバが構築されており，SSHでログインできるようになっている
1. Docker がインストールされており，`sudo` なしで Docker が実行できるようになっている

この準備がまだの方は，次の記事でその手順を詳しく解説していますので，必要に応じてこちらを設定してから，続きをお読みください。（下記記事では Ubuntu でサーバ構築していますが，他の Linux でも大差ありませんので大丈夫です。）

https://qiita.com/doraTeX/items/90452f163b17541df825

# VPNサーバを構築する目的

旅が好きな自分は，海外を含む空港やホテルが提供する公衆WiFiを使ってネット接続する場面が多々あります。それにあたり，ConoHa VPS上にVPNサーバを構築し，**踏み台サーバ**として用いると便利です。その目的は大きく4つあります。

## 目的①. 公衆WiFi接続時のセキュリティ確保

公衆WiFiのセキュリティに不安を持つ人も多いでしょう。そこで，ConoHa上のVPNサーバを踏み台として，全通信を暗号化されたVPNトンネルを通して行うことで，公衆WiFiを通す通信を暗号化し，セキュリティを確保できます。

## 目的②. 国内からしかアクセスできないサイトに海外から接続する

動画配信サイトや金融機関のサイトなどで，日本国外からのアクセスを，IPアドレスで判定して遮断しているサイトがあります。そこで，国内にある ConoHa VPS を踏み台としてアクセスすることで，サイト側からは日本国内からのアクセスと判定させて，海外からでも日本国内にいるときのようなアクセスを確保できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/60a1ddf1-65bd-1032-e7b0-945bdb8fafcf.png)


なお，これを目的として，有料で提供されている既存の大手VPNサービスを使う手もありますが，サイトによっては，有名な大手VPN提供業者のIPアドレスがNGリストに登録されており，そのVPN業者からのアクセスを遮断しているケースもあります。自分でVPNサーバを構築しておけば，そのようなIPアドレス規制にも引っかからず確実です。

## 目的③. ファイアウォールの回避

空港やホテルのファイアウォール設定によっては，HTTP(S)やDNSなどの必要最低限のプロトコル以外のアウトバウンド接続を規制していたり，あるいは帯域制限等の目的で動画配信サイトへのアクセスが遮断されていたりすることがあります。VPS上に構成されたVPNサーバを踏み台とし，全ての通信をそのVPNトンネルを経由して接続することで，そのような制限をかいくぐることができます。特に，HTTPS通信と同じ 443/tcp でVPNサーバを待ち受けさせ，そこに向けてTLSで暗号化したVPN通信を通せば，通常のウェブブラウザによるHTTPS通信と区別を付けることは困難なので，ブロックされる可能性は極めて小さいと言えるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/d4d6a356-fe1d-4761-b97b-e0461863040c.png)



## 目的④. 自宅LAN内へのアクセス確保

自宅LAN内の端末と出先の端末を，ともに ConoHa VPS 上のVPNサーバに接続しておきます。すると，その仮想ネットワークにおいては，自宅の端末と出先の端末が「同一LAN内」に存在することとなります。よって，SSH, SMB, VNCをはじめ，自宅LAN内の端末に自由に接続できるようになります。さらに，その自宅端末を踏み台にすることで，自宅LAN内の他の端末への接続も可能となるわけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/6237d6a3-4ea7-4bdc-5d66-bd4c81664392.png)

この方法で自宅LANへの接続を確保する長所は次の通りです。

* 自宅のルータのポートフォワーディング設定などを変えなくてよい。
* インバウンド接続が全て拒否されるようなNAT内に対しても外からの接続を確保できる。
* ケーブルTVネットワークなどで，そもそも契約者にグローバルIPアドレスが与えられず，外部ネットワークから unreachable な自宅LAN環境であっても，外部からの接続が可能となる。



# VPNサーバの種類の選択

## PPTP

古いVPNプロトコルの一つで，設定が比較的簡単ですが，セキュリティが弱いので，現在では非推奨となっています。

## L2TP/IPsec

定番のVPNプロトコルで，各OSでも標準でクライアント機能が用意されているので便利です。ただしポート番号が固定（UDP 500/1701/4500，IP 50 (ESP)）であるため，公衆WiFiのファイアウォールでアウトバウンドポートが制限されている場合は使用不可となってしまいます。

## OpenVPN

TLSを利用したオープンソースで提供されるVPNソリューションです。デフォルトでは 1194/udp を利用しますが，ポート番号を変更したり，UDPではなくTCPを使用することも可能です。各OSにはデフォルトでクライアント機能は用意されていないので，クライアントには自前で OpenVPN クライアントをソフトウェアをインストールする必要があります。

## 結論：OpenVPN サーバを Docker で構築する

これらを比較検討した結果，上述の目的①～④を全て満たすことができる，OpenVPN を選ぶことにしましょう。OpenVPN サーバの構築は本来それほど簡単ではありませんが，Docker を利用してイメージを展開することで，かなり楽に OpenVPN サーバ構築ができるようになります。

# プロトコル・ポートの選択：UDP vs. TCP

OpenVPN の場合，デフォルトの待ち受けポートは 1194/udp です。多くの場合このままで問題はないでしょう。UDPはTCPに比べオーバーヘッドが少ないので，高速になると期待されます。ですが，次のようなケースで問題になり得ます。

* 航空機内WiFiなど，特に回線が貧弱でパケットロスが起こりやすい場合，UDPの信頼性の低さが問題となる。オーバーヘッドを許容してでも，TCPの信頼性が欲しいケースもある。
* [目的③](#目的-ファイアウォールの回避)に関連して，厳しいファイアウォールによって HTTP(S) 以外のアウトバウンド接続が制限されているようなケースだと接続できない。
* また，1194/udp に対して接続していると，「OpenVPN サーバへ接続している」ということが検知されやすく，ブロックされる可能性がある。（中国の金盾とか？）

このようなケースに対処するためには，OpenVPN サーバを 1194/udp ではなく 443/tcp で待ち受けさせるという手が考えられます。443/tcp はHTTPSのポートなので，これがファイアウォールでブロックされている可能性は限りなく小さいです。443/tcp で待ち受ける OpenVPN サーバに対してTLSで暗号化したVPNトンネルを張れば，ウェブブラウザの利用による通常のHTTPS通信と区別が付かないため，ブロックすることは困難でありましょう。

## 結論：UDPとTCPでデュアルスタンバイとする

一方，通常の利用であれば，オーバーヘッドの少ない 1194/udp で十分です。そこで，Dockerの強みを活かして，

* 同じ設定ファイル一式を元に，OpenVPNサーバを二重に起動させる（Dockerコンテナを2つ起動させる）。
* 片方はUDP，もう片方はTCPで待ち受けさせる。
* 通常利用時はUDPの方を使い，特殊なケースならTCPの方に接続する

というデュアルスタンバイ体制を整えてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/c7bb7f6a-54f1-3619-1ead-250343756d49.png)


# OpenVPNにおける仮想ネットワークトポロジーの選択：`net30` vs. `subnet`

**結論：`subnet`を選んでおけばよい**

:::note info

<details><summary>詳細説明：net30 と subnet の違い</summary><div>

デフォルトでは，OpenVPN サーバが構築する仮想ネットワークのトポロジー設定は，`net30` というものになっています。これは，IPv4 の 32bit のIPアドレスにおいて，上位 30bit をネットワークアドレスとし，下位 2bit のみをホストアドレスとして，接続クライアントごとに別々のネットワーク空間に属するように設定するものです。

## `net30` トポロジーの例

### クライアントAとOpenVPNサーバとの接続

* ネットワークアドレス：`192.168.255.0`（2進法で書けば`11000000.10101000.11111111.00000000`）
* サブネットマスク：`255.255.255.252`（2進法で書けば `11111111.11111111.11111111.11111100`）

➡ サブネット内のIPアドレスは4個しかないことになります。しかも，うち2つはネットワークアドレスとブロードキャストアドレスになるため，ホストに使えるIPアドレスは2個のみ。その2つを，サーバ側とクライアント側で分け合います。

* `192.168.255.0`（下位2bitが`00`）：ネットワークアドレス
* `192.168.255.1`（下位2bitが`01`）：OpenVPNサーバ側のIPアドレス
* `192.168.255.2`（下位2bitが`10`）：クライアントAのIPアドレス
* `192.168.255.3`（下位2bitが`11`）：ブロードキャストアドレス

### クライアントBとOpenVPNサーバとの接続

* ネットワークアドレス：`192.168.255.4`（2進法で書けば`11000000.10101000.11111111.00000100`）
* サブネットマスク：`255.255.255.252`（2進法で書けば `11111111.11111111.11111111.11111100`）

同様に，サブネット内の4個のIPアドレスは，ネットワークアドレス・サーバのIPアドレス・クライアントのIPアドレス・ブロードキャストアドレスで使用します。

* `192.168.255.4`（下位2bitが`00`）：ネットワークアドレス
* `192.168.255.5`（下位2bitが`01`）：OpenVPNサーバ側のIPアドレス
* `192.168.255.6`（下位2bitが`10`）：クライアントBのIPアドレス
* `192.168.255.7`（下位2bitが`11`）：ブロードキャストアドレス

このように，`net30` トポロジーの場合，1クライアントごとにIPアドレス空間を4個ずつ消費してゆくので，アドレス空間の使い方として効率が低いです。また何より，クライアントごとに別々のサブネットに所属しているのは，[目的④](#目的-自宅lan内へのアクセス確保)（外部から自宅LAN内の端末と同一ネットワーク内として接続したい）のためには分かりづらいです。そこで，もっとシンプルに，OpenVPNサーバと，接続中の各クライアントとが，全て同一ネットワーク内に所属するような仮想ネットワーク構成としたいです。それを実現するのが `subnet` というネットワークトポロジー設定です。これであれば，

* ネットワークアドレス：`192.168.255.0`
* サブネットマスク：`255.255.255.0`
* OpenVPNサーバ側のIPアドレス：`192.168.255.1`
* クライアントAのIPアドレス：`192.168.255.2`
* クライアントBのIPアドレス：`192.168.255.3`
　⋮
* ブロードキャストアドレス：`192.168.255.255`

という，ごく普通の `192.168.255.0/24` の仮想ネットワークが実現でき，アドレス空間が有効活用できますし，何よりシンプルで分かりやすいです。

古いOpenVPNクライアントだと `subnet` トポロジーに対応していないという理由で `net30` トポロジーがデフォルト設定となっているようですが，今から新規にOpenVPNサーバを構築するなら，`subnet` トポロジーで構築しておくのがよいでしょう。
</div></details>
:::

# 作業工程

## 前提

### VPSのドメイン名

ConoHa VPS のサーバに与えられたドメイン名が `VPS.SERVERNAME.COM` であるとします。独自ドメイン名を取得していない場合も，ConoHa VPS のコントロールパネルを見ると，`vXXX-XXX-XXX-XXX.fxcu.static.cnode.jp` といったドメインが与えられていることが分かりますので，それを使えばOKです。

### VPSのSSHサーバへの接続法

ConoHa VPS へのSSH接続ができるようになっているとします。[前記事](https://qiita.com/doraTeX/items/90452f163b17541df825)で設定したように，

* パスワード認証を無効化して `~/.ssh/id_ed25519` による公開鍵認証に
* `~/.ssh/config` において `__conoha` という名前でエイリアス設定

としておくと，安全かつ便利です。

```ssh:［クライアント上の］~/.ssh/config
Host __conoha
    User USERNAME
    Hostname VPS.SERVERNAME.COM
    Port 12345
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes
```

### OpenVPNサーバの設定ファイルの保存場所

VPSのUbuntu上において，`$HOME/ovpn-data` というディレクトリを設定ファイルの保存場所とします。


## 工程1：OpenVPN の Docker イメージを pull して初期設定

```sh:［VPS上で］設定ファイル保存ディレクトリを作成
$ mkdir $HOME/ovpn-data
$ cd $HOME/ovpn-data
```

OpenVPN サーバの Docker イメージとして，`kylemanna/openvpn` というイメージを使います。

* [`kylemanna/openvpn` (Docker Hub)](https://hub.docker.com/r/kylemanna/openvpn/)
* [`kylemanna/openvpn` (GitHub)](https://github.com/kylemanna/docker-openvpn)

これを pull しましょう。

```sh:［VPS上で］kylemanna/openvpn をpull
$ docker pull kylemanna/openvpn
```

まずはデフォルト通り 1194/udp で待ち受ける設定，かつ `subnet` トポロジーで，設定ファイルを生成します。

```sh:［VPS上で］設定ファイルを生成
$ docker run --rm -v $HOME/ovpn-data:/etc/openvpn \
    kylemanna/openvpn ovpn_genconfig \
      -u udp://VPS.SERVERNAME.COM:1194 \
      -e 'topology subnet'
```

これで `~/ovpn-data/openvpn.conf` という設定ファイルが生成されます。必要に応じてこのファイルを次のように手動編集しましょう。

```sh:［VPS上で］設定ファイルを手動編集
$ sudo vim ~/ovpn-data/openvpn.conf
```

デフォルトで生成される `openvpn.conf` において，

```
route 192.168.254.0 255.255.255.0
```

という行は，`subnet` トポロジを採用する結果不要となりますので，`#` でコメントアウトしておくとよいでしょう。

また，他には，

```
duplicate-cn
```

という行を加えておけば，同一証明書を持つ複数の端末からの同時接続を許可できます。ただし，本来，セキュリティ上は端末ごとに別々の証明書を発行して分離すべきです。同一端末扱いの複数のクライアントが同時に接続すると，ログ上での追跡が難しくなりますし，[目的④](#目的-自宅lan内へのアクセス確保)のために端末ごとにIPアドレスを固定する運用をする場合には障害になりますので，避けておいた方がよいでしょう。ここでは `duplicate-cn` は指定しないものとします。

## 工程2：PKI初期設定

次に，PKI（公開鍵基盤）の初期設定を行います。CA（認証局）のパスフレーズを決めてください。これは忘れぬよう記録しておきましょう。Common Name の質問はそのままリターンを押せばよいです。

```sh:［VPS上で］PKI初期設定
$ docker run --rm -it -v $HOME/ovpn-data:/etc/openvpn \
    kylemanna/openvpn ovpn_initpki

init-pki complete; you may now create a CA or requests.
（中略）
Enter New CA Key Passphrase:（ここでCAのパスフレーズを入力）
Re-Enter New CA Key Passphrase: （確認のためもう一度入力）
（中略）
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:（リターン入力）
（中略）
Enter pass phrase for /etc/openvpn/pki/private/ca.key:（CAのパスフレーズを再入力）
（中略）
Enter pass phrase for /etc/openvpn/pki/private/ca.key:（CAのパスフレーズを再入力）
（後略）
```

## 工程3：クライアントごとの鍵ペアと設定ファイルを生成

VPN接続したいクライアント（Mac，Windows，iPhoneなど）ごとに，鍵ペアと設定ファイルを生成します。

まずは，OpenVPNサーバが認識する固有のクライアント名を決めましょう。半角英数字のみ，記号は不可のようです。そして，そのクライアントに対応するパスフレーズも決めます。

```sh:［VPS上で］クライアントAに対応する鍵ペアの生成
$ export CLIENTNAME="ClientA"
$ docker run --rm -it -v $HOME/ovpn-data:/etc/openvpn \
    kylemanna/openvpn easyrsa build-client-full $CLIENTNAME

（中略）
Enter PEM pass phrase:（クライアントAのパスフレーズを入力）
Verifying - Enter PEM pass phrase:（クライアントAのパスフレーズを再入力）
（中略）
Enter pass phrase for /etc/openvpn/pki/private/ca.key:（CAのパスフレーズを入力）
（中略）
Write out database with 1 new entries
Data Base Updated
```

次に，ここで設定した `ClientA` というクライアントにインストールすべき設定ファイル（証明書を含む）を生成します。

```sh:［VPS上で］クライアントAのための設定ファイル生成
$ docker run --rm -v $HOME/ovpn-data:/etc/openvpn \
    kylemanna/openvpn ovpn_getclient $CLIENTNAME > ~/$CLIENTNAME.ovpn
```

すると，この例ならば `~/ClientA.ovpn` というファイルが生成されているはずです。

以下，他に接続したいクライアント `ClientB`, `ClientC`, …… があれば，その分だけこの工程を繰り返します。

## 工程4：ファイアウォールの許可設定

ConoHa VPS 内のLinuxのファイアウォール設定において，`1194/udp` と `443/tcp` を許可します。Ubuntu の `ufw` であれば次のようにして許可します。

```sh:［VPS上で］Ubuntuのファイアウォール許可設定
$ sudo ufw allow 1194/udp
$ sudo ufw allow 443/tcp
```

ConoHa の側でもファイアウォール設定がある場合は，そちらにも許可設定を加えることを忘れてはいけません。ConoHa VPS Ver.3.0 の「セキュリティグループ」であれば，次のようにカスタムしたセキュリティグループを適用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/d415b7b7-f825-303b-2f05-dad729c708a5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/1313f69a-761e-5e8b-546a-30c3401af58b.png)

## 工程5：デュアルスタンバイのための Docker compose ファイルを用意

次のファイルをVPS上の `~/docker-compose.yml` として用意します。

```yaml:［VPS上の］~/docker-compose.yml
version: '3.8'

services:
  openvpn-udp:
    image: kylemanna/openvpn
    container_name: openvpn-udp
    ports:
      - "1194:1194/udp"
    volumes:
      - "./ovpn-data:/etc/openvpn"
    cap_add:
      - NET_ADMIN
    restart: unless-stopped

  openvpn-tcp:
    image: kylemanna/openvpn
    container_name: OpenVPN-TCP
    ports:
      - "443:1194/tcp"
    volumes:
      - "./ovpn-data:/etc/openvpn"
    cap_add:
      - NET_ADMIN
    command: ovpn_run --proto tcp
    restart: unless-stopped
```

これにより，`openvpn-udp` と `openvpn-tcp` という2つのコンテナが起動します。後者は，起動オプションとして `--proto tcp` が指定されています。これにより，UDPでの待ち受けを，強制的に（ポート番号は同じ1194のままで）TCPでの待ち受けに変更して起動します。そして，

* VPS上の 1194/udp ↔ `openvpn-udp` コンテナ内の 1194/udp
* VPS上の 443/tcp ↔ `openvpn-tcp` コンテナ内の 1194/tcp

へとマッピングすることにより，外部からVPSへの 1194/udp，443/tcp への接続のそれぞれが `openvpn-udp`, `openvpn-tcp` へとマッピングされる，というわけです。

では，Docker compose を使って，これら2つのコンテナを起動してみましょう。

```sh:［VPS上で］Dockerコンテナ2つを起動してデュアルスタンバイ
$ cd ~
$ docker compose up -d
```

`docker ps -a` で起動中のコンテナを確認し，`openvpn-udp`, `openvpn-tcp` という名称のコンテナが起動していることを確認しておきましょう。


## 工程6：クライアントに設定ファイルをダウンロードして編集

次に，VPS上の `~/ClientA.ovpn` を，実際に使用するクライアントAへと安全にダウンロードします。クライアントAの `~/.ssh/config` で `__conoha` という名前の[エイリアス設定](#vpsのsshサーバへの接続法)が済んでいれば，次のように `scp` コマンドによって安全・簡単にダウンロードできます。

```sh:［クライアントAで］ClientA.ovpnをダウンロード
$ scp __conoha:ClientA.ovpn .
```

次に，UDP用とTCP用にファイルを分けます。

```sh:［クライアントAで］設定ファイルの複製
$ mv ClientA.ovpn ClientA-udp.ovpn
$ cp ClientA-udp.ovpn ClientA-tcp.ovpn
```

`ClientA-tcp.ovpn` のファイルを開き，

```
remote VPS.SERVERNAME.COM 1194 udp
```

の行を

```
remote VPS.SERVERNAME.COM 443 tcp
```

に変更しておきます。

## 工程7：クライアントに OpenVPN Connect をインストールして接続

VPN接続したいクライアント（Mac，Windows，iPhoneなど）に対し，クライアントソフトウェアである [OpenVPN Connect](https://openvpn.net/client/) をインストールしましょう。

そして，新規プロファイル設定画面において，`ClientA-udp.ovpn` を投入します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/1cf00710-f851-f79a-ca7c-3fe3ab3c8f01.png" width="30%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/ac0f0496-9d7c-b14f-4ac1-7b0808ff31ab.png" width="30%">

これで接続できれば成功です！

同様に，`ClientA-tcp.ovpn` 用のプロファイルも作っておきましょう。

## 確認：接続先から見た自分のIPアドレスが ConoHa VPS のものに変更されているか？

[WhatIsMyIPAddress.com](https://whatismyipaddress.com/ja/index) のようなIPアドレス確認サイトを利用して，接続先サイト側から見た自分のIPアドレスが ConoHa VPS のものに変化したことを確認しましょう。



:::note info

<details><summary>発展：どのようにして全通信をVPNトンネルに通しているか？</summary><div>

`ClientA-udp.ovpn` を開いてみると，次のような行があります。

```
redirect-gateway def1
```

この設定があることで，（LAN内向けの通信を除く）全通信がVPNトンネル経由で送られるようになります。しかし，OSのデフォルトゲートウェイ設定は変更されていません。OSのデフォルトゲートウェイ設定を変えることなく，LAN外向けの全通信をどのようにしてVPNトンネルへと差し向けているのでしょうか。

まずは `ifconfig` で設定を確認してみます。

```sh:［クライアントA上で］ifconfigを確認
$ ifconfig
（中略）
utun14: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
	inet 192.168.255.2 --> 192.168.255.1 netmask 0xffffff00
```

この場合，`utun14` がVPN用の仮想ネットワークインターフェースです。そこで，`utun14` が絡むルーティングテーブルを確認してみます。

```sh:［クライアントA上で］ルーティングテーブルを確認
$ netstat -rn | grep utun14
0/1                192.168.255.1      UGScg              utun14       
128.0/1            192.168.255.1      UGSc               utun14 
192.168.255        192.168.255.2      UGSc               utun14       
192.168.255.1      192.168.255.2      UHr                utun14     
```

ここに，`0/1` および `128.0/1` というルート情報があることに注目します。ルーティングテーブルには**ロンゲストマッチ**という原則があります。宛先IPアドレスにマッチするルート情報が複数ある場合，その中で最もプレフィックス長が長いルート情報が優先されます。

2進法で書くと，`0/1` と `128.0/1` はそれぞれ

```
00000000.00000000.00000000.00000000（先頭1bitがプレフィックス）
10000000.00000000.00000000.00000000（先頭1bitがプレフィックス）
```

となります。つまり，先頭1bitが`0`であるようなIPアドレスは前者に，`1`であるようなIPアドレスは後者にマッチします。

これらはプレフィックス長が1なので，ロンゲストマッチ原則における優先順位としては最下位となります。しかし，どのIPアドレスも，先頭1bitは`0`か`1`のどちらかなので，他のルート情報にマッチしなかったどのIPアドレスも，必ずこのどちらかのルート情報にマッチして拾われることになります。その結果，

* 他のどのルート情報にもマッチしなかった宛先への通信は，全て `0/1`, `128.0/1` いずれかのルート情報にマッチする結果，`utun14` に回される
* OSのデフォルトゲートウェイ設定まで落ちてくることはなく，デフォルトゲートウェイ設定が結果的に無効化されることになる

となるわけです。
</div></details>
:::

# 仮想ネットワーク内でのクライアントのIPアドレスを固定するには

[目的④](#目的-自宅lan内へのアクセス確保)（外部から自宅LAN内の端末と同一ネットワーク内として接続したい）のためには，仮想ネットワーク内でのクライアントのIPアドレスが固定されるようにした方が都合が良いです。
そこで，OpenVPNサーバの側に，クライアントIPアドレス固定設定を加えましょう。

```sh:［VPS上で］ClientAのIPアドレスを192.168.255.2へと固定する設定を行う
$ cd ~/ovpn-data/ccd
$ sudo echo ifconfig-push 192.168.255.2 255.255.255.0 > ClientA
```

この `ClientA` というのは，[工程3](#工程3クライアントごとの鍵ペアと設定ファイルを生成)で定めたクライアント名と一致させてください。`192.168.255.1` はコンテナ内のサーバ側のIPアドレスとして使うので，クライアントのIPアドレスとしては `192.168.255.2`～`192.168.255.254` のいずれかを指定してください。

# その他のメンテナンス作業
## 稼働中のコンテナ内に入ってネットワークの状況を調査するには

```sh:［VPS上で］稼働中のコンテナ内に入ってネットワークの状況を調査する
$ docker exec -it openvpn-udp /bin/bash
```

こうしてコンテナ内に入れば，`ifconfig` や `netstat` で仮想ネットワークの状況調査ができます。

## クライアント証明書を失効させるには

使わなくなったクライアントがあれば，その証明書ではVPN接続できないようにしましょう。「登録を削除する」ということはできず，「証明書を CRL (Certificate Revocation List，証明書失効リスト) に登録する」という手を取ります。

```sh:［VPS上で］ClientAの証明書を失効させる
$ export CLIENTNAME="ClientA"
# revokeしてCRLに登録
$ docker run --rm -it -v $HOME/ovpn-data:/etc/openvpn \
    kylemanna/openvpn easyrsa revoke $CLIENTNAME
$ docker run --rm -it -v $HOME/ovpn-data:/etc/openvpn \
    kylemanna/openvpn easyrsa gen-crl
# その上でOpenVPNサーバを再起動 → CRLが有効化
$ docker compose down
$ docker compose up -d
```