外出先から家の家計簿サーバにアクセスするのに昨年SSHフォワードのVPN環境を作りました。
非常にお手軽に作れて使い勝手も悪くないのですが、他のサーバにもアクセスしたくなるかもしれません。
ConnectBotでAndroidの簡易VPNを作る - paloma blog
本当はNWエンジニアらしくIPsecを張りたいのですが、自宅で使っているキャリアのレンタルルータがUDPをNATしない仕様の様なのでSSHにしたのですが、
やはり本物のVPN環境がほしいところ。
※レンタルルータの設定手順がなにか間違っていた可能性がありますが、UDPのNATはしないものとして進めています。
いろいろ考えてTCPのVPNといったらSSLVPNだよねということでOPENVPNで作ってみることにしました。
昔仕事でFortigateでSSLVPN環境を作ったことはありますが、サーバでは初めて。
というわけで作成記です。
最適解と考えたのは構築の難易度ではなくルータの件など環境面の方でいろいろ融通が効きそうだと思ったからです。
ちなみに拠点間ではなくスマホから自宅環境へのアクセスを想定しています。
参考手順。
www.digitalocean.com
環境
いつものubuntu環境です。
masashi@PC-ubuntu:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.4 LTS Release: 20.04 Codename: focal masashi@PC-ubuntu:~$ openvpn --version | head -3 OpenVPN 2.4.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Mar 22 2022 library versions: OpenSSL 1.1.1f 31 Mar 2020, LZO 2.10 Originally developed by James Yonan
CA局での操作
サーバ証明書作成
以前作った自宅CA局があるのでこちらを使って発行します。
easy-rsaで簡単に自宅CA構築+自己証明書発行 - paloma blog
CA証明書は作成済みなのでサーバ証明書を発行します。
サーバ鍵作成
root@HomeCA:~/easy-rsa/csr# openssl genrsa -out vpnserver.key Generating RSA private key, 2048 bit long modulus (2 primes) .........................................+++++ .....................................................................+++++ e is 65537 (0x010001)
CSR作成
今の所ドメイン取得は考えていないのでCommon NameはIP直書きにします。
一応個人情報周りマスクします。
root@HomeCA:~/easy-rsa/csr# openssl req -new -key vpnserver.key -out vpnserver.req \ > -subj /C=JP/ST=xxxxx/L=xxxxx\ shi/O=Home\ labo/CN=118.xxx.xxx.xxx
作成完了。
server.xxxのファイルは以前作成したもので関係ありません。
root@HomeCA:~/easy-rsa/csr# ls -l total 8 -rw------- 1 root root 1675 Jun 26 2021 server.key -rw-r--r-- 1 root root 1005 Jun 26 2021 server.req -rw------- 1 root root 1679 Jun 1 10:00 vpnserver.key -rw-r--r-- 1 root root 997 Jun 1 10:02 vpnserver.req
署名
まずはCSRをインポートします。
root@HomeCA:~/easy-rsa# ./easyrsa import-req csr/vpnserver.req openvpn Note: using Easy-RSA configuration from: ./vars Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020 The request has been successfully imported with a short name of: openvpn You may now use this name to perform signing operations on this request.
署名。
easy-rsaはopensslの難しいコマンドを覚えなくていいので楽ですね。
root@HomeCA:~/easy-rsa# ./easyrsa sign-req server openvpn Note: using Easy-RSA configuration from: ./vars Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020 You are about to sign the following certificate. Please check over the details shown below for accuracy. Note that this request has not been cryptographically verified. Please be sure it came from a trusted source or that you have verified the request checksum with the sender. Request subject, to be signed as a server certificate for 365 days: subject= countryName = JP stateOrProvinceName = xxxxx localityName = xxxxx shi organizationName = Home labo commonName = 118.xxx.xxx.xxx Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes Using configuration from /root/easy-rsa/pki/safessl-easyrsa.cnf Check that the request matches the signature Signature ok (略) Certificate is to be certified until Jun 1 10:06:55 2023 GMT (365 days) Write out database with 1 new entries Data Base Updated Certificate created at: /root/easy-rsa/pki/issued/openvpn.crt
手順上ta.keyをいうのも作成必要なので作ります。
(これは何か後で調べる)
masashi@PC-ubuntu:/tmp$ openvpn --genkey --secret ta.key masashi@PC-ubuntu:/tmp$ ls -l ta.key -rw------- 1 masashi masashi 636 6月 1 20:13 ta.key
これで証明書作成は完了です。
クライアント証明書作成
つづいてクライアント証明書を作ります。
これをスマホに入れることになります。
証明書と鍵ペア作成。
root@HomeCA:~/easy-rsa# ./easyrsa gen-req client1 nopass Note: using Easy-RSA configuration from: ./vars Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020 Generating a RSA private key ...............................................................................................+++++ ..................................+++++ writing new private key to '/root/easy-rsa/pki/private/client1.key.hPbmaswwty' ----- (略) ----- Common Name (eg: your user, host, or server name) [client1]: Keypair and certificate request completed. Your files are: req: /root/easy-rsa/pki/reqs/client1.req key: /root/easy-rsa/pki/private/client1.key
CSRインポートしようとしましたが、上記実行時にディレクトリに作成されるようです。
root@HomeCA:~/easy-rsa# ./easyrsa import-req pki/reqs/client1.req client1 Note: using Easy-RSA configuration from: ./vars Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020 Easy-RSA error: Unable to import the request as the destination file already exists. Please choose a different name for your imported request file. Existing file at: /root/easy-rsa/pki/reqs/client1.req
署名。
root@HomeCA:~/easy-rsa# ./easyrsa sign-req client client1 (略) subject= commonName = client1 (略) Write out database with 1 new entries Data Base Updated Certificate created at: /root/easy-rsa/pki/issued/client1.crt
ホスト側での操作
OPENVPN構築
パッケージのインストールは割愛します。
作成した証明書をホスト側に移動しました。
ディレクトリの中身はこんな感じです。
client側のファイルはローカルでの確認用に用意しました。
masashi@PC-ubuntu:/etc$ tree openvpn openvpn ├── client │ ├── ca.crt │ ├── client.conf │ ├── client.conf.org #デフォルトとして退避 │ ├── client1.crt │ ├── client1.key │ └── ta.key ├── server │ ├── ca.crt │ ├── openvpn.crt │ ├── openvpn.key │ ├── server.conf │ ├── server.conf.org #デフォルトとして退避 │ └── ta.key └── update-resolv-conf
server.conf、client.confをそれぞれ編集します。
変更内容は以下の通り。
手順のままなので特にチューニングはしていません。
- server.conf
masashi@PC-ubuntu:/etc/openvpn/server$ diff -u server.conf{.org,} | grep -E '^(\+|\-)' --- server.conf.org 2022-06-01 19:41:13.562980184 +0900 +++ server.conf 2022-06-01 19:47:07.182377795 +0900 -port 1194 +port 443 -;proto tcp -proto udp +proto tcp +;proto udp -cert server.crt -key server.key # This file should be kept secret +cert vpnserver.crt +key vpnserver.key # This file should be kept secret -dh dh2048.pem +;dh dh2048.pem +dh none -;push "redirect-gateway def1 bypass-dhcp" +push "redirect-gateway def1 bypass-dhcp" -tls-auth ta.key 0 # This file is secret +;tls-auth ta.key 0 # This file is secret +tls-crypto ta.key -cipher AES-256-CBC +;cipher AES-256-CBC +cipher AES-256-GCM + +auth SHA256 -;user nobody -;group nogroup +user nobody +group nogroup -explicit-exit-notify 1 +explicit-exit-notify 0
- client.conf
masashi@PC-ubuntu:/etc/openvpn/client$ diff -u client.conf{.org,} | grep -E '^(\+|\-)' --- client.conf.org 2022-06-03 19:58:49.312388881 +0900 +++ client.conf 2022-06-04 04:42:36.750973040 +0900 -;proto tcp -proto udp +proto tcp +;proto udp -remote my-server-1 1194 +remote localhost 443 -;user nobody -;group nogroup +user nobody +group nogroup -cert client.crt -key client.key +cert client1.crt +key client1.key -tls-auth ta.key 1 +;tls-auth ta.key 1 -cipher AES-256-CBC +cipher AES-256-GCM +auth SHA256 + +# key direction +key-direction 1 +
接続テスト
まずはホスト環境のみで接続テストしてみます。
デーモンではなくコマンド経由でサーバ起動してログ等見ます。
masashi@PC-ubuntu:/etc/openvpn/server$ sudo openvpn --config server.conf Fri Jun 3 19:36:51 2022 OpenVPN 2.4.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Mar 22 2022 Fri Jun 3 19:36:51 2022 library versions: OpenSSL 1.1.1f 31 Mar 2020, LZO 2.10 Fri Jun 3 19:36:51 2022 NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x. Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet. Fri Jun 3 19:36:51 2022 Outgoing Control Channel Encryption: Cipher 'AES-256-CTR' initialized with 256 bit key Fri Jun 3 19:36:51 2022 Outgoing Control Channel Encryption: Using 256 bit message hash 'SHA256' for HMAC authentication Fri Jun 3 19:36:51 2022 Incoming Control Channel Encryption: Cipher 'AES-256-CTR' initialized with 256 bit key Fri Jun 3 19:36:51 2022 Incoming Control Channel Encryption: Using 256 bit message hash 'SHA256' for HMAC authentication Fri Jun 3 19:36:51 2022 ROUTE_GATEWAY 192.168.0.1/255.255.255.0 IFACE=enp2s0 HWADDR=6c:62:6d:e9:65:56 Fri Jun 3 19:36:51 2022 TUN/TAP device tun0 opened (略) Fri Jun 3 19:36:51 2022 Initialization Sequence Completed
OK。サーバは立ち上がりました。
クライアント側
同じ手順でクライアント側も起動。
masashi@PC-ubuntu:/etc/openvpn/client$ sudo openvpn --config client.conf Sat Jun 4 04:43:08 2022 OpenVPN 2.4.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Mar 22 2022 Sat Jun 4 04:43:08 2022 library versions: OpenSSL 1.1.1f 31 Mar 2020, LZO 2.10 Sat Jun 4 04:43:08 2022 TCP/UDP: Preserving recently used remote address: [AF_INET]127.0.0.1:443 Sat Jun 4 04:43:08 2022 Socket Buffers: R=[131072->131072] S=[16384->16384] Sat Jun 4 04:43:08 2022 Attempting to establish TCP connection with [AF_INET]127.0.0.1:443 [nonblock] Sat Jun 4 04:43:08 2022 TCP connection established with [AF_INET]127.0.0.1:443 Sat Jun 4 04:43:08 2022 TCP_CLIENT link local: (not bound) Sat Jun 4 04:43:08 2022 TCP_CLIENT link remote: [AF_INET]127.0.0.1:443 Sat Jun 4 04:43:08 2022 NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay Sat Jun 4 04:43:08 2022 Connection reset, restarting [0] Sat Jun 4 04:43:08 2022 SIGUSR1[soft,connection-reset] received, process restarting Sat Jun 4 04:43:08 2022 Restart pause, 5 second(s)
ESTABLISHにはなりましたが、Connection resetになってますね。
サーバ側のログもtls-cryptがエラーになってます。
Jun 4 04:43:08 PC-ubuntu openvpn[630900]: TCP connection established with [AF_INET]127.0.0.1:57156 Jun 4 04:43:08 PC-ubuntu openvpn[630900]: 127.0.0.1:57156 TLS: Initial packet from [AF_INET]127.0.0.1:57156, sid=7873fbc8 512a693e Jun 4 04:43:08 PC-ubuntu openvpn[630900]: 127.0.0.1:57156 tls-crypt unwrap error: packet too short Jun 4 04:43:08 PC-ubuntu openvpn[630900]: 127.0.0.1:57156 TLS Error: tls-crypt unwrapping failed from [AF_INET]127.0.0.1:57156 Jun 4 04:43:08 PC-ubuntu openvpn[630900]: 127.0.0.1:57156 Fatal TLS error (check_tls_errors_co), restarting Jun 4 04:43:08 PC-ubuntu openvpn[630900]: 127.0.0.1:57156 SIGUSR1[soft,tls-error] received, client-instance restarting
調べたらta.keyも呼び出さないとダメだそうです。
[Solved] tls-crypt unwrap error: packet too short - OpenVPN Support Forum
再実施。
masashi@PC-ubuntu:/etc/openvpn/client$ sudo openvpn --config client.conf --tls-crypt ta.key Sat Jun 4 04:48:18 2022 OpenVPN 2.4.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Mar 22 2022 Sat Jun 4 04:48:18 2022 library versions: OpenSSL 1.1.1f 31 Mar 2020, LZO 2.10 Sat Jun 4 04:48:18 2022 Outgoing Control Channel Encryption: Cipher 'AES-256-CTR' initialized with 256 bit key Sat Jun 4 04:48:18 2022 Outgoing Control Channel Encryption: Using 256 bit message hash 'SHA256' for HMAC authentication Sat Jun 4 04:48:18 2022 Incoming Control Channel Encryption: Cipher 'AES-256-CTR' initialized with 256 bit key Sat Jun 4 04:48:18 2022 Incoming Control Channel Encryption: Using 256 bit message hash 'SHA256' for HMAC authentication Sat Jun 4 04:48:18 2022 TCP/UDP: Preserving recently used remote address: [AF_INET]127.0.0.1:443 Sat Jun 4 04:48:18 2022 Socket Buffers: R=[131072->131072] S=[16384->16384] Sat Jun 4 04:48:18 2022 Attempting to establish TCP connection with [AF_INET]127.0.0.1:443 [nonblock] Sat Jun 4 04:48:18 2022 TCP connection established with [AF_INET]127.0.0.1:443 Sat Jun 4 04:48:18 2022 TCP_CLIENT link local: (not bound) Sat Jun 4 04:48:18 2022 TCP_CLIENT link remote: [AF_INET]127.0.0.1:443 Sat Jun 4 04:48:18 2022 NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay Sat Jun 4 04:48:18 2022 TLS: Initial packet from [AF_INET]127.0.0.1:443, sid=4cadbc4a c3da1e0c Sat Jun 4 04:48:18 2022 VERIFY OK: depth=1, CN=HomeCA.szkmhome.lab Sat Jun 4 04:48:18 2022 VERIFY KU OK (略) Sat Jun 4 04:48:19 2022 /sbin/ip link set dev tun1 up mtu 1500 Sat Jun 4 04:48:19 2022 /sbin/ip addr add dev tun1 local 10.8.0.6 peer 10.8.0.5 Sat Jun 4 04:48:19 2022 /sbin/ip route add 127.0.0.1/32 via 192.168.0.1 RTNETLINK answers: File exists Sat Jun 4 04:48:19 2022 ERROR: Linux route add command failed: external program exited with error status: 2 Sat Jun 4 04:48:19 2022 /sbin/ip route add 0.0.0.0/1 via 10.8.0.5 Sat Jun 4 04:48:19 2022 /sbin/ip route add 128.0.0.0/1 via 10.8.0.5 Sat Jun 4 04:48:19 2022 /sbin/ip route add 10.8.0.1/32 via 10.8.0.5 Sat Jun 4 04:48:19 2022 GID set to nogroup Sat Jun 4 04:48:19 2022 UID set to nobody Sat Jun 4 04:48:19 2022 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this Sat Jun 4 04:48:19 2022 Initialization Sequence Completed
ルートもインストールされました。
OKそうですね。
サーバ側もログがずらずらっと出てきましたのでOkでしょう。
Jun 4 04:48:18 PC-ubuntu openvpn[630900]: TCP connection established with [AF_INET]127.0.0.1:57208 Jun 4 04:48:18 PC-ubuntu openvpn[630900]: 127.0.0.1:57208 TLS: Initial packet from [AF_INET]127.0.0.1:57208, sid=916e5c45 e9d1b439 Jun 4 04:48:18 PC-ubuntu openvpn[630900]: 127.0.0.1:57208 VERIFY OK: depth=1, CN=HomeCA.szkmhome.lab Jun 4 04:48:18 PC-ubuntu openvpn[630900]: 127.0.0.1:57208 VERIFY OK: depth=0, CN=client1 (略) Jun 4 04:48:18 PC-ubuntu openvpn[630900]: 127.0.0.1:57208 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA Jun 4 04:48:18 PC-ubuntu openvpn[630900]: 127.0.0.1:57208 [client1] Peer Connection Initiated with [AF_INET]127.0.0.1:57208 Jun 4 04:48:18 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 MULTI_sva: pool returned IPv4=10.8.0.6, IPv6=(Not enabled) Jun 4 04:48:18 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 MULTI: Learn: 10.8.0.6 -> client1/127.0.0.1:57208 Jun 4 04:48:18 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 MULTI: primary virtual IP for client1/127.0.0.1:57208: 10.8.0.6 Jun 4 04:48:19 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 PUSH: Received control message: 'PUSH_REQUEST' Jun 4 04:48:19 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 SENT CONTROL [client1]: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,route 10.8.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM' (status=1) Jun 4 04:48:19 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key Jun 4 04:48:19 PC-ubuntu openvpn[630900]: client1/127.0.0.1:57208 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key Jun 4 04:48:19 PC-ubuntu NetworkManager[1118]: <info> [1654285699.6846] manager: (tun1): new Tun device (/org/freedesktop/NetworkManager/Devices/25) Jun 4 04:48:19 PC-ubuntu charon: 11[KNL] interface tun1 activated Jun 4 04:48:19 PC-ubuntu systemd-udevd[666021]: ethtool: autonegotiation is unset or enabled, the speed and duplex are not writable. Jun 4 04:48:19 PC-ubuntu charon: 13[KNL] fe80::9bb5:5d53:5ab6:4925 appeared on tun1 Jun 4 04:48:19 PC-ubuntu charon: 02[KNL] 10.8.0.6 appeared on tun1 (略)
NW周りのステータス
同一マシン内ですがVPNは張れたようなのでNWのステータスを見てみます。
トンネルインターフェースがちゃんとUpしてます。
デフォルトの10.8.0.0/24のIPも払い出されてますね。
masashi@PC-ubuntu:~$ ip address show dev tun1 25: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100 link/none inet 10.8.0.6 peer 10.8.0.5/32 scope global tun1 valid_lft forever preferred_lft forever inet6 fe80::9bb5:5d53:5ab6:4925/64 scope link stable-privacy valid_lft forever preferred_lft forever
続いてルーティングインストール。
払い出しもデフォルトのままです。
ホスト機のプロキシ経由でLXD環境にアクセスしたいだけなので追加は不要でしょう。
masashi@PC-ubuntu:~$ ip r show dev tun1 0.0.0.0/1 via 10.8.0.5 10.8.0.1 via 10.8.0.5 10.8.0.5 proto kernel scope link src 10.8.0.6 128.0.0.0/1 via 10.8.0.5
一応pingも打ってみます。
10.8.0.5はGWですが通りませんでした。
masashi@PC-ubuntu:~$ ping -c4 10.8.0.5 PING 10.8.0.5 (10.8.0.5) 56(84) バイトのデータ --- 10.8.0.5 ping 統計 --- 送信パケット数 4, 受信パケット数 0, パケット損失 100%, 時間 3064ミリ秒
10.8.0.1は何者かわかりませんが、返ってきます。
masashi@PC-ubuntu:~$ ping -c4 10.8.0.1 PING 10.8.0.1 (10.8.0.1) 56(84) バイトのデータ 64 バイト応答 送信元 10.8.0.1: icmp_seq=1 ttl=64 時間=0.057ミリ秒 64 バイト応答 送信元 10.8.0.1: icmp_seq=2 ttl=64 時間=0.059ミリ秒 64 バイト応答 送信元 10.8.0.1: icmp_seq=3 ttl=64 時間=0.059ミリ秒 64 バイト応答 送信元 10.8.0.1: icmp_seq=4 ttl=64 時間=0.058ミリ秒 --- 10.8.0.1 ping 統計 --- 送信パケット数 4, 受信パケット数 4, パケット損失 0%, 時間 3056ミリ秒 rtt 最小/平均/最大/mdev = 0.057/0.058/0.059/0.000ミリ秒
この辺は実際の疎通でNGになったら調べましょう。
サービス起動
これで接続確認できましたのでデーモンで起動しておきます。
masashi@PC-ubuntu:/etc/openvpn/server$ sudo systemctl start openvpn-server@server masashi@PC-ubuntu:/etc/openvpn/server$ sudo systemctl status openvpn-server@server ● openvpn-server@server.service - OpenVPN service for server Loaded: loaded (/lib/systemd/system/openvpn-server@.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2022-06-03 19:38:49 JST; 51s ago Docs: man:openvpn(8) https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage https://community.openvpn.net/openvpn/wiki/HOWTO Main PID: 630900 (openvpn)
これでOK。
まとめ
OPENVPN環境の構築を行いました。
SSLVPNは証明書が必要ですが、どの手順を見ても証明書の作成から書かれていて長くなりがちです。
私はCA局は作成していたのでサーバ証明書発行のみで済みましたが、このへんは仕様上仕方ないにしても結構面倒ですね。
(面倒なほどの難しいコマンドは打ってませんが…)
とりあえず無事にローカルでの接続確認はできましたので、次回はスマホからのアクセスを試します。