Android端末にOpenVPNクライアントの設定をする

OS: Android 7.0
OpenVPN Connect 3.0.5

Windows10にOpenVPNクライアントの設定を施したら続いてAndroid端末でもOpenVPNで接続したいものである。Androidクライアント用に証明書と秘密鍵を誂える。

$ cd easy-rsa-3.0.5/easyrsa3/
$ ./easyrsa build-client-full android
(snip)
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
(snip)
Enter pass phrase for /home/guro/src/openvpn/easy-rsa-3.0.5/easyrsa3/pki/private/ca.key:

設定ファイルも準備しておく。

$ vi android.ovpn
client
dev             tun
proto           udp
remote          www7390uo.sakura.ne.jp 1194
ca              ca.crt
cert            android.crt
key             android.key
tls-auth        ta.key 1
cipher          AES-256-GCM
remote-cert-tls server
compress        lz4-v2
auth-nocache
nobind

これらのファイルをAndroid端末へ首尾よくコピーする。

$ sudo scp /etc/openvpn/ca.crt /etc/openvpn/ta.key pki/issued/android.crt pki/private/android.key android.ovpn guro@192.168.0.150:/mnt/file

次はAndroid端末を手にしてOpenVPNが作り上げた「OpenVPN Connect – Fast & Safe SSL VPN Client」をインストールする。

OpenVPN Connectを起動。

「OVPN Profile Connect with .ovpn file」をタップ。

端末にコピーした設定ファイルを選択し、「IMPORT」をタップ。

設定内容に誤りが無ければ「Profile successfully imported」であるからあとはプロファイル名を好きに付けてから「ADD」をタップする。設定の都合が悪ければここで具体的なエラー内容が示されるようになっていた。「Save Private Key Password」にチェックをつけると秘密鍵のパスフレーズを入力する箇所が現れる。OpenVPNサーバへ接続する都度、パスフレーズを入力するのが差し支えあるならここで入力しておくと宜しい。

追加したプロファイルをタップすると接続が開始される。右上にある困り顔の一反木綿みたようなピクトグラムはログを表示するためのものであった。

秘密鍵のパスフレーズを保存するよう設定していなければ毎回ここで入力画面が顔を出す。

初回接続時だけ接続要求のメッセージが表示される。ソースを信頼できる場合にのみOKをタップする。

滞りなく接続が完了するとこういう具合に画面が切り替わる。

ところがUbuntu Server 12.04に構築したOpenVPNサーバであると、接続の際に「The certificate is signed with an unacceptable key (eg bad curve, RSA too short)」というようなエラーメッセージが出て処理が終いになってしまった。接続のログをひとしべひとしべ確認してゆくと認証局の鍵が512bitで作成されているようであるが、此れが為にエラーが出ているような雰囲気を感ずる。easyrsaのスクリプトを編集して2048bitで作成されるよう試みたがうまい具合に処理されなかったのでOpenVPNサーバのOpenSSLを1.0.1から1.0.2に刷新したところ問題が解決した。OpenSSLのサイトには1.0.1はもはやサポートされないので使ってはならぬとある。この問題が解決するまでの場当たり的な犯行としてクライアント側の設定ファイルに

tls-cipher "DEFAULT:@SECLEVEL=0"

を追加してしのいでいたが安全を考えると心持ちの良い解決方法ではないのでやはりOpenSSLをアップデートするのがよさそうである。

参考:
{Resolved} openssl new versions consider md certificates too weak
Bug 1425859 – Can’t connect to VPN after upgrade
OpenSSL

Windows10にOpenVPNクライアントの設定をする

OS: Windows 10 Pro ver 1709
OpenVPN GUI for Windows v11.10.0.0

OpenVPNサーバの構築が完了したら次はクライアント側の設定が待ち受けているものである。まずはクライアントの証明書と秘密鍵をこしらえなければならない。これにはeasy-rsaを使えばよろしい。最初に問われるパスフレーズはクライアントの秘密鍵に設定するパスフレーズ、次に聞かれるものは認証局のパスフレーズである。

$ cd easy-rsa-3.0.5/easyrsa3/
$ ./easyrsa build-client-full guro
(snip)
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
(snip)
Enter pass phrase for /home/guro/src/openvpn/easy-rsa-3.0.5/easyrsa3/pki/private/ca.key:

クライアント側の設定ファイルも用意しておく。clientディレクティブによってOpenVPNをクライアントモードで動かすぞと宣言している。設定ファイルの拡張子はovpnにして保存せねばならない。

$ vi vpn.ovpn
client
dev             tun
proto           udp
remote          www7390uo.sakura.ne.jp 1194
ca              ca.crt
cert            guro.crt
key             guro.key
tls-auth        ta.key 1
verb            3
tun-mtu         1500
cipher          AES-256-GCM
remote-cert-tls server
compress        lz4-v2
auth-nocache
nobind

そうしたら必要となるファイルをクライアントマシンへコピーする。認証局の証明書とHMACキー、クライアントの証明書と秘密鍵、そして設定ファイルである。秘密鍵は決して他人にひけらかしてはならないからscpでコピーしたり飛行機と電車を乗り継いてクライアントマシンのところへ肌身離さず持っていくなどするのがよいとおもう。

$ sudo scp /etc/openvpn/ca.crt /etc/openvpn/ta.key pki/issued/guro.crt pki/private/guro.key vpn.ovpn guro@192.168.0.150:/mnt/file

次はクライアントマシンにOpenVPNをインストールする。OpenVPNのDownloadsページからWindowsのインストーラopenvpn-install-2.4.5-I601.exeをダウンロードする。

ダウンロードしたファイルを実行する。

セットアップウィザードが始まるので「Next」をクリック。

ソフトウェア利用許諾契約が表示されるので隅々まで精読してその上で同意を決断するか否かを判断するのがほんとうであろうけれどもいつも億劫になってひとつも読まずに「I Agree」である。

インストールするコンポーネントを選択する。

OpenVPNをインストールするフォルダを決定する。

ネットワークアダプターをインストールする。

インストールが完了したらNextをクリック。

Finishをクリック。

デスクトップに作成されたOpenVPN GUIアイコンをダブルクリック。

設定ファイルが見当たらないとその旨、ダイアログで通知される。設定ファイルを設置する場所は%homepath%\OpenVPN\config%ProgramFiles%\OpenVPN\configであるという。

予め用意しておいたファイルを%homepath%\OpenVPN\configのフォルダへ放り込む。

タスクトレイに潜んでいる、ディスプレイの左上に南京錠がデザインされたアイコンがOpenVPN GUIのそれである。此れを右クリックするとコンテキストメニューがあらわれるから、「接続」をクリック。

クライアントの秘密鍵に設定したキーフレーズをここで入力する。毎回入力するのが億劫だということになれば「Save password」にチェックをつけておくと宜しい。

恙無くOpenVPNサーバへ接続できればその旨、トースト通知が表示される。

ステータスを表示するとこういう具合である。

OpenVPNのオプションについて

OS: Ubuntu Server 16.04
OpenVPN 2.4.5

設定に使用したオプションが一体どういう意味を持つのか今ひとつ呑み込めていないけれども調べた結果をひとまず記録しておくものである。

オプション 内容
port OpenVPNの待受ポート番号を指定。デフォルトは1194。バージョンが2.00-beta17よりも古いOpenVPNはデフォルトが5000。
proto 通信プロトコルを指定。デフォルトはudp。他にtcp-client、tcp-serverの選択肢もある様子であった。
dev 仮想ネットワークデバイスを指定。tunX、tapX、nullから選択。Xはだいたい数値が入るものと思われるけれども省略可能であった。tunはL3、tapはL2。
ca 認証局の証明書(ルート証明書)を指定。
cert サーバ証明書を指定。caで指定した認証局によって署名されたものでなければいけない。
key サーバの秘密鍵を指定。certで指定した証明書とキーペアになるものでなければいけない。
dh Diffie Hellmanパラメータを含むファイルを指定。noneを指定するとDiffie Hellman鍵交換はやめにして楕円曲線Diffie-Hellman鍵共有(ECDH)だけ使う。
tls-auth HMACキーファイルを指定。ファイル名のあとに指定する数値はサーバ側では0、クライアント側では1がよいようである。

server クライアントに割り当てるIPアドレスの範囲をネットワークとネットマスクで指定。server 10.8.0.0 255.255.255.0などと簡単に指定できるけれどもネットワークデバイスがTUNとTAPのどちらであるか、またtopologyの設定は如何なるものかなどによって心持ち挙動が異なってくるようである。
push pushで指定したオプションにせよとサーバーからクライアントに対して伝える。オプションはダブルクオートで括られていないといけない。routeの設定などは各クライアント毎にいちいち書くのは大変なことなのでこのオプションがたいへん役に立つ。
compress VPNでのやりとりするデータを圧縮するのに使用するアルゴリズムを選択する。lzo、lz4または何も指定しない。と説明書に書いてあるけれどもOpenVPN2.4以上であればlv4-v2というものも選択できるようである。lzoよりもlz4-v2のほうがCPUへの負担が小さくてよいという。サンプルの設定ファイルにはlz4-v2が記載されているけれども説明書にはまだ反映されていない模様である。

client-to-client これを有効にするとクライアント同士でのやり取りができるようになる。デフォルトは無効でクライアントはVPNサーバしか見えない。
keepalive pingを放ち接続の死活監視して指定時間を超えてタイムアウトしたら再接続を行う。ping、ping-restartを組み合わせたオプションということであろうと思う。2つの引数を取り、1つ目はpingを送る間隔を秒で指定する。2つ目はタイムアウトとみなす時間を秒で指定する。なおサーバ側では指定した秒の2倍だけタイムアウトするまで待つ。サーバ、クライアント共にこのオプションを使用できるけれども普通はサーバ側にだけ設定しておけば概ねよいようである。サーバにもクライアントにも設定されていたらサーバ側の設定で上書きされるという。
cipher やり取りの際に使用する暗号化のアルゴリズムを指定する。デフォルトはBF-CBCであるけれどもこれは攻撃に弱い様子である。またOpenVPN2.6で削除される予定であるから使わないほうがよいようである。openvpn --show-ciphersコマンドを実行すれば使用できるアルゴリズムがあらわれる。今どきはAES-256-GCMやAES-128-GCMを選択するのが良さそうである。

ncp-ciphers 暗号化に使用するアルゴリズムをどうするかサーバとクライアントでやり取りする際に、ここで指定したものから選択する。コロンで区切って複数指定することができる。デフォルトはAES-256-GCM:AES-128-GCM。双方で使用するアルゴリズムが合意に達するとcipherオプションで指定したものよりこちらが優先される仕組みであった。
tls-version-min TLSのバージョンが此れを下回ると受け入れない。デフォルトは1.0である。他には1.1と1.2が現在のところ選択できる。
tls-cipher TLS接続で使用する暗号化のアルゴリズムを指定する。openvpn --show-tlsでサポートされているアルゴリズムが一覧できる。エキスパート向けの設定であるようであるからうっかり無闇に触ることは大変危険な行為である旨、記載されていた。

But it is also easy to unwittingly use it to carefully align a gun with your foot, or just break your connection. Use
with care!

user OpenVPNプロセスの実行ユーザを指定。
group OpenVPNプロセスの実行グループを指定。
persist-key OpenVPNに再起動が発生しても鍵ファイルを再読込しないようにする。それというのも起動時はroot権限で鍵ファイルを読みにゆけるけれどもそのあとはuserで指定した権限に降格となるから普通、鍵ファイルは読み取れなくなってしまう。そうすると再起動時にたいへん困るから最初に読み込んだ鍵ファイルをそのままキープしておこうという算段のようである。
persist-tun OpenVPNの再起動が発生してもTUN/TAPデバイスを閉じて再度開くことをしないようである。
status OpenVPNサーバに接続しているクライアントやルーティングテーブルの様子を記録するファイルを指定する。デフォルトでは60秒ごとに更新されてゆく。ファイル名のあとに数値を指定すると更新間隔を変更できる。単位は秒である。

log-append OpenVPNのログを記録するファイルを指定する。毎回ファイルがクリアされて新規に記録されるlogオプションと異なって、log-appendはログがどんどん追記されてゆく。
ifconfig-pool-persist 接続しているクライアントのコモンネームと割り当てられたIPアドレスが記録される。というわけではないようである。過去に紐付けられたコモンネームとIPアドレスに基づいて、提案としてだけOpenVPNに扱われるとあるけれども何だかわからない。読み解く力の乏しさが悔やまれる。コモンネームとIPアドレスの紐づけを見るならstatusで指定したファイルで良いと思った。

$ sudo cat /var/log/ipp.txt
guro,10.8.0.4
gero,10.8.0.8
verb 出力するログの冗長さを0~11で指定。0は致命的なエラーを除いてまったくログを出力せず、数値が大きくなるに連れて冗長さが増す。3か4くらいがちょうどよい程度であった。5を超えるとパケットの読み書きが発生するたびにr、w、R、Wの文字が記録される。rwはTUN/TAPパケットを表し、RWはTCP/UDPパケットをあらわすという。ログがべらぼうに見づらくなったので無闇に設定するものじゃないと思った。

参考:
man openvpn
Openvpn2.4 ManPage

OpenVPNサーバを構築する

OS: Ubuntu Server 16.04
OpenVPN 2.4.5
easy-rsa v3.0.5

高度で複雑な仕組みと専門用語におそれをなして及び腰になってしまってから数年間ペンディングしていたOpenVPNの導入であるけれども世論の高まりを受けていよいよ実施するから記録を残しておくものである。まずはソースをダウンロードする。

$ wget -c https://swupdate.openvpn.org/community/releases/openvpn-2.4.5.tar.gz
$ wget -c https://swupdate.openvpn.org/community/releases/openvpn-2.4.5.tar.gz.asc

$ gpg --recv-key AF131CAE
$ gpg --verify openvpn-2.4.5.tar.gz.asc

$ tar zxvf openvpn-2.4.5.tar.gz
$ cd openvpn-2.4.5/

configureを実施する前に必要なパッケージを準備しておかねばならない。さもなくば立て続けにエラーメッセージを頂戴して終いである。なおUbuntu Server 18.04のベータ版では「configure: error: route utility is required but missing」と表示されたのでnet-toolsを要するようであった。iproute2への移行が進んでいることを感ずる。

メッセージ 必要なパッケージ
usable LZ4 library or header not found,
using version in src/compat/compat-lz4.*
liblz4-dev
openssl check failed libssl-dev
lzo enabled but missing liblzo2-dev
libpam required but missing libpam0g-dev
route utility is required but missing net-tools
$ sudo apt install libssl-dev liblz4-dev liblzo2-dev libpam0g-dev
$ ./configure
$ make
$ sudo make install

次はeasy-rsaを用意する。此れで以って認証局を構築したりサーバ、クライアントの証明書や秘密鍵を作成してゆくようである。

$ cd ..
$ wget -c https://github.com/OpenVPN/easy-rsa/archive/v3.0.5.zip -O easy-rsa-v3.0.5.zip
$ unzip -x easy-rsa-v3.0.5.zip
$ cd easy-rsa-3.0.5/easyrsa3/

事始めにinit-pkiコマンドによってpkiディレクトリとprivate、reqsサブディレクトリを作成する。

$ ./easyrsa init-pki

認証局の構築

OpenVPNサーバとは別のマシンに認証局を構築するのがほんとうのところであるとの事であったが、余分に割くリソースがちょっとないのでやむなく同じマシンに作り上げるものである。認証局のパスフレーズをここで定めるのであるが、これを忘れると証明書の発行に差し障りがでるので大切に管理しなければならない。

$ ./easyrsa build-ca
Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
(snip)

/etc/openvpnディレクトリを作成してここへOpenVPNに関連するファイルや設定ファイルを放り込んでゆく方針にする。先ずはさきに作成した認証局の証明書をコピーする。

$ sudo mkdir /etc/openvpn
$ sudo cp pki/ca.crt /etc/openvpn/

サーバの証明書と秘密鍵作成

サーバの証明書と秘密鍵をこさえる。./easyrsa build-server-full server nopassのserverの箇所はファイル名となるもののようである。例えばここをopenvpnに変更すればopenvpn.keyとopenvpn.crtが出来上がるというわけである。nopassはサーバの秘密鍵を暗号化せずに運用するものである。暗号化するとOpenVPN起動のたびにパスフレーズを入力する必要に迫られる。

$ ./easyrsa build-server-full server nopass
(snip)
Enter pass phrase for /home/guro/src/openvpn/easy-rsa-3.0.5/easyrsa3/pki/private/ca.key:

$ sudo cp pki/issued/server.crt pki/private/server.key /etc/openvpn/

作成には認証局のパスフレーズが問われるので正確に入力する。これを間違えるとエラーが出て終いであるが、改めて作成を試みると前回の証明書署名要求ファイルと秘密鍵が置き去りのままである為に「Request file already exists.」というエラーメッセージが現れて先へ進まないからこれらを削除してしまうのが良いようである。

$ rm pki/reqs/server.req pki/private/server.key

Diffie-Hellmanパラメータの生成

一体どういうパラメータなのかちょっと知れないが前方秘匿性という性質で以って持て囃されているようである。マシンパワーもさることながら巡り合わせによってはまことに暇のかかる処理であるから、コマンドを実行したらしばらくお茶にでも出掛けるのが良かろうと思う。

$ ./easyrsa gen-dh
$ sudo cp pki/dh.pem /etc/openvpn/

中身をつぶさに見てゆくならこうである。2048bitもの巨大な素数primeとgeneratorが鍵交換のために使われるようである。これらの値は悪いやつに知られてしまっても構わないようである。

$ sudo openssl dh -text -in /etc/openvpn/dh.pem
    DH Parameters: (2048 bit)
        prime:
            00:fd:fe:1c:09:f4:03:49:3e:69:e5:45:4a:51:ff:
            7f:2b:c9:3b:59:18:e0:7e:86:79:e8:d6:09:15:3a:
            dc:8e:27:7f:f2:6b:e1:08:21:33:ba:71:4e:54:d3:
(snip)
            05:c5:b0:e3:ef:1b:1b:d0:58:1e:bc:88:8f:4e:be:
            f9:3f:2e:45:d7:7e:0e:e4:5e:80:e6:3e:d1:9c:d8:
            d9:fd:5b:a7:10:2a:d9:9f:f3:c2:45:a7:48:a6:0d:
            7c:4b
        generator: 2 (0x2)

HMACキーの作成

HMACとはHash-based Message Authentication Codeの略称のようである。大変長い。目がまわる。これはUDPポートフラッディング攻撃のようなDoS攻撃などを未然に防ぐために役立つようである。

$ sudo openvpn --genkey --secret /etc/openvpn/ta.key

設定ファイルの編集

サンプルの設定ファイルが準備されているのでこれをコピーし、環境に合わせて設定を施してゆくのが良かろうと思う。

$ cd ../../openvpn-2.4.5/sample/sample-config-files/
$ sudo cp server.conf /etc/openvpn/

多くの設定項目があるので大変難儀したけれども概ねこういう具合に落ち着いた。

$ sudo vi /etc/openvpn/server.conf
port                  1194
proto                 udp
dev                   tun
ca                    /etc/openvpn/ca.crt
cert                  /etc/openvpn/server.crt
key                   /etc/openvpn/server.key
dh                    /etc/openvpn/dh.pem
tls-auth              /etc/openvpn/ta.key 0
server                10.8.0.0 255.255.255.0
push                  "route 10.8.0.0 255.255.255.0"
push                  "redirect-gateway def1 bypass-dhcp"
push                  "dhcp-option DNS 8.8.4.4"
push                  "compress lz4-v2"
compress              lz4-v2
client-to-client
keepalive             10 120
cipher                AES-256-GCM
ncp-ciphers           AES-256-GCM
tls-version-min       1.2
tls-cipher            TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
user                  openvpn
group                 openvpn
persist-key
persist-tun
status                /var/log/openvpn-status.log
log-append            /var/log/openvpn.log
ifconfig-pool-persist /var/log/ipp.txt
verb                  4

OpenVPNの実行ユーザとグループをopenvpnにセットしたので実際に作成しておく。

$ sudo useradd -s /bin/false openvpn

ipフォワードを有効にしてiptablesで以ってIPマスカレードの設定をする。こうすることでクライアントがサーバ側のセグメントにあるマシンとやり取りできるようになるようである。

$ sudo vi /etc/sysctl.conf
#net.ipv4.ip_forward=1
net.ipv4.ip_forward=1

$ sudo sysctl -p
net.ipv4.ip_forward = 1

$ sudo iptables -A POSTROUTING -t nat -s 10.8.0.0/24 -o ens33 -j MASQUERADE

あとは起動を試みてエラーがでなければサーバの構築は完了である。

$ sudo openvpn --config /etc/openvpn/server.conf --daemon

参考:
基本的なOpenVPNの構築手順
OpenVPN – Open Source VPN
OpenVPN/easy-rsa
Easy-RSA – ArchWiki