OpenVPNでキャリアNAT超えで自宅LANに接続できるようにする

### 2022-07-30追記: 後日談を追記しました
環境によっては以下の手順でも動かないかもしれません。以下の記事を参照してみてください。
[結局キャリアグレードNATに敗北し5Gルータを入れた話](https://qiita.com/daredeshow/items/720ddba1b425496eeb96)
# 動機
もともと自宅のサーバにOpenVPNを入れて外出先から自宅が見えるようにしていて。外出先から自宅の中のメールサーバを見たり、録画しておいた番組を見たり、sshでログインできると幸せだ。今年になってマンション管理会社の方針(管理費のコスト削減)でマンションのインターネットプロバイダが変わることになった。説明会で話を聞いてみると、なんと(ついに)自宅に付与されるアドレスがプライベートIPアドレスになってしまうらしい。いわゆる[キャリアグレードNAT](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%AA%E3%82%A2%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89NAT)だ。ほとんどの用途で問題ないとはプロバイダ担当氏の説明であるのだが、私の利用用途はたぶん担当氏の想定外なんだろうな・・・と思いながらもそれをことさらに言いたてることもせず(どうせ言っても理解してくれないし、理解してくれたところで解決策もなく徒にマンションの同居世帯の和を乱すだけ)、自力で解決策を探ることにした。

自前で自室までフレッツを引き込むとかはマンション内で賛同者集めたり管理組合の許可が必要なので手間がかかる。LTEの回線にするということも考えたのだがあまり気が乗らなかった。とりあえず外から自宅が見れれば及第点ということにして方策を探ってみると、まあ順当に考えればクラウドとかに出島を作って双方からつなぐしかないよね、ということになる。要するにこういう通信をしたい。
![191112-OpenVPN-AWS-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52237/66e19531-b698-3f4c-6f45-4d3bc69603e4.png)

で、結論を言えばできたので結果を共有する。

# 結論だけ読んで帰りたい人用の記述
結論だけ言うと [OpenVPN - Expanding the scope of the VPN to include additional machines on either the client or server subnet. (https://openvpn.net/community-resources/how-to/#expanding-the-scope-of-the-vpn-to-include-additional-machines-on-either-the-client-or-server-subnet)](https://openvpn.net/community-resources/how-to/#expanding-the-scope-of-the-vpn-to-include-additional-machines-on-either-the-client-or-server-subnet) の手順でできる。これでわかる人は特にこの下を読む必要はない。

とは言うもののこの記事には絵もないし正直正解を見付けるのに苦労したし日本で同じことしてる記事とかがほとんどひっかからなかったので、改めて日本語で解説しておくと同じような困り事を持っている人の助けになるのでは・・・と。

AWSであれば謹製のOpenVPNサービス(AWS Client VPN)もあるようだが、いくつかの理由で使用しなかった。理由は後述する。

# OpenVPNの構成パターン
この構成は、site-to-site構成のバリエーションの一つと言えるかもしれない。接続の片側は自宅で、GWがOpenVPNクライアントになる。ただし自宅LAN内の全ての機器はOpenVPNを意識することなくVPN経由の疎通ができなければいけない。もう片方は普通のパソコンで、OpenVPNクライアントとなる。

OpenVPNのpoint-to-pointの構成パターンで `push route 192.168.20.0 255.255.255.0` とかしてしまうと、パソコン側の方はいいのだが自宅LAN側はOpenVPNクライアントの接続を確立した時点でLAN内の疎通ができなくなる。今回の設定はこの部分が少し工夫されている。

# 設定手順
ここから実際の設定を記述する。

## OpenVPNサーバの設定
今回OpenVPNサーバはAWSにたてた。別にAzureでもGCPでも好きなものを使えばいいと思う。

### インスタンスの作成

AWSの場合今回はt3a.nanoのスポットインスタンスを使ってコストをできるだけ安くした。多分月額500円程度にできるんじゃないかな。メモリが512MBしかないけど、今のところ動作には支障はなさそう。

VPCを作って、サブネットをつくる。インスタンスを作る時には当然だけどグローバルIPを付与する。OSはAmazon Linuxにした。

セキュリティグループは以下のような設定にした。443/udpはOpenVPNの受付ポートとして使う。なんで443/udpにしているかというと、出先の環境によってはOpenVPNのデフォルトポートである 1194/udp が閉じられていることがあるから。443であればほとんどの環境でポートは開いていると思う。UDP狙いうちで閉じていることも可能性としてなくはないけど。

- 許可
    - ssh: 0.0.0.0/0
    - 443/udp: 0.0.0.0/0

### インストール

インスタンスが起動したらOpenVPNを入れる。

```shell
$ sudo su -
# amazon-linux-extras install epel
# yum -y install openvpn easy-rsa firewalld NetworkManager
# reboot
```

### ネットワークの設定

IP Masqueradeの設定をする。OpenVPNの受付用に443/udpを開いている。

```shell
# firewall-cmd --list-all-zones
  -> zone publicにeth0が所属していることを確認する。
     していなかったら nmcli c mod eth0 connection.zone public で所属させる
# firewall-cmd --zone=public --add-masquerade --permanent
# firewall-cmd --add-port=443/udp --zone=public --permanent
# firewall-cmd --reload
# firewall-cmd --list-all-zones
(以下のようになっていればOK)
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: ssh dhcpv6-client
  ports: 443/udp
  protocols: 
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

```

### OpenVPNで使うキーを作成

```shell
# cd /usr/share/easy-rsa/3.0.6

===(初期化)===
# ./easy-rsa init-pki

===(DHの作成)===
# ./easy-rsa gen-dh
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...................(略).................+................++*++*

DH parameters of size 2048 created at /usr/share/easy-rsa/3.0.6/pki/dh.pem

# mv pki/dh.pem pki/dh2048.pem

===(CAの作成, Common Nameに入れる文字はなんでもよい)===
# ./easy-rsa build-ca nopass
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating RSA private key, 2048 bit long modulus
..+++
....................+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:openvpn

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/usr/share/easy-rsa/3.0.6/pki/ca.crt

===(サーバ証明書の作成。これはOpenVPNサーバで使用する)===
# ./rasy-rsa build-server-full server nopass
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
..............................................+++
........+++
writing new private key to '/usr/share/easy-rsa/3.0.6/pki/privat/server.key.bZ6CtKC2sd'
-----
Using configuration from /usr/share/easy-rsa/3.0.6/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
commonName            :ASN.1 12:'server'
Certificate is to be certified until Oct 26 04:00:57 2022 GMT (1080 days)

Write out database with 1 new entries
Data Base Updated

===(クライアント証明書その1の作成。これは自宅LAN側で使用する)===
# ./easy-rsa build-client-full client1 nopass
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
.............+++
......................................................................................................................................................................................+++
writing new private key to '/usr/share/easy-rsa/3.0.6/pki/priva/client1.key.kqscbvbrB5'
-----
Using configuration from /usr/share/easy-rsa/3.0.6/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
commonName            :ASN.1 12:'client1'
Certificate is to be certified until Oct 26 04:01:28 2022 GMT (1080 days)

Write out database with 1 new entries
Data Base Updated

===(クライアント証明書その2の作成。これは端末のパソコン(上図の左側の端末)で使用する)===
# ./easy-rsa build-client-full client2 nopass
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
.............+++
......................................................................................................................................................................................+++
writing new private key to '/usr/share/easy-rsa/3.0.6/pki/private/client2.key.kqscbvbrB5'
-----
Using configuration from /usr/share/easy-rsa/3.0.6/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
commonName            :ASN.1 12:'client2'
Certificate is to be certified until Oct 26 04:01:28 2022 GMT (1080 days)

Write out database with 1 new entries
Data Base Updated

===(最終的にできたキーは以下のようになっている)===
# tree
.
├── easyrsa
├── openssl-easyrsa.cnf
├── pki
│   ├── ca.crt
│   ├── certs_by_serial
│   │   ├── 3590DFCD7D4AF96D9443E87E0E148A3B.pem
│   │   ├── 56E0697726AB4AC60BD47BACFEFD872D.pem
│   │   └── 7F9E6544685DBD784094E57549AB2832.pem
│   ├── dh2048.pem
│   ├── extensions.temp
│   ├── index.txt
│   ├── index.txt.attr
│   ├── index.txt.attr.old
│   ├── index.txt.old
│   ├── issued
│   │   ├── client1.crt
│   │   ├── client2.crt
│   │   └── server.crt
│   ├── openssl-easyrsa.cnf
│   ├── private
│   │   ├── ca.key
│   │   ├── client1.key
│   │   ├── client2.key
│   │   └── server.key
│   ├── renewed
│   │   ├── certs_by_serial
│   │   ├── private_by_serial
│   │   └── reqs_by_serial
│   ├── reqs
│   │   ├── client1.req
│   │   ├── client2.req
│   │   └── server.req
│   ├── revoked
│   │   ├── certs_by_serial
│   │   ├── private_by_serial
│   │   └── reqs_by_serial
│   ├── safessl-easyrsa.cnf
│   ├── serial
│   └── serial.old
└── x509-types
    ├── ca
    ├── client
    ├── code-signing
    ├── COMMON
    ├── server
    └── serverClient
```

OpenVPNサーバに必要なキーをコピーする

```shell
# cp pki/ca.crt pki/dh2048.pem pki/issued/server.crt pki/private/server.key /etc/openvpn
```

### OpenVPNサーバの設定

テンプレートをベースに編集する

```shell
# cp /usr/share/doc/openvpn-2.4.7/sample/sample-config-files/server.conf /etc/openvpn/server.conf
```

以下のようにする(以下の出力はコメント行、空行を省略している)

```shell
# grep -v "^#" /etc/openvpn/server.conf | grep -v "^;" | sed '/^$/d'
port 443
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0
# 自宅LAN側の設定
client-config-dir ccd
route 192.168.20.0 255.255.255.0
client-to-client
# 自宅LAN側のサブネット、DNSを広告
push "route 192.168.20.0 255.255.255.0"
push "dhcp-option DNS 192.168.20.254"
# クラウド側のサブネット、DNSを広告(省略可)
push "route 172.30.0.0 255.255.255.0"
push "route 172.30.1.0 255.255.255.0"
push "dhcp-option DNS 172.30.0.2"
keepalive 10 120
cipher AES-256-CBC
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
log-append  openvpn.log
verb 3
explicit-exit-notify 1
```

`/etc/openvpn` 以下に `ccd` というディレクトリを作成する。

```shell
# mkdir /etc/openvpn/ccd
```

`/etc/openvpn/ccd` の中に `client1` というファイルを作る。内容は以下のようにする。

```shell
# cat /etc/openvpn/ccd/client1
iroute 192.168.20.0 255.255.255.0
```

`iroute`はOpenVPNサーバが、この証明書で接続してきたクライアントがどのサブネットに属しているのかを認識する。`route`はOpenVPNサーバのLinuxカーネルが自宅LANサブネットをTUNデバイスにルーティングさせるために使用される。似ている記述だけど役割が異なる。

最後に `client-to-client`でクライアント間の疎通を許し, `push "route 192.168.20.0 255.255.255.0"`でclient1以外のクライアントに対して自宅LANのサブネットへのアクセスにOpenVPNトンネルを使用するように広告する。

`comp-lzo`は趣味で入れている。外しても良い。外す場合はクライアントの設定も合わせること(後述)。`user nobody`, `group nobody`もそう。

### OpenVPNサーバの起動

```shell
# systemctl enable openvpn@server
# systemctl start openvpn@server
```

うまく起動しなかったら `/etc/openvpn/openvpn.log`を見て各自がんばる。

## 自宅LAN側OpenVPNクライアントの設定

次に自宅LAN側のGWにOpenVPNクライアントを設定する。今回自宅LANのGWはRaspberry Pi 3上でOpenWRTを動かしている。

まず使用するパッケージをインストールする。

```shell
# opkg install openvpn-openssl
# opkg install screen
```

OpenVPNサーバ上で作成した `ca.crt`, `client1.crt`, `client1.key`をそれぞれ見れる状態にする。(OpenWRT上にコピーする必要はない)

以下のような設定ファイルを作成する。この例ではファイル名は `/root/openvpn-client1.conf` としている。`<ca>..</ca>`, `<cert>..</cert>`, `<key>..</key>`の内容はそれぞれ `ca.crt`, `client1.crt`, `client1.key`の内容になる。`client1.crt`だけ内容全部ではないので注意。`-----BEGIN CERTIFICATE-----` から `-----END CERTIFICATE-----` の間だけコピーする。

```shell
# cat /root/openvpn-client1.conf
client
dev tun
proto udp
remote OpenVPNサーバのグローバルIPアドレス 443
resolv-retry infinite
nobind
persist-key
persist-tun
comp-lzo
verb 3
<ca>
-----BEGIN CERTIFICATE-----
MIIDKDC (略) G2oaM+mUaCgmph8=
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIIDQj (略) YQnWvL3dl5w==
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIE (略) VolLqc
-----END PRIVATE KEY-----
</key>
```

またIP Forwardingを有効にし、ファイアーウォールの設定も適切に設定する。OpenWRTの場合は以下の部分をACCEPTに変更しておく。
![Screenshot from 2019-11-13 01-41-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52237/610f6dd6-26db-9a46-8102-e67117f5eaff.png)


### 接続

GWからOpenVPNサーバに接続する。

```shell
# openvpn --config /root/openvpn-client1.conf
Wed Nov 13 01:34:32 2019 OpenVPN 2.4.5 aarch64-openwrt-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD]
Wed Nov 13 01:34:32 2019 library versions: OpenSSL 1.0.2s  28 May 2019, LZO 2.10

(略)

Wed Nov 13 01:34:32 2019 UDP link remote: [AF_INET]13.113.223.169:443
Wed Nov 13 01:34:32 2019 TLS: Initial packet from [AF_INET]13.113.223.169:443, sid=99826a3f 58b718da
Wed Nov 13 01:34:32 2019 VERIFY OK: depth=1, CN=openvpn
Wed Nov 13 01:34:32 2019 VERIFY OK: depth=0, CN=server

(略)

Wed Nov 13 01:34:33 2019 Initialization Sequence Completed
```

とりあえず上記のような `Initialization Sequence Completed` が出ていれば接続は成功している。起動時のメッセージには他にもどのようなルート情報が広告されているかなど記述されているので、見ておくにこしたことはない。

OpenVPNの接続が確立した後の各NEIF, ルーティング情報は以下のような感じになっている。

```shell
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
    link/ether b8:27:eb:9b:73:02 brd ff:ff:ff:ff:ff:ff
    inet 172.22.1.14/21 brd 172.22.7.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::ba27:ebff:fe9b:7302/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br-lan state UP qlen 1000
    link/ether 00:1d:73:68:32:6f brd ff:ff:ff:ff:ff:ff
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br-lan state UP qlen 1000
    link/ether b8:27:eb:ce:26:57 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::ba27:ebff:fece:2657/64 scope link 
       valid_lft forever preferred_lft forever
5: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 00:1d:73:68:32:6f brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.254/24 brd 192.168.20.255 scope global br-lan
       valid_lft forever preferred_lft forever
    inet6 fd6a:6a60:4c5a::1/60 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::21d:73ff:fe68:326f/64 scope link 
       valid_lft forever preferred_lft forever
10: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 100
    link/[65534] 
    inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::289f:4ba:23bc:b32f/64 scope link 
       valid_lft forever preferred_lft forever

# ip route show
default via 172.22.0.1 dev eth0  src 172.22.1.14 
10.8.0.0/24 via 10.8.0.5 dev tun0 
10.8.0.5 dev tun0 scope link  src 10.8.0.6 
172.22.0.0/21 dev eth0 scope link  src 172.22.1.14 
172.30.0.0/24 via 10.8.0.5 dev tun0 
172.30.1.0/24 via 10.8.0.5 dev tun0 
192.168.20.0/24 dev br-lan scope link  src 192.168.20.254 
```

### 疎通テスト

疎通確認する。まずは自宅LAN内のGW以外のホストから、OpenVPNサーバまで疎通しているか確認する。

```shell
[my@lan-pasokon ~]$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 6c:4b:90:5b:40:30 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.240/24 brd 192.168.20.255 scope global dynamic noprefixroute enp3s0
       valid_lft 30242sec preferred_lft 30242sec
    inet6 fd6a:6a60:4c5a::f2b/128 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fd6a:6a60:4c5a:0:f9d:43ed:822a:e33c/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::dc73:9883:5e2b:224e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 0a:52:03:fe:20:68 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:9d:4b:af brd ff:ff:ff:ff:ff:ff


[my@lan-pasokon ~]$ ip route show
default via 192.168.20.254 dev enp3s0 proto dhcp metric 100 
192.168.20.0/24 dev enp3s0 proto kernel scope link src 192.168.20.240 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown 


[my@lan-pasokon ~]$ ping 172.30.1.64
PING 172.30.1.64 (172.30.1.64) 56(84) バイトのデータ
64 バイト応答 送信元 172.30.1.64: icmp_seq=1 ttl=254 時間=14.9ミリ秒
64 バイト応答 送信元 172.30.1.64: icmp_seq=2 ttl=254 時間=27.2ミリ秒
64 バイト応答 送信元 172.30.1.64: icmp_seq=3 ttl=254 時間=14.8ミリ秒
^C
--- 172.30.1.64 ping 統計 ---
送信パケット数 3, 受信パケット数 3, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 14.760/18.954/27.203/5.833 ms
```

クラウド(AWS)上のDNSが参照できるか確認する

```shell
[my@lan-pasokon ~]$ nslookup
> server
Default server: 192.168.20.254
Address: 192.168.20.254#53
Default server: fd6a:6a60:4c5a::1
Address: fd6a:6a60:4c5a::1#53
> server 172.30.0.2
Default server: 172.30.0.2
Address: 172.30.0.2#53
> www.google.com
Server:		172.30.0.2
Address:	172.30.0.2#53

Non-authoritative answer:
Name:	www.google.com
Address: 216.58.197.196
Name:	www.google.com
Address: 2404:6800:4004:80c::2004
> ec2-13-113-223-169.ap-northeast-1.compute.amazonaws.com
Server:		172.30.0.2
Address:	172.30.0.2#53

Non-authoritative answer:
Name:	ec2-13-113-223-169.ap-northeast-1.compute.amazonaws.com
Address: 172.30.1.64
> 
```

クラウド上のOpenVPNサーバから自宅LAN内のパソコンに疎通していることを確認する。

```shell
[ec2-user@ip-172-30-1-64 ~]$ ping 192.168.20.240
PING 192.168.20.240 (192.168.20.240) 56(84) bytes of data.
64 bytes from 192.168.20.240: icmp_seq=1 ttl=63 time=16.7 ms
64 bytes from 192.168.20.240: icmp_seq=2 ttl=63 time=16.6 ms
64 bytes from 192.168.20.240: icmp_seq=3 ttl=63 time=29.6 ms
^C
--- 192.168.20.240 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 16.663/21.017/29.658/6.111 ms

[ec2-user@ip-172-30-1-64 ~]$ host 192.168.20.240 192.168.20.254
Using domain server:
Name: 192.168.20.254
Address: 192.168.20.254#53
Aliases: 

240.20.168.192.in-addr.arpa domain name pointer lan-pasokon.int.mkiuchi.org.
```

## 外出先OpenVPNクライアントの設定

以下のような設定ファイルを作成する。`<ca>..</ca>`, `<cert>..</cert>`, `<key>..</key>`の内容はそれぞれ `ca.crt`, `client2.crt`, `client2.key`の内容になる。

```shell
client
dev tun
proto udp
remote OpenVPNサーバのグローバルIPアドレス 443
resolv-retry infinite
nobind
persist-key
persist-tun
comp-lzo
verb 3
<ca>
-----BEGIN CERTIFICATE-----
MIIDKD (略) mUaCgmph8=
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIIDQ (略) dKYuyA==
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEv (略) Usc47tpw=
-----END PRIVATE KEY-----
</key>
```

クライアントのOSによってこの先の設定は変わってくる。`openvpn windows` なり、 `openvpn mac` なりでぐぐって頂くとどのように設定すれば良いかは出てくるので各自頑張っていただく。

### 接続確認

接続したら、自宅LANの内容を見ることができるかを確認する。

![スクリーンショット (231).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52237/8baa1717-dd0f-8a8a-ade4-7d59ae410b61.png)

# コストなど

最後にコストなどについて記述する。試算上は以下のような感じ。月800円くらい。
![Screenshot from 2019-11-13 02-48-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52237/b8cc7864-0ac1-cbc9-c8a7-f817e80890f5.png)

今回スポットインスタンスを使っているので実際にはもう少し安くなると思う。月500円切ったらいいな、と。

あとAWS謹製のOpenVPNサービス AWS Client VPNは非常に高い。1サブネット接続でだいたい月30,000円くらいかかる。最初これ設定して1週間くらいしてコスト内訳見た時思わず声が出てしまった。痛い勉強代。AWSは全般的にそうだけど個人で気軽にジャンジャン使えるような値段設定じゃないのでおっかなびっくり使わないと、というイメージ。それ言ったらAzureもGCPもそうだけど。まあ気を付けましょうね、と。あと接続ごとにエンドポイント作らなければいけなかったり、使い勝手がイマイチ。今回のインスタンスでやる方法だったら接続の制限もあまりないし、AWS内部の疎通も特に制限はないし、コスト重視の人にはいいんじゃないかな、と。

レイテンシが気にならない人であればGCPの無料インスタンスでやるという手もある。試してないけど(参考: [GCEのf1-microインスタンスを真にタダで使う方法](https://qiita.com/hnw/items/a4e395d047b382e7dc5f))。最近は[Oracle Cloudでもタダでインスタンスが使えるようになった](https://www.itmedia.co.jp/news/articles/1909/17/news076.html)の？知らんけど。

# さいごに

遭遇してはじめてわかるキャリアグレードNATの不便さ。健闘を祈ります。もっとリーズナブルにできる方法あったら教えてください。