この記事は古くなっています。以下の記事を参照してください。


前編では、Let's Encrypt で発行されたサーバ証明書を使って Strongswan を構築し、パスワード認証の VPN を構築しました。後編では、Let's Encrypt のサーバ証明書を使用したまま、オレオレ認証局を建ててクライアント証明書を使った認証に切り替える方法をご紹介します。長くなりますが、各設定項目についても解説します。悪用されるとダメージが大きいサーバを建てているので、なぜこの設定で良いのかを納得して設定を進めましょう。

認証局の作成

Strongswan の PKI ツールを使って認証局を作成します。

認証局で必要な仕事を一通りこなす Makefile を作りましたので、これを /etc/pki/myCA/ に配置します。Makefile は行頭のタブ文字が重要です。Makefile をコピペするとタブ文字が空白に展開される可能性があるため、ダウンロードしてご利用ください。

/etc/pki/ 以下に、適当なディレクトリ(ここでは myCA)を作り、Makefile をダウンロードします。※ github に公開しましたので、こちからダウンロードしてください。

$ sudo mkdir -p "/etc/pki/myCA"
$ sudo curl -sSL "https://raw.githubusercontent.com/seinolab/simple-ca-with-strongswan/main/Makefile" -o "/etc/pki/myCA/Makefile"
$

Makefile を設定します。認証局の所在地、組織、名前を決めます。各証明書の有効期限(単位:日)を適宜決めます。


CA_ROOT=/etc/pki/myCA

COUNTRY=JP
STATE=Niigata
ORGANIZATION=your organization
CA_NAME=your Root CA

# lifetime of certificates
EXPIRE=366
EXPIRE_CA=366
EXPIRE_CRL=15

# ------ end of configuration ----------------------------------------------

make します。認証局が作成されます。

$ cd /etc/pki/myCA
$ sudo make
mkdir -p /etc/pki/myCA/cacerts
strongswan pki --gen --type rsa --size 4096 --outform pem > /etc/pki/myCA/cacerts/root.key.pem
chmod 600 /etc/pki/myCA/cacerts/root.key.pem
strongswan pki --self --ca --lifetime 366 \
               --in /etc/pki/myCA/cacerts/root.key.pem --type rsa \
               --dn "C=JP, ST=Niigata, O=your organization, CN=your Root CA" --outform pem \
           > /etc/pki/myCA/cacerts/root.cert.pem
openssl x509 -in /etc/pki/myCA/cacerts/root.cert.pem -outform DER -out /etc/pki/myCA/cacerts/root.cert.der
mkdir -p /etc/pki/myCA/crls
strongswan pki --signcrl --cacert /etc/pki/myCA/cacerts/root.cert.pem --cakey /etc/pki/myCA/cacerts/root.key.pem \
               --lifetime=15 --outform pem \
           > /etc/pki/myCA/crls/crl.pem
$

認証局の公開鍵のインストール

/etc/pki/myCA/cacerts/ に認証局の公開鍵(root.cert.pem)、秘密鍵(root.key.pem)があります。/etc/strongswan/ipsec.d/ 以下に、公開鍵のシンボリックリンクを作成します。

$ ls cacerts
root.cert.der  root.cert.pem  root.key.pem
$ sudo ln -s /etc/pki/myCA/cacerts/root.cert.pem /etc/strongswan/ipsec.d/cacerts/
$

併せて、VPN クライアント側にインストールするための配布用公開鍵(root.cert.der)もここにありますので、必要があればインストールしてください。

CRL のインストール

(この項の作業は、認証局が発行した証明書の無効化(revoke)を行わないならば、省略可です。)

/etc/pki/myCA/crls/ には、CRL が作成されています。/etc/strongswan/ipsec.d/ 以下に、CRL のシンボリックリンクを作成します。

$ ls crls
crl.pem
$ sudo ln -s /etc/pki/myCA/crls/crl.pem /etc/strongswan/ipsec.d/crls/
$

CRL は無効化された証明書のリストです。実際に無効化処理を実行したかどうかに関わらず、CRL は定期的に更新する必要があります。更新を怠ると、すべての証明書が無効扱いになりますので、ご注意ください。

クライアント証明書の発行

Makefile にクライアント証明書の発行処理が書き込まれていますので、それを利用します。common name が vpnuser のクライアント証明書を作成するのは、 次のようにタイプします。

何度も書きますが、ユーザ名は vpnuser@example.com のような形式でないとダメ、とする解説記事も多いのですが、そのような制限はありません

$ sudo make issue USER=vpnuser
mkdir -p /etc/pki/myCA/clients
strongswan pki --gen --type rsa --size 2048 --outform pem > /etc/pki/myCA/clients/vpnuser.key.pem
chmod 600 /etc/pki/myCA/clients/vpnuser.key.pem
strongswan pki --pub --in /etc/pki/myCA/clients/vpnuser.key.pem --type rsa \
| strongswan pki --issue --lifetime 366 \
                 --cacert /etc/pki/myCA/cacerts/root.cert.pem --cakey /etc/pki/myCA/cacerts/root.key.pem \
                 --dn "C=JP, O=your organization, CN=vpnuser" \
                 --san vpnuser --outform pem \
             > /etc/pki/myCA/clients/vpnuser.cert.pem
openssl pkcs12 -export -inkey /etc/pki/myCA/clients/vpnuser.key.pem -in /etc/pki/myCA/clients/vpnuser.cert.pem \
               -certfile /etc/pki/myCA/cacerts/root.cert.pem -caname "your Root CA" \
               -name "your organization client certificate" \
               -out /etc/pki/myCA/clients/vpnuser.p12
Enter Export Password: (パスワード)
Verifying - Enter Export Password: (パスワード)
$

/etc/pki/myCA/clients/ にクライアント証明書が作成されますので、.p12 ファイルを端末にインストールします。インストールの際は、上で設定したパスワードが必要です。

$ ls clients
vpnuser.cert.pem  vpnuser.key.pem  vpnuser.p12  vpnuser.key.pem
$

ipsec.conf

ipsec.conf には、ユーザ毎に、以下の設定を書きます。

conn vpnuser-IPSec-IKEv2-TLS
      keyexchange=ikev2

      left=%any
      leftsubnet=0.0.0.0/0
      leftid=example.com
      leftcert=cert.pem
      leftsendcert=always

      right=%any
      rightdns=8.8.8.8,8.8.4.4
      rightsourceip=192.168.1.0/24
      rightauth=eap-tls
      rightid=vpnuser
      rightcert=vpnuser.cert.pem
      rightca="C=JP, ST=Niigata, O=your organization, CN=your Root CA"

      auto=add

right には VPN クライアントに対して接続を許可するネットワークを IP アドレス、FQDN、またはサブネットなどで指定します。ここでは、公衆無線 LAN などからの利用を想定しており、事前に IP アドレスが分かりませんので、すべてのアドレスからの接続を許可(%any)します。

rightid はクライアント証明書の common name です。

rightcert には、クライアント証明書の公開鍵を指定します。クライアントはログイン時に秘密鍵で暗号化したデータを送ってきますので、対応する公開鍵で復号することで認証します。同じユーザに対して、複数のクライアント証明書を発行(※)できてしまいますので、最後に発行した証明書を有効なものとして扱い、それ以外は無効とするために、最新の証明書がどれかを示すための設定です。CRL を省略した場合は、必ず設定してください。

通常は古い証明書を無効化(revoke)してから、新しいものを発行します。

rightca は、クライアント証明書の検証に使う認証局の DN(Distingished Name)を書きます。現在の設定では、証明書チェーンが 2つインストールされていますので、Let's Encrypt 側で発行したクライアント証明書も認証が成功してしまう可能性があります。クライアント証明書の検証では、こちら側で建てた認証局を利用するように設定しておきましょう。DN は以下のように調べます。

$ openssl x509 -in /etc/pki/myCA/cacerts/root.cert.pem -text | grep Subject | head -1
        Subject: C=JP, ST=Niigata, O=your organization, CN=your Root CA
$ 

Strongswan は /C=JP/SN=Niigata/O=your organization/CN=your Root CA のスタイルの DN は受け入れてくれません。

rightca を書き間違えた場合、ログファイルに charon: 05[CFG] CA certificate "..." not found, discarding CA constraint と吐き出して、設定が無効になった上で、涼しい顔で動いていますので、必ずログファイルを確認しましょう。

ipsec.conf には、ユーザごとに conn がずらずらと並ぶことになります。あるいは right を適切に設定し、同じユーザでも、自宅からの設定、会社からの設定…という具合にたくさん並ぶのが正常な姿です。たくさんある conn の中から、条件にマッチするものが選ばれて、VPN が作成されるという仕様です。そもそも Strongswan は拠点間で固定的な VPN を作成するのに利用することもありますので、このようなファイル設定になっているのだ、と気がつくと腑に落ちると思います。