我自己的CA用Apache发布的客户端证书

时间:2013-10-25 14:25:07

标签: apache ssl https openssl pki

尝试使用来自自签名CA的客户端证书来使HTTPS会话正常工作。连接应检查所有证书是否有效,包括客户端和服务器端。

我遵循的程序如下:

  1. 创建证书颁发机构

    openssl genrsa -out CA.key 4096
    openssl req -new -key CA.key -out CA.csr
    openssl x509 -req -days 365 -in CA.csr -out CA.crt -signkey CA.key
    
  2. 创建服务器证书

    openssl genrsa -out server.key 4096
    openssl req -new -key server.key -out server.csr
    openssl ca -in server.csr -cert CA.crt -keyfile CA.key -out server.crt
    
  3. 创建客户端证书

    openssl genrsa -out client.key 4096
    openssl req -new -key client.key -out client.csr
    openssl ca -in client.csr -cert CA.crt -keyfile CA.key -out client.crt
    
  4. 配置Apache

    <VirtualHost _default_:443>
      SSLEngine on
      SSLCertificateFile "server.crt"
      SSLCertificateKeyFile "server.key"
      SSLCACertificateFile "CA.crt"
      <Directory "/var/www">
          SSLVerifyClient optional
          SSLVerifyDepth 10
          SSLOptions +StdEnvVars +ExportCertData
      </Directory>
    </VirtualHost>  
    
  5. 现在我尝试建立测试连接:

    wget \
        --post-data 'id=1234' \
        --certificate=client.crt \
        --ca-certificate=CA.crt  \
        https://test.example.com:443
    

    wget的结果输出显示(一遍又一遍),部分:

    HTTP request sent, awaiting response... No data received.
    Retrying.
    

    从Apache检查SSL错误日志会给我以下消息:

    [debug] ssl_engine_io.c(1606): [client xx.xx.xx.xx] total of 41 bytes in buffer, eos=1
    [client xx.xx.xx.xx] Requesting connection re-negotiation
    [debug] ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#80b075190 [mem: 80b0ca003]
    [debug] ssl_engine_kernel.c(771): [client xx.xx.xx.xx] Performing full renegotiation: complete handshake protocol (client does support secure renegotiation)
    [debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSL renegotiate ciphers
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 write hello request A
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 flush data
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 write hello request C
    [info] [client xx.xx.xx.xx] Awaiting re-negotiation handshake
    [debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: before accept initialization
    [debug] ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#80b075190 [mem: 80b0ca003]
    [debug] ssl_engine_kernel.c(1929): OpenSSL: Exit: error in SSLv3 read client hello B
    [error] [client xx.xx.xx.xx] Re-negotiation handshake failed: Not accepted by client!?
    [debug] ssl_engine_io.c(1650): [client xx.xx.xx.xx] read from buffered SSL brigade, mode 0, 8192 bytes
    [debug] ssl_engine_io.c(1725): [client xx.xx.xx.xx] buffered SSL brigade exhausted
    [debug] ssl_engine_io.c(1650): [client xx.xx.xx.xx] read from buffered SSL brigade, mode 2, 0 bytes
    [info] [client XX:XX:XX:XX::xx] Connection to child 3 established (server register.kiosk.tain.com:443)
    [info] Seeding PRNG with 656 bytes of entropy
    [debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start 
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: before/accept initialization
    

    运行openssl客户端,看看这里有什么值得帮助的地方:

    openssl s_client \
        -showcerts \
        -connect test.example.com:443 \
        -cert client.crt \
        -key client.key \
        -CAfile CA.crt
    

    在回复中,我看到以下内容:

    ---
    Server certificate
    subject=/C=XX/ST=XXXXX/O=XXXX/CN=test.example.com
    issuer=/O=XXXX/L=XXXXX/ST=XXXXX/C=SE/CN=XXXX Certificate Authority
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 3846 bytes and written 519 bytes
    ---
    New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
    Server public key is 4096 bit
    

    “没有发送客户端证书CA名称”看起来与我期望的不同。我想要客户证书。

    我哪里错了?

1 个答案:

答案 0 :(得分:2)

谈论“自签名CA”并没有多大意义。您的标题(“自签名客户端SSL证书[...] ”)表明您正在谈论自签名客户端证书。你不是:你在谈论自己的CA颁发的客户证书。

您已将SSLVerifyClient指令放在Directory部分中,这意味着一旦客户端发出请求尝试访问该目录,就会重新协商获取客户端证书。< / p>

由于您的配置中没有DocumentRoot指令,因此不清楚/上的请求是否会尝试访问此目录(这可能取决于编译选项,具体取决于它的打包方式,但是/var/www不是默认值,否则。)

SSLVerifyClient直接放入虚拟主机应该至少让openssl s_client看到客户端证书请求。修复DocumentRoot可能还不够,因为您需要发出HTTP请求才能触发重新协商。