apache / 2.4 / reference / ssl-ssl_howto.html

SSL/TLS 强加密:操作方法

本文档旨在帮助您入门,并使一些工作正常进行。强烈建议您阅读其余的 SSL 文档,并在 continue 学习高级技术之前对材料进行更深入的了解。

基本配置示例

您的 SSL 配置至少需要包含以下指令。

LoadModule ssl_module modules/mod_ssl.so

Listen 443
<VirtualHost *:443>
    ServerName www.example.com
    SSLEngine on
    SSLCertificateFile "/path/to/www.example.com.cert"
    SSLCertificateKeyFile "/path/to/www.example.com.key"
</VirtualHost>

密码套件并加强安全性

如何创建仅接受强加密的 SSL 服务器?

以下仅启用最强的密码:

SSLCipherSuite HIGH:!aNULL:!MD5

在使用以下配置时,您可以为特定的速度优化密码指定首选项(如果 Client 端支持,它将由 mod_ssl 选择):

SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:!aNULL:!MD5
SSLHonorCipherOrder on

如何创建一个 SSL 服务器,该服务器通常接受所有类型的密码,但是需要强密码才能访问特定的 URL?

显然,在服务器范围内的SSLCipherSuite只能将密码限制为强大的变体形式,但这并不是答案。但是,可以在Location块内重新配置mod_ssl,以提供按目录的解决方案,并且可以自动强制重新协商 SSL 参数以满足新配置。可以按照以下步骤进行:

# be liberal in general
SSLCipherSuite ALL:!aNULL:RC4+RSA:+HIGH:+MEDIUM:+LOW:+EXP:+eNULL

<Location "/strong/area">
# but https://hostname/strong/area/ and below
# requires strong ciphers
SSLCipherSuite HIGH:!aNULL:!MD5
</Location>

OCSP Stapling

联机证书状态协议(OCSP)是一种用于确定服务器证书是否已被吊销的机制,而 OCSP 装订是一种特殊形式,其中服务器(例如 httpd 和 mod_ssl)将为其证书维护当前的 OCSP 响应。并将它们发送给与服务器通信的 Client 端。大多数证书包含由签发证书颁发机构维护的 OCSP 响应者的地址,并且 mod_ssl 可以与该响应者进行通信,以获得可以发送给与服务器进行通信的 Client 端的签名响应。

因为 Client 端可以从服务器获取证书吊销状态,而无需从 Client 端到证书颁发机构的额外连接,所以 OCSP 装订是获取吊销状态的首选方法。消除 Client 端与证书颁发机构之间的通信的其他好处是,Client 端浏览历史记录不会暴露给证书颁发机构,并且通过不依赖于可能负载较重的证书颁发机构服务器来获取状态更加可靠。

由于在响应有效期间可以将使用同一证书的所有 Client 端重用服务器获得的响应,因此服务器的开销很小。

正确配置了常规 SSL 支持后,启用 OCSP 装订通常只需要对 httpd 配置进行非常小的修改-增加这两个指令:

SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

这些指令位于放置其他全局 SSL 配置指令的任何地方的全局范围内(即不在虚拟主机定义内),例如在conf/extra/httpd-ssl.conf中表示 httpd 的常规开源构建,在/etc/apache2/mods-enabled/ssl.conf中表示 Ubuntu 或 Debian Binding 的 httpd,等等。

SSLStaplingCache指令上的路径(例如logs/)应与SSLSessionCache指令上的路径匹配。此路径相对于ServerRoot

这个特定的SSLStaplingCache指令需要mod_socache_shmcb(从该指令的参数的shmcb前缀开始)。通常已为SSLSessionCache或代表mod_ssl以外的某个模块启用了此模块。如果您使用mod_socache_shmcb以外的机制启用了 SSL 会话缓存,则也应对SSLStaplingCache使用该替代机制。例如:

SSLSessionCache "dbm:logs/ssl_scache"
SSLStaplingCache "dbm:logs/ssl_stapling"

您可以使用 openssl 命令行程序来验证服务器是否发送了 OCSP 响应:

$ openssl s_client -connect www.example.com:443 -status -servername www.example.com
...
OCSP response: 
======================================
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
...
    Cert Status: Good
...

以下各节重点介绍了需要对配置进行进一步修改的最常见情况。另请参阅mod_ssl参考手册。

如果服务器使用了多个 SSL 证书

OCSP 响应存储在 SSL 装订缓存中。尽管响应的大小通常为几百到几千个字节,但 mod_ssl 支持 OCSP 响应,最大大小约为 1 万个字节。如果证书不止几个,则可能需要增加装订缓存大小(以上示例中为 32768 字节)。如果存储响应时出错,将记录错误消息 AH01929.

如果证书没有指向 OCSP 响应者,或者必须使用其他地址

请参阅SSLStaplingForceURL指令。

您可以使用 openssl 命令行程序确认服务器证书指向 OCSP 响应者,如下所示:

$ openssl x509 -in ./www.example.com.crt -text | grep 'OCSP.*http'
OCSP - URI:http://ocsp.example.com

如果提供了 OCSP URI,并且 Web 服务器无需使用代理即可直接与其通信,则无需进行配置。请注意,可能需要调整控制来自 Web 服务器的出站连接的防火墙规则。

如果未提供 OCSP URI,请与您的证书颁发机构联系以确定是否可用。如果是这样,请在使用证书的虚拟主机中将其配置为SSLStaplingForceURL

如果配置了多个启用 SSL 的虚拟主机,并且某些主机应禁用 OCSP 装订

SSLUseStapling Off添加到应禁用 OCSP 装订的虚拟主机。

如果 OCSP 响应程序速度慢或不可靠

有几种指令可用于处理超时和错误。请参考SSLStaplingFakeTryLaterSSLStaplingResponderTimeoutSSLStaplingReturnResponderErrors指令的文档。

如果 mod_ssl 记录错误 AH02217

AH02217: ssl_stapling_init_cert: Can't retrieve issuer certificate!

为了在使用特定服务器证书时支持 OCSP 装订,必须配置该证书的证书链。如果未将其配置为启用 SSL 的一部分,则在启用装订时将发出 AH02217 错误,并且不会为使用证书的 Client 端提供 OCSP 响应。

有关配置证书链的说明,请参考SSLCertificateChainFileSSLCertificateFile

Client 端身份验证和访问控制

如何强制 Client 端使用证书进行身份验证?

当您知道所有用户时(例如,在公司 Intranet 上通常如此),则可以要求普通证书身份验证。您需要做的就是创建由您自己的 CA 证书(ca.crt)签名的 Client 端证书,然后根据该证书验证 Client 端。

# require a client certificate which has to be directly
# signed by our CA certificate in ca.crt
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile "conf/ssl.crt/ca.crt"

如何强制 Client 端对特定 URL 使用证书进行身份验证,但仍然允许任意 Client 端访问服务器的其余部分?

要强制 Client 端使用针对特定 URL 的证书进行身份验证,可以使用mod_ssl的按目录重新配置功能:

SSLVerifyClient none
SSLCACertificateFile "conf/ssl.crt/ca.crt"

<Location "/secure/area">
SSLVerifyClient require
SSLVerifyDepth 1
</Location>

如何仅允许具有证书的 Client 端访问特定的 URL,但允许所有 Client 端访问服务器的其余部分?

这样做的关键是检查 Client 端证书的一部分是否符合您的期望。通常,这意味着检查全部或部分专有名称(DN),以查看其是否包含某些已知字符串。有两种方法可以使用mod_auth_basicSSLRequire

当证书是完全任意的,或者它们的 DN 没有公共字段(通常是组织等)时,通常需要mod_auth_basic方法。在这种情况下,您应该构建一个包含* all *允许的 Client 端的密码数据库,如下所示:

SSLVerifyClient      none
SSLCACertificateFile "conf/ssl.crt/ca.crt"
SSLCACertificatePath "conf/ssl.crt"

<Directory "/usr/local/apache2/htdocs/secure/area">
    SSLVerifyClient      require
    SSLVerifyDepth       5
    SSLOptions           +FakeBasicAuth
    SSLRequireSSL
    AuthName             "Snake Oil Authentication"
    AuthType             Basic
    AuthBasicProvider    file
    AuthUserFile         "/usr/local/apache2/conf/httpd.passwd"
    Require              valid-user
</Directory>

在此示例中使用的密码是 DES 加密字符串“ password”。有关更多信息,请参见SSLOptions文档。

httpd.passwd

/C=DE/L=Munich/O=Snake Oil, Ltd./OU=Staff/CN=Foo:xxj31ZMTZzkVA
/C=US/L=S.F./O=Snake Oil, Ltd./OU=CA/CN=Bar:xxj31ZMTZzkVA
/C=US/L=L.A./O=Snake Oil, Ltd./OU=Dev/CN=Quux:xxj31ZMTZzkVA

当您的 Client 全部属于编码为 DN 的通用层次结构的一部分时,可以使用SSLRequire轻松匹配它们,如下所示:

SSLVerifyClient      none
SSLCACertificateFile "conf/ssl.crt/ca.crt"
SSLCACertificatePath "conf/ssl.crt"

<Directory "/usr/local/apache2/htdocs/secure/area">
  SSLVerifyClient      require
  SSLVerifyDepth       5
  SSLOptions           +FakeBasicAuth
  SSLRequireSSL
  SSLRequire       %{SSL_CLIENT_S_DN_O}  eq "Snake Oil, Ltd." \
               and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"}
</Directory>

对于来自 Internet 的 Client 端,我如何要求 HTTPS 具有强密码,基本身份验证或 Client 端证书才能访问 Intranet 网站的一部分?我仍然希望允许 Intranet 上的 Client 端进行简单的 HTTP 访问。

这些示例假定 Intranet 上的 Client 端 IP 地址在 192.168.1.0/24 范围内,并且您要允许 Internet 访问的 Intranet 网站部分为/usr/local/apache2/htdocs/subarea。此配置应保留在 HTTPS 虚拟主机之外,以便它适用于 HTTPS 和 HTTP。

SSLCACertificateFile "conf/ssl.crt/company-ca.crt"

<Directory "/usr/local/apache2/htdocs">
    #   Outside the subarea only Intranet access is granted
    Require              ip 192.168.1.0/24
</Directory>

<Directory "/usr/local/apache2/htdocs/subarea">
    #   Inside the subarea any Intranet access is allowed
    #   but from the Internet only HTTPS + Strong-Cipher + Password
    #   or the alternative HTTPS + Strong-Cipher + Client-Certificate
    
    #   If HTTPS is used, make sure a strong cipher is used.
    #   Additionally allow client certs as alternative to basic auth.
    SSLVerifyClient      optional
    SSLVerifyDepth       1
    SSLOptions           +FakeBasicAuth +StrictRequire
    SSLRequire           %{SSL_CIPHER_USEKEYSIZE} >= 128
    
    #   Force clients from the Internet to use HTTPS
    RewriteEngine        on
    RewriteCond          "%{REMOTE_ADDR}" "!^192\.168\.1\.[0-9]+$"
    RewriteCond          "%{HTTPS}" "!=on"
    RewriteRule          "." "-" [F]
    
    #   Allow Network Access and/or Basic Auth
    Satisfy              any
    
    #   Network Access Control
    Require              ip 192.168.1.0/24
    
    #   HTTP Basic Authentication
    AuthType             basic
    AuthName             "Protected Intranet Area"
    AuthBasicProvider    file
    AuthUserFile         "conf/protected.passwd"
    Require              valid-user
</Directory>

Logging

LogLevel设置为较高的跟踪级别时,mod_ssl可以将极其详细的调试信息记录到错误日志中。另一方面,在非常繁忙的服务器上,级别info可能已经太多了。请记住,您可以根据需要配置每个模块的LogLevel