我有一台 CentOS 6 服务器,运行 Apache 2.2.15 和 OpenSSL 1.0.1e-fips。我正在尝试为我的 Web 根目录中的特定位置设置双向 SSL 身份验证。第三方提供了公共(纯文本)和私有(二进制)证书。
我需要一些关于如何包含公共和私人证书以使握手正常工作的指导,因为我收到以下错误:
重新协商握手失败:客户端不接受!?
以下是我的 /etc/httpd/conf.d/ssl.conf 文件中与本节相关的内容:
<Location /api/path/>
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCACertificateFile /etc/pki/tls/private/public.cer
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
</Location>
诚然,我不是 SSL 专家。但我知道如何安装和运行证书。我已将 logginf 调至“调试”级别。我尝试遵循以下指南:
http://www.stefanocapitanio.com/configuring-two-way-authentication-ssl-with-apache/
提前致谢!
完整的 ssl.conf 文件:
LoadModule ssl_module modules/mod_ssl.so
Listen 443
SSLPassPhraseDialog builtin
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
#SSLRandomSeed startup file:/dev/random 512
#SSLRandomSeed connect file:/dev/random 512
#SSLRandomSeed connect file:/dev/urandom 512
SSLCryptoDevice builtin
#SSLCryptoDevice ubsec
<VirtualHost *:443>
DocumentRoot "/var/www/html/staging-site"
ServerName staging.site.com:443
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel debug
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/pki/tls/certs/cert.crt
SSLCertificateKeyFile /etc/pki/tls/private/private.key
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
SSLCACertificateFile /etc/pki/tls/certs/rapidssl.crt
#SSLVerifyClient require
#SSLVerifyDepth 10
# Access Control:
#<Location />
#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#</Location>
<Location /path/api/>
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCACertificateFile /etc/pki/tls/private/3rdpartyprivate.cer
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
</Location>
# SSL Engine Options:
#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
# SSL Protocol Adjustments:
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# Per-Server Logging:
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
答案1
我认为您没有在正确的地方使用正确的证书。您应该在SSLCertificateFile
(PEM 格式的证书)、SSLCertificateKeyFile
(与证书匹配的 PEM 格式的密钥)和SSLCertificateChainFile
(从主机证书的颁发者证书开始直到 PEM 格式的根证书的证书)中使用受信任 CA 颁发的服务器证书。
您SSLCACertificateFile
必须使用签署客户端证书的 CA 的证书(同样为 PEM 格式)。
这是一个完整的示例,请记住,我使用的服务器证书由签署客户端证书的同一 CA 签署。如果您的需求不同,请进行调整。
生成证书
openssl genrsa -des3 -out ca.key 4096 openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=Self-Signed CA" openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=client" openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt openssl genrsa -out server.key 4096 openssl req -new -key server.key -out server.csr -subj "/C=US/ST=Some State/L=FancyTown/O=SomeOrg/CN=server" openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out server.crt
将它们移至更方便的位置
mkdir /etc/ssl_ ; mv * /etc/ssl_
安装 webserver 和 mod_ssl
yum install -y httpd mod_ssl
清除默认 TLS 配置
truncate -s0 /etc/httpd/conf.d/ssl.conf
所有 VHost 的通用 TLS 配置,
/etc/httpd/conf.d/00-ssl.conf
``` LoadModule ssl_module modules/mod_ssl.so
监听 443 https SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt SSLStaplingCache shmcb:/run/httpd/stapling_cache(128000) SSLUseStapling 关闭
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog SSLSessionCache shmcb:/run/httpd/sslcache(512000) SSLSessionCacheTimeout 300 SSLRandomSeed 启动文件:/dev/urandom 256 SSLRandomSeed 连接内置 SSLCryptoDevice 内置
SSLStrictSNIVHost勾选 SSLProtocol +TLSv1.2 -TLSv1.1 -TLSv1 -SSLv3 SSLHonorCipherOrder
SSLCompression 关闭 SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:-ECDHE-RSA-RC4-SHA:ECDHE-RSA-AE S256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:-RC4-SHA:AES256- GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA ```
- VHost 配置
/etc/httpd/conf.d/50-ssl-vhost.conf
``` ServerAlias localhost.localdomain localhost ServerName server SSLEngine on SSLCertificateFile /etc/_ssl/server.crt SSLCertificateKeyFile /etc/_ssl/server.key SSLCertificateChainFile /etc/_ssl/ca.crt SSLCACertificateFile /etc/_ssl/ca.crt
SSLVerifyClient require
SSLVerifyDepth 10
DocumentRoot /var/www/html
<Directory /var/www/html>
Require all granted
</Directory>
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
```
创建
index.html
测试文件echo 'It works\!' > /var/www/html/index.html
启动 httpd
systemctl enable --now httpd
- 添加主机名
echo '127.0.1.1 server' >> /etc/hosts
- 测试
这有效(身份验证成功):
( echo -en 'GET / HTTP/1.1\r\nHost: server\r\n\r\n' ; sleep 2) | openssl s_client -CAfile /etc/_ssl/ca.crt -cert /etc/_ssl/client.crt -key /etc/_ssl/cli ent.key -connect server:443 -servername server
这不行,我们没有提供正确的证书:
( echo -en 'GET / HTTP/1.1\r\nHost: server\r\n\r\n' ; sleep 2) | openssl s_client -CAfile /etc/_ssl/ca.crt -connect server:443 -servername server
答案2
针对我们的情况,我们最终做出了三项改变:
取消注释 SSLCertificateChainFile 并将其设置为 RapidSSL 的证书链文件(谁颁发了我们的证书)。
将 SSLCACertificateFile 更改为第三方颁发者(颁发其证书的机构)的 CA 链文件。
从指令中删除了 SSLCACertificateFile。
一旦我们改变这些并重新启动,双向认证就会起作用,他们就可以访问 API。
感谢@fuero 的帮助。