クライアント証明書認証の設定メモ(Apache2.4 + CentOS)

Linux
Linux
スポンサーリンク

クライアント証明書認証とは、サービスを利用するユーザーに証明書を発行し(これを「クライアント証明書」と呼びます)その証明書によってユーザーを認証する仕組みのことです。一般的なユーザーIDとパスワードの認証に加えて、このクライアント証明書認証を導入することによって、ログイン時のセキュリティを強化することができます。そこで今回は、プライベート認証局の構築とクライアント証明書認証の発行、Apache httpd 2.4 でのクライアント証明書認証の設定手順をまとめてみました。

プライベート認証局の構築

まずはじめに、クライアント証明書を発行するためのプライベート認証局を構築します。

「プライベート認証局の構築」と書くとなにやら大変そうですが、CentOS には初期状態で認証局構築ツールが入っていますので、簡単にプライベート認証局を構築できます。

・OpenSSL の設定をプライベート認証局構築用に変更します。
sudo vim /etc/pki/tls/openssl.cnf

[ usr_cert ]
(略)
basicConstraints=CA:FALSE
 ↓
basicConstraints=CA:TRUE
 
[ v3_ca ]
(略)
# nsCertType = sslCA, emailCA
 ↓
nsCertType = sslCA, emailCA

・プライベート認証局構築スクリプトを編集し、有効期限を30年に変更します。
sudo vim /etc/pki/tls/misc/CA

CADAYS="-days 1095" # 3 years
 ↓
CADAYS="-days 10950" # 30 years

(補足)CentOS8には /etc/pki/tls/misc/CA がありませんので、インストールしてください。
関連記事:CentOS8 に /etc/pki/tls/misc/CA をインストールする方法

「/etc/pki/CA/」ディレクトリ下に(もしこのディレクトリが無かったら作成してください)証明書のラベル付けに使用するシリアルファイルを作成します。
sudo vim /etc/pki/CA/serial

00

・プライベート認証局を作成します。青文字の箇所以外は<空エンター>でOKです。
sudo /etc/pki/tls/misc/CA -newca

CA certificate filename (or enter to create)
<空エンター>
(略)
Enter PEM pass phrase: 1234 ←表示されません
Verifying - Enter PEM pass phrase: 1234 ←表示されません
(略)
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]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []: private-ca
Email Address []:
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/./cakey.pem: 1234 ←表示されません
Check that the request matches the signature
Signature ok
 
(略:入力した認証局の情報が表示されます)
 
Certificate is to be certified until Apr 15 20:52:22 2120 GMT (36500 days)
 
Write out database with 1 new entries
Data Base Updated

プライベート認証局の秘密鍵のパスフレーズを削除します。

sudo openssl rsa -in /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/private/cakey.pem
Enter pass phrase for cakey.pem: 1234 ←表示されません

プライベート認証局の秘密鍵のパーミションを変更

sudo chmod 400 /etc/pki/CA/private/cakey.pem

以上で、プライベート認証局の構築完了です。「/etc/pki/CA/cacert.pem」がプライベート認証局の証明書になります。(これを後ほど Apache httpd に設定します)

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

プライベート認証局構築用になっている OpenSSL の設定を、クライアント証明書発行用に変更します。

sudo vim /etc/pki/tls/openssl.cnf

[ CA_default ]
(略)
default_days = 365
 ↓
default_days = 36500

[ usr_cert ]
(略)
basicConstraints=CA:TRUE
 ↓
basicConstraints=CA:FALSE

# nsCertType = client, email, objsign
 ↓
nsCertType = client, email, objsign

[ v3_ca ]
(略)
nsCertType = sslCA, emailCA
 ↓
# nsCertType = sslCA, emailCA

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

本題のクライアント証明書の発行です。

適当な場所に作業用ディレクトリを作成して、そのディレクトリに移動してください。

sudo mkdir /etc/pki/tls/client
cd /etc/pki/tls/client/

クライアント証明書用の秘密鍵を作成します。

sudo openssl genrsa -out client.key 2048

・クライアント証明書の発行要求(CSR)を作成します。青文字の箇所以外は<空エンター>でOKです。
sudo openssl req -new -key client.key -out client.csr

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]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []: client
Email Address []:
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

・クライアント証明書を発行します。
sudo openssl ca -in client.csr -out client.crt

 
(クライアント証明書の発行要求の内容が表示されます)
 
Certificate is to be certified until Apr 15 21:26:01 2120 GMT (36500 days)
Sign the certificate? [y/n]: y
 
1 out of 1 certificate requests certified, commit? [y/n] y
Write out database with 1 new entries
Data Base Updated

・秘密鍵と発行したクライアント証明書を PKCS#12 ファイルにまとめます。(設定したパスワードはブラウザにインストールする時に必要になります)
sudo openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12

Enter Export Password:<パスワード>
Verifying - Enter Export <パスワード>

この PKCS#12ファイルを使ってクライアント証明書をWebブラウザにインストールしますので、クライアントとなるパソコンにコピーしておきましょう。(Webブラウザへのインストール方法は「<Webブラウザ名> クライアント証明書」で検索してください)

/etc/pki/tls/client/client.p12

Apache httpd 2.4 でのクライアント証明書認証の設定

青字の部分が、Apache httpd 2.4 でのクライアント証明書認証の設定です。クライアント証明書認証は、TLS/SSL のオプションという位置づけのためサーバー側の TLS/SSL 設定は必須です。

<VirtualHost *:443>
    ServerName www.example.com
    DocumentRoot "/var/www/html"

    SSLEngine on
    Header always set Strict-Transport-Security "max-age=31536000"
    SSLCertificateFile /etc/pki/tls/certs/server.crt
    SSLCertificateKeyFile /etc/pki/tls/private/server.key

    SSLCACertificateFile /etc/pki/CA/cacert.pem
    SSLVerifyDepth 1

    <Directory "/var/www/html">
        Options FollowSymLinks
        AllowOverride None
        # Require all granted

        SSLVerifyClient require
        Require expr %{SSL_CLIENT_S_DN_CN} == 'client'
    </Directory>

    SetEnvIf Request_URI "\.(gif|jpg|png|css|js)$" nolog
    ErrorLog logs/error_log
    CustomLog logs/access_log combined env=!nolog
</VirtualHost>

設定の補足

SSLCACertificateFile /etc/pki/CA/cacert.pem
 クライアント証明書を発行した認証局(冒頭で作成したプライベート認証局のことです)の証明書「/etc/pki/CA/cacert.pem」を指定します。(このディレクティブは Directory ディレクティブの下や .htaccess には書けません)

SSLVerifyDepth 1
 中間証明書を発行した認証局の最大数です。今回の場合は、SSLCACertificateFile で指定した認証局が直接クライアント証明書を発行していますので「1」を指定します。

SSLVerifyClient require
 クライアント証明書認証の検証レベルを指定します。クライアント証明書認証を必須とする場合は「require」を指定します。

Require expr %{SSL_CLIENT_S_DN_CN} == 'client'
 このディレクティブは必須ではありませんが、上記のように指定するとコモンネーム(SSL_CLIENT_S_DN_CN)が「client」のクライアント証明証のみ認証します。組織名(SSL_CLIENT_S_DN_O)や部門名(SSL_CLIENT_S_DN_OU)なども指定することができます。

参考資料:mod_ssl Environment Variables

以前よくつかわれていた SSLRequire は、非推奨になったため Require expr の利用が推奨されています。

Cannot perform Post-Handshake Authentication エラー対処法

TLS1.3 を有効にしている場合、以下のようなエラーが発生して、クライアント証明書認証ができない場合があります。

[Thu May 14 05:32:08.231119 2020] [ssl:error] [pid 1858:tid 140234977113856] [client 192.168.56.1:50202] AH: verify client post handshake
[Thu May 14 05:32:08.231184 2020] [ssl:error] [pid 1858:tid 140234977113856] [client 192.168.56.1:50202] AH10158: cannot perform post-handshake authentication
[Thu May 14 05:32:08.231224 2020] [ssl:error] [pid 1858:tid 140234977113856] SSL Library Error: error:14268117:SSL routines:SSL_verify_client_post_handshake:extension not received

その場合は、TLS1.3 を無効にし、TLS1.2 のみ有効にしてください。

sudo vim /etc/httpd/conf.d/ssl.conf

SSLProtocol -all +TLSv1.2 +TLSv1.3
 ↓
SSLProtocol -all +TLSv1.2

おわりに

テレワークが一気に普及したことにより、特定の端末からのみからサービスにアクセスさせたいという要望が増えています。そんな時にはこのクライアント証明書認証が活用できそうですね。

コメント

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