クライアント認証

Apachehttps でのクライアント認証に対応しています.

普段利用する https の場合は,サーバから送られてきたサーバ証明書を証明書をクライアント側で確認します.
クライアント認証の場合は,https で接続してきた端末(クライアント)から送られてきたクライアント証明書を使用して,サーバ側で認証をおこないます.

証明書の送信

f:id:Hexa:20120310164240j:plain

ServerHello, Certificate, ServerKeyExchange の次に CertificateRequest が送信されてきます.
CertificateRquest には certificate_types と certificate_authorities の 2 つが含まれています.

  • certificate_types はクライアントに要求する証明書のタイプのリスト(rsa_sign や dss_sign など)
  • certificate_authorities は容認する認証局の DN のリスト

インストール

OS
CentOS 6.2
# yum install httpd mod_ssl

設定

  • /etc/httpd/conf/httpd.conf の編集
ServerName www.example.com:80
  • /etc/httpd/conf.d/ssl.conf の編集(下記の内容に変更します)
## サーバ証明書
SSLCertificateFile /etc/pki/tls/certs/server.crt
## サーバ証明書とペアの秘密鍵
SSLCertificateKeyFile /etc/pki/tls/private/server.key
## 中間証明書(あれば設定する)
SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
## クライアント認証時にクライアント証明書を検証する CA 証明書(ca.crt には PEM 形式の証明書を複数枚格納することが可能です)
SSLCACertificateFile /etc/pki/tls/certs/ca.crt
## クライアント証明書検証のタイプ
SSLVerifyClient require
  • ssl.conf で指定した証明書を格納する
    • 本番環境であればサーバ証明書は正規の認証局から買いましょう
    • テスト環境であれば,サーバ証明書を発行したオレオレ CA 証明書をクライアントにインストールして信頼しておきます

httpd を起動させる

# service httpd start

https://www.example.com へアクセス

今回はテスト用なので hosts に www.example.com をあらかじめ書いておきました.

有効なクライアント証明書による接続

1. クライアント証明書を選択
f:id:Hexa:20120310171210p:plain
2. アクセスの許可
f:id:Hexa:20120310171419p:plain
3. 接続(https で接続できています)
f:id:Hexa:20120310171457p:plain

有効性が検証できないサーバ証明書の場合は 3 で警告が出ます
f:id:Hexa:20120310171625p:plain

無効なクライアント証明書による接続

期限切れのクライアント証明書を使用してみました.
無効なクライアント証明書を選択する以外は,上記の 有効なクライアント証明書による接続 と手順は同じです.
f:id:Hexa:20120310171846p:plain

接続エラーになりました.

パケット

パケットは,Wireshark で取得しています.

CertificateRequest.

CertificateRequest 周りを見ています.

    SSLv3 Record Layer: Handshake Protocol: Server Key Exchange
        Content Type: Handshake (22)
        Version: SSL 3.0 (0x0300)
        Length: 525
        Handshake Protocol: Server Key Exchange
            Handshake Type: Server Key Exchange (12)
            Length: 521
    SSLv3 Record Layer: Handshake Protocol: Multiple Handshake Messages
        Content Type: Handshake (22)
        Version: SSL 3.0 (0x0300)
        Length: 107
        Handshake Protocol: Certificate Request
            Handshake Type: Certificate Request (13)
            Length: 99
            Certificate types count: 6
            Certificate types (6 types)
                Certificate type: RSA Fixed DH (3)
                Certificate type: DSS Fixed DH (4)
                Certificate type: Unknown (5)
                Certificate type: Unknown (6)
                Certificate type: RSA Sign (1)
                Certificate type: DSS Sign (2)
            Distinguished Names Length: 90
            Distinguished Names (90 bytes)
                Distinguished Name Length: 28
                Distinguished Name: (id-at-commonName=ca1.example.com)
                    RDNSequence item: 1 item (id-at-commonName=ca1.example.com)
                        RelativeDistinguishedName item (id-at-commonName=ca1.example.com)
                            Id: 2.5.4.3 (id-at-commonName)
                            DirectoryString: uTF8String (4)
                                uTF8String: ca1.example.com
                Distinguished Name Length: 28
                Distinguished Name: (id-at-commonName=ca2.example.com)
                    RDNSequence item: 1 item (id-at-commonName=ca2.example.com)
                        RelativeDistinguishedName item (id-at-commonName=ca2.example.com)
                            Id: 2.5.4.3 (id-at-commonName)
                            DirectoryString: uTF8String (4)
                                uTF8String: ca2.example.com
                Distinguished Name Length: 28
                Distinguished Name: (id-at-commonName=ca3.example.com)
                    RDNSequence item: 1 item (id-at-commonName=ca3.example.com)
                        RelativeDistinguishedName item (id-at-commonName=ca3.example.com)
                            Id: 2.5.4.3 (id-at-commonName)
                            DirectoryString: uTF8String (4)
                                uTF8String: ca3.example.com
        Handshake Protocol: Server Hello Done
            Handshake Type: Server Hello Done (14)
            Length: 0
  • Certificate types として下記の 6 つがクライアントに送られています
    • RSA Fixed DH (3)
    • DSS Fixed DH (4)
    • Unknown (5)
    • Unknown (6)
    • RSA Sign (1)
    • DSS Sign (2)
  • Distinguished Names が容認する認証局の DN のリストです(今回は ca.crt に 3 枚の CA 証明書を格納しています)
ClientCertificate

サーバからの CertificateRequest を受けて,ブラウザ上で選択したクライアント証明書の送信の部分を少しだけ見てみます.

    SSLv3 Record Layer: Handshake Protocol: Multiple Handshake Messages
        Content Type: Handshake (22)
        Version: SSL 3.0 (0x0300)
        Length: 1239
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 839
            Certificates Length: 836
            Certificates (836 bytes)
                Certificate Length: 833
                Certificate (id-at-commonName=user03@example.org)
                    signedCertificate
                        version: v3 (2)
                        serialNumber: 1
                        signature (shaWithRSAEncryption)
                            Algorithm Id: 1.2.840.113549.1.1.5 (shaWithRSAEncryption)
                        issuer: rdnSequence (0)
                            rdnSequence: 1 item (id-at-commonName=ca3.example.com)
                                RDNSequence item: 1 item (id-at-commonName=ca3.example.com)
                                    RelativeDistinguishedName item (id-at-commonName=ca3.example.com)
                                        Id: 2.5.4.3 (id-at-commonName)
                                        DirectoryString: uTF8String (4)
                                            uTF8String: ca3.example.com
                        validity
                            notBefore: utcTime (0)
                                utcTime: 10-09-20 15:00:00 (UTC)
                            notAfter: utcTime (0)
                                utcTime: 13-01-20 15:00:00 (UTC)
                        subject: rdnSequence (0)
                            rdnSequence: 1 item (id-at-commonName=user03@example.org)
                                RDNSequence item: 1 item (id-at-commonName=user03@example.org)
                                    RelativeDistinguishedName item (id-at-commonName=user03@example.org)
                                        Id: 2.5.4.3 (id-at-commonName)
                                        DirectoryString: uTF8String (4)
                                            uTF8String: user03@example.org
                        subjectPublicKeyInfo
                            algorithm (rsaEncryption)
                                Algorithm Id: 1.2.840.113549.1.1.1 (rsaEncryption)
                            Padding: 0
                            subjectPublicKey: 3082010a0282010100c322c4b058adee5342f5b7f6799800...
                        extensions: 5 items
                            Extension (id-ce-basicConstraints)
                                Extension Id: 2.5.29.19 (id-ce-basicConstraints)
                                critical: True
                                BasicConstraintsSyntax
                            Extension (id-ce-authorityKeyIdentifier)
                                Extension Id: 2.5.29.35 (id-ce-authorityKeyIdentifier)
                                AuthorityKeyIdentifier
                            Extension (id-ce-subjectKeyIdentifier)
                                Extension Id: 2.5.29.14 (id-ce-subjectKeyIdentifier)
                                SubjectKeyIdentifier: 67d149c911412b2da2254fe94377e7e9c66a7b28
                            Extension (id-ce-extKeyUsage)
                                Extension Id: 2.5.29.37 (id-ce-extKeyUsage)
                                KeyPurposeIDs: 1 item
                                    KeyPurposeId: 1.3.6.1.5.5.7.3.2 (id-kp-clientAuth)
                            Extension (id-ce-cRLDistributionPoints)
                                Extension Id: 2.5.29.31 (id-ce-cRLDistributionPoints)
                                CRLDistPointsSyntax: 1 item
                                    DistributionPoint
                                        distributionPoint: fullName (0)
                                            fullName: 1 item
                                                GeneralName: uniformResourceIdentifier (6)
                                                    uniformResourceIdentifier: http://example.com:9292/crl/example.crl
                    algorithmIdentifier (shaWithRSAEncryption)
                        Algorithm Id: 1.2.840.113549.1.1.5 (shaWithRSAEncryption)
                    Padding: 0
                    encrypted: ccb3a0a79dbca91c1d02331798d2cbed32c50bc409e1539e...
        Handshake Protocol: Client Key Exchange
            Handshake Type: Client Key Exchange (16)
            Length: 130
  • 下記の dn のクライアント証明書を送信しています
    • id-at-commonName=user03@example.org
  • id-ce-extKeyUsage には id-kp-clientAuth を付けています

この後はサーバからの ChangeCipherSpec と Finished が続きます.

    SSLv3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: SSL 3.0 (0x0300)
        Length: 1
        Change Cipher Spec Message
    SSLv3 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: SSL 3.0 (0x0300)
        Length: 64
        Handshake Protocol: Encrypted Handshake Message
有効ではないクライアント証明書による接続

ブラウザには SSL 接続 エラー と表示されました.
サーバは,クライアント証明書を検証して有効ではないと判定して ChangeCipherSpec, Finished ではなく,Alert をクライアントへ返しています.

    TLSv1 Record Layer: Alert (Level: Fatal, Description: Certificate Expired)
        Content Type: Alert (21)
        Version: TLS 1.0 (0x0301)
        Length: 2
        Alert Message
            Level: Fatal (2)
            Description: Certificate Expired (45)

今回は,有効期限が切れているクライアント証明書をサーバへ送ったため Certificate Expired がきちんと返ってきています.

所感

  • Apache のクライアント認証の設定はそれほど難しくはない
  • 証明書の管理ができれば,期限付きでアクセスする権限を与えることが簡単にできそう
    • クライアント証明書を検証する CA 証明書は複数枚設定することが可能なので,ある程度いい加減な管理でも良さそう(CA の期限が切れる前に追加すればいいので)