【簡単CA構築】TLSクライアント認証証明書によるクライアント認証(Apache+OpenSSL)

Windows OSおよびLinux OSを扱った経験のある方を前提に記載している。
手順に従って進めば、OpenSSLでプライベート認証局を利用したクライアント認証が可能。

動作環境

Windows上に仮想環境のVMware Workstation 16 Playerをインストールし、Cent OSの後継OSであるRocky Linuxをインストール。

Microsoft Windows 10
└VMware Workstation 16 Player
 └Rocky Linux 8.6
  └OpenSSL 1.1.1k FIPS 25 Mar 2021
  └Apache (httpd-2.4.37-47.module+el8.6.0+823+f143cee1.1.x86_64)

CA構成

OpenSSLで3階層のCA構築(Root CA + 中間CA + EE証明書)
Root CA → CN=RCA(25年)・・・RCAの自己署名証明書
└□中間CA → CN=SCA01(15年)・・・RCAからSCA01のCA証明書に署名
 └□EE(End Entity)証明書 → CN=*.example.com(825日)・・・TLSサーバー証明書

 └□EE(End Entity)証明書 → CN=202205250001(1825日)・・・TLSクライアント認証証明書

以下URLよりCA構築済みの前提とし、TLSクライアント認証証明書を今回は発行する。
【簡単】プライベート認証局を構築しTLSサーバー証明書を発行(OpenSSLの3階層CA) | Japanese PKI Blog (world-tls.com)

TLSクライアント認証証明書を使用するWebサーバーは「www2.example.com」とし、リポジトリーとは別のサーバーとする。

Webサーバー構築

(1)HTTPSへのリダイレクト設定

CAサーバーとは別の「www2.example.com」Webサーバーが構築済みの前提とする。
クライアント認証なしで、アクセスするのを防止するため、HTTP通信を禁止する。
「80ポートから来た通信をHTTP通信にリダイレクト」コメント以下6行を追記。

/etc/httpd/conf.d/ssl.conf

# 80ポートから来た通信をHTTP通信にリダイレクト
<VirtualHost *:80>
  ServerName www2.example.com:80
  RewriteEngine on
  RewriteCond %{HTTP_HOST} .* 
  RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
...

サービス再起動

systemctl restart httpd

(2)クライアント認証を必須にさせる

SSLCACertificateFile → RootCA証明書と中間CA証明書を設定

  1. PEM形式で1つのファイルに結合しca-allow.crtに書き込む。RootCA証明書と中間CA証明書の順番は問わない。
  2. もし、RootCA証明書の記載をしていない場合、エラーになる。
  3. SSLCACertificateFileにRootCA証明書だけ設定してある場合、クライアント認証の際、クライアント端末から中間CA証明書が送信されれば、認証が成立する。
ca-allow.crtの記載例
#RCA
-----BEGIN CERTIFICATE-----
MIIFYTCCA0mgAwIBAgIUQ1pa3A8Dpdw6VDAfFDnF3ukYwywwDQYJKoZIhvcNAQEL
BQAwODELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMQswCQYDVQQKDAJDQTEM
MAoGA1UEAwwDUkNBMB4XDTIyMDUyNzAxNTYxMloXDTQ3MDUyMTAxNTYxMlowODEL
MAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMQswCQYDVQQKDAJDQTEMMAoGA1UE
AwwDUkNBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvOUCjWb6nrab
8kYDbAlEIaFdFV6BP+1zp0r4sseaD8VTfshHWfuiKKjjmnleK5heFOyT9RHvOw8W
xw13cQFtVPiNDm+7V3j+sIvpD2pT8lH+arfJPz8iE0jnZ9dGVz9OTSYtySuK7MPX
+gQzSlq1qAq0r4+42LtBSDOvvImQbDCIT625GIr0qx6L8oLvImzPogzzRGgA8R3q
r+EufZlxE2SA3Qy2JPEyXa+jqyqOM76stK38EBi+nUUf/2W9xNT4wl+ODehVEmMl
iE4T2vAV2kgrGBnrZ+wEOBTMookf634vyGB1MWD01FlxNOxV5kRL0/cEs5sCBzZT
okLBC+muQ8O6HY6GIYTFoOhz/l8+sjlHoO2IrPdbUOE26TDQv/YBmPNhRMLpxNH2
Lbp41qJ15ECvHKmuMCYcdawWpv3XMjQRBk1MktqMpDUJmbkQQYNNPQE50HNasLxu
ayuB3kCp7t58Tr5ZV2cTcuyWHpDUqIkwt8KyWAlLHf2sNGcAPu/n5VFDA06Yy2LC
CKa/Dcm3f3r/T2IhuQvvzM+cWhAVGp3wDPpnA1UlmZEoF+KaY028tZfz//q2TXQc
nKuKwBMqSCZm9lo/ryqdpdIYNFmanueNSRJEu9SVzqFIjbIShUvHtLJFJ6pnCJTN
oLkgYs7llqJTBLi0cSHhd6kz+5pHfaMCAwEAAaNjMGEwHQYDVR0OBBYEFDc+G0k8
rnFyIT4PV6lyuTZ9AO6+MB8GA1UdIwQYMBaAFDc+G0k8rnFyIT4PV6lyuTZ9AO6+
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUA
A4ICAQB7ClISdxTycy3VkulGLscARMu6adEnwSp94Rze5U/xhp4j1RwNz6BfA8yP
ocaF829nRVnAGyizFdNxTZxeauQAmX9+PzyMWV8gWNM8YxXXFRpmx1ij2h7b3t4/
0SJwMH2botDrtZ6vKWGYDEePwT3fiD0aP6OvkZruu4hnNUW1t0WE7MYTM5TWJZxR
tp3RrwQB92BGxcq4msnsod/vDWc2cLwaSBqHqkS6nki1gPE+a36mdp8bvy19r7xY
5J0+15+/a7fyq/4PRwZYJw6PaWjoAP5SUiDis2f/B3dszB18DAw8JyHtSwPsrlpw
kNiDyCjvy5zNNZpv2vRX9zTapY8o8IDs/io1cAG1204hV2zBJDysOUJtAd8kYidj
QfYjE7SrponGtsUb63HdWwsXV9tq5x2DkV9eSwuCL0YujTvLDE38KUlXjWJZ5bpp
sJIZmzhL3rR/X1fghNwUqPQ93UW0AaAoueHXn5ykF7basN2ceQXUI+KTuYmaJd2F
Z/OLDtDp6A0HQtF1jQ/hGvgsjJiWGgj3feFhPzxcUORjjfb6CDomPUHgqf+3fvMn
Kbiu9kAmHM18NSV/FAL1XZ40AAYAzGSawzW+gSd6PxaRPwl4s1YtoHGdg8AvQ78K
dkC8Mnr9pns9pbzwL6uiiEzVhX8JzyRdYtshkJEPFSyUGKc91w==
-----END CERTIFICATE-----
#SCA01
-----BEGIN CERTIFICATE-----
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
BzpVwsQgvtHowig=
-----END CERTIFICATE-----

エラー表示例
192.168.0.2からのアクセスで「SSLCACertificateFile」に中間CA証明書のみ設定され、RootCA証明書が設定されておらずエラーになった場合の例
[Mon Jul 26 12:06:46.518755 2021] [ssl:error] [pid 4096:tid 140271515952896] [client 192.168.0.2:58000] AH02039: Certificate Verification: Error (2): unable to get issuer certificate

SSLCARevocationFile

  1. クライアント証明書を発行しているCAから生成されるCRL(失効情報)ファイルをPEM形式で記載。複数結合可。
  2. CRL有効期限を超過せず、失効情報を適切に取得するため定期的に自動取得する仕組みが必要。
    以下ssl.confでは、場所を「/etc/pki/tls/ca-crl.pem」としている。

SSLVerifyClient

  1. none クライアント証明書の検証は行われない。
  2. optional クライアント証明書の検証を行う。クライアントからクライアント証明書を提示されない場合、処理は続行される。
  3. require クライアント証明書の検証を行う。クライアントからクライアント証明書を提示されない場合は、エラーが発生する。

SSLVerifyDepth

  1. 自己署名証明書は0
  2. RootCAから直接発行されている場合は1
  3. RootCA証明書→中間CA証明書→EE証明書の階層なら2。
    SSLRequire → ST=Tokyo、L=なし、O=CA、OU=なしの場合のみアクセス可能とする。

参考:Apache Module mod_ssl

Apacheを安全な設定にする方法
参考:Mozilla SSL Configuration Generator

/etc/httpd/conf.d/ssl.conf

#   Certificate Authority (CA):
#   Set the CA certificate verification path where to find CA
#   certificates for client authentication or alternatively one
#   huge file containing all of them (file must be PEM encoded)
#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
SSLCACertificateFile /etc/pki/tls/certs/ca-allow.crt
SSLCARevocationFile  /etc/pki/tls/ca-crl.pem

#   Client Authentication (Type):
#   Client certificate verification type and depth.  Types are
#   none, optional, require and optional_no_ca.  Depth is a
#   number which specifies how deeply to verify the certificate
#   issuer chain before deciding the certificate is not valid.
SSLVerifyClient require
SSLVerifyDepth  2
<Location />
SSLRequire (     %{SSL_CLIENT_S_DN_ST} eq "Tokyo" \
             and %{SSL_CLIENT_S_DN_L} eq "" \
             and %{SSL_CLIENT_S_DN_O} eq "CA" \
             and %{SSL_CLIENT_S_DN_OU} eq "" \
             and %{SSL_CLIENT_VERIFY} eq "SUCCESS" \
               )
</Location>

ブラウザ上にキャッシュを残さないようにする。
「Apacheがキャッシュを残さないようにする」コメント以下4行を追加。

/etc/httpd/conf/httpd.conf

<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

#Apacheがキャッシュを残さないようにする
<IfModule mod_headers.c>
  Header set Pragma no-cache
  Header set Cache-Control no-cache
</IfModule>

サービス再起動

systemctl restart httpd

CAサーバーで証明書発行

クライアント認証証明書をCAサーバーで発行

証明書プロファイルの設定

cd /etc/pki/tls/myca
mkdir SCA01-EE-Client01
cp /etc/pki/tls/openssl.cnf /etc/pki/tls/myca/SCA01-EE-Client01/openssl-SCA01-EE-Client01.cnf
vim /etc/pki/tls/myca/SCA01-EE-Client01/openssl-SCA01-EE-Client01.cnf

以下、編集する(crlDistributionPointsは、適宜、FQDN部分を変更)
OCSPレスポンダーを準備する場合は、[ v3_ca ]で以下に置き換え。
authorityInfoAccess = OCSP;URI:http://www1.example.com:8081, caIssuers;URI:http://www1.example.com/SCA01.crt

openssl-SCA01-EE-Client01.cnf

[ CA_default ]
dir=/etc/pki/tls/myca/SCA01
unique_subject = no            # Set to 'no' to allow creation of
default_days	= 1825			# how long to certify for
default_crl_days= 365			# how long before next CRL
[ usr_cert ]
#basicConstraints=CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
crlDistributionPoints = URI:http://www1.example.com/SCA01crl.crl
authorityInfoAccess = caIssuers;URI:http://www1.example.com/SCA01.crt
#nsComment			= "OpenSSL Generated Certificate"

秘密鍵を生成
・PEM pass phrase(例)3333a

cd /etc/pki/tls/myca/SCA01-EE-Client01
openssl genrsa -aes256 2048 > SCA01-EE-Client01_key.pem

CSRを生成

openssl req -config /etc/pki/tls/myca/SCA01-EE-Client01/openssl-SCA01-EE-Client01.cnf -new -key SCA01-EE-Client01_key.pem -out SCA01-EE-Client01_csr.pem

以下入力する。

Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:.
Organization Name (eg, company) [Default Company Ltd]:CA
Organizational Unit Name (eg, section) []:.
Common Name (eg, your name or your server's hostname) []:202205250001
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

★中間CA証明書の秘密鍵でクライアント証明書に署名し、発行する。
(/SCA01-EE-Client01/SCA01-EE-Client01_csr.pemを使用し、有効期間825日で発行)

cd /etc/pki/tls/myca/SCA01
openssl ca -config /etc/pki/tls/myca/SCA01-EE-Client01/openssl-SCA01-EE-Client01.cnf  -create_serial -batch -in ../SCA01-EE-Client01/SCA01-EE-Client01_csr.pem -keyfile private/cakey.pem -cert cacert.pem -out ../SCA01-EE-Client01/SCA01-EE-Client01.crt -policy policy_anything

PEM pass phrase(例)2222a

クライアント認証証明書を検証。
以下が結果として表示されればOK。
「SCA01-EE-Client01/SCA01-EE-Client01.crt: OK」

cd /etc/pki/tls/myca
openssl verify -CAfile RS01-chain.pem SCA01-EE-Client01/SCA01-EE-Client01.crt

PFXファイルの作成

cd /etc/pki/tls/myca/SCA01-EE-Client01
openssl pkcs12 -export -in SCA01-EE-Client01.crt -inkey SCA01-EE-Client01_key.pem -out SCA01-EE-Client01.pfx

PEM pass phrase(例)3333a

クライアント認証するPCにPFXファイル、中間CA証明書、Root CA証明書をインポートする。
アクセスする際、証明書を要求され、クライアント認証が成功する。

タイトルとURLをコピーしました