自宅-VPS間でIPsec (strongswan X.509証明書認証)

前の記事と同じ構成で、認証に証明書を導入してみた。

ネットワーク構成は前の記事と同じで、以下の図のようになる。

前提:
・VPS の OS は CentOS 7.5、自宅側サーバは Raspbian 9.4 である。
・IPsec 実装には strongswan を利用する。
・証明書作成にはOpenSSLを使い、PEM ファイルの形で管理する。
・自宅側のIPsec端点 (ホスト名:myserver1) と同一のサーバに CA を作成しておき、この CA 上で両側の端点用の証明書を発行する。

1. strongswan インストール

user@myserver1:~$ sudo apt-get install strongswan
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

カーネルパラメータは前々回の記事と同一の設定をしておく。

自宅内サーバ側の設定。
user@myserver1:~$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す

user@myserver1:~$ sudo sysctl -p /etc/sysctl.conf

VPS の方にも同じ設定を実施する。
[user@myvps1 ~]$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #追記する

[user@myvps1 ~]$ sudo sysctl -p /etc/sysctl.conf

ファイアウォール(ufw)を閉じている場合は、UDP 500 と 4500 を空けておくこと。

2. 証明書の作成

myserver1 上に CA のためのディレクトリと設定を準備する。
user@myserver1:~$ sudo mkdir /etc/ssl/CA
user@myserver1:~$ sudo mkdir /etc/ssl/newcerts
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
user@myserver1:~$ sudo touch /etc/ssl/CA/index.txt
user@myserver1:~$ sudo vi /etc/ssl/openssl.cnf

/etc/ssl/openssl.cnfの抜粋:

dir		= /etc/ssl		# Where everything is kept
database	= $dir/CA/index.txt	# database index file.
certificate	= $dir/certs/ca1.crt 	# The CA certificate
serial		= $dir/CA/serial 		# The current serial number
crlnumber	= $dir/CA/crlnumber # the current crl number
                    # must be commented out to leave a V1 CRL
crl     = $dir/crl/crl.pem
private_key	= $dir/private/ca1.key

CA 鍵・証明書を作成する。
user@myserver1:~$ sudo openssl req -new -x509 -extensions v3_ca -keyout /etc/ssl/private/ca1.key -out /etc/ssl/certs/ca1.crt -days 3652
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:CA
Common Name (e.g. server FQDN or YOUR name) []:ca1.home.example.com
Email Address []:

myserver1 の秘密鍵を作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく。
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myserver1.key -out /etc/ssl/private/myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

myserver1 の CSR を作成する。
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myserver1.key -out /etc/ssl/cert/myserver1.csr
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:Server
Common Name (e.g. server FQDN or YOUR name) []:myserver1.home.example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CA 鍵を使って CSR に署名する。
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myserver1.csr -config /etc/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/ca.key:********
(snip)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
(snip)
Data Base Updated

CA 証明書とホスト証明書・鍵を strongswan 用に配置する。
user@myserver1:~$ sudo cp /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
user@myserver1:~$ sudo cp /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myserver1.key /etc/ipsec.d/private/

myvps1 用の証明書も同様に作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myvps1.key 2048
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myvps1.key -out /etc/ssl/private/myvps1.key
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myvps1.key -out /etc/ssl/cert/myvps1.csr
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myvps1.csr -config /etc/ssl/openssl.cnf

いま作成した myvps1 用のホスト証明書・鍵、CA証明書を myvps1 側にコピーする。
user@myserver1:~$ cp /etc/ssl/certs/ca1.crt .
user@myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myvps1.key .
user@myserver1:~$ sudo chown user myvps1.key
user@myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1 上で証明書・鍵を配置する。
[user@myvps1 ~]$ sudo cp ca1.crt /etc/strongswan/ipsec.d/cacerts/
[user@myvps1 ~]$ sudo cp myvps1.crt /etc/strongswan/ipsec.d/certs/
[user@myvps1 ~]$ sudo cp myvps1.key /etc/strongswan/ipsec.d/private/

作業用ファイルを削除する。
[user@myvps1 ~]$ rm ca1.crt myvps1.crt myvps1.key
user@myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

3. strongswan の設定 (myserver1側)

設定ファイルを編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

config setup セクションの後に以下の内容を追加する。

conn myhome-to-vps
	authby=rsasig
	auto=start
	closeaction=restart
	dpdaction=restart
	left=192.168.100.240
	leftsubnet=192.168.100.0/24
	leftcert=myserver1.crt
	right=203.0.113.180
	rightsubnet=203.0.113.180/32
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.vpsnet.example.com"

こちら側から接続を開始するため、auto=start を記述する。また接続が切れたときにはこちら側から再接続を実行するため、closeaction=restart と dpdaction=restart を記述する。

パスワードファイルには秘密鍵のファイル名を記述する。
user@myserver1:~$ sudo vi /etc/ipsec.secrets

: RSA myserver1.key

4. strongswan の設定 (myvps1側)

こちらも設定ファイルを編集する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.conf

以下の内容を追加する。

conn myhome-to-vps
	authby=rsasig
	auto=add
	closeaction=clear
	dpdaction=clear
	left=203.0.113.180
	leftsubnet=203.0.113.180/32
	leftcert=myvps1.crt
	right=%any
	rightsubnet=192.168.100.0/24
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"

パスワードファイルには秘密鍵のファイル名を記述する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: RSA myvps1.key

5. サービス起動と確認

サービスを起動する。

user@myserver1:~$ sudo service strongswan start
[user@myvps1 ~]$ sudo service strongswan start

接続できたかどうか、ip xfrm state コマンドで確認する。

user@myserver1:~$ sudo ip xfrm state
src 192.168.100.240 dst 203.0.113.180
	proto esp spi 0xbaef12dc reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x6bde34f03f729b5a3c1d93c112ea6a40bf312742 96
	enc cbc(aes) 0x4f2fa3876e41e825be32a4e710a5f193
	encap type espinudp sport 4500 dport 4500 addr 0.0.0.0
src 203.0.113.180 dst 192.168.100.240
	proto esp spi 0xbb4b32e0 reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x44b52fad2bf912e10b61706add1337f823ec344e 96
	enc cbc(aes) 0xaf32405118ac467efb02f5f76e59aad1
	encap type espinudp sport 4500 dport 4500 addr 0.0.0.0