Configuring HTTPS servers配置HTTPS服务器
To configure an HTTPS server, the 要配置HTTPS服务器,必须在服务器块中的侦听套接字上启用ssl
parameter must be enabled on listening sockets in the server block, and the locations of the server certificate and private key files should be specified:ssl
参数,并且应指定服务器证书和私钥文件的位置:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
The server certificate is a public entity. 服务器证书是公共实体。It is sent to every client that connects to the server. 它被发送到连接到服务器的每个客户端。The private key is a secure entity and should be stored in a file with restricted access, however, it must be readable by nginx’s master process. 私钥是一个安全实体,应该存储在访问受限的文件中,但是,它必须能够被nginx的主进程读取。The private key may alternately be stored in the same file as the certificate:私钥可以交替地存储在与证书相同的文件中:
ssl_certificate www.example.com.cert; ssl_certificate_key www.example.com.cert;
in which case the file access rights should also be restricted. 在这种情况下,文件访问权限也应受到限制。Although the certificate and the key are stored in one file, only the certificate is sent to a client.尽管证书和密钥存储在一个文件中,但只有证书被发送到客户端。
The directives ssl_protocols and ssl_ciphers can be used to limit connections to include only the strong versions and ciphers of SSL/TLS. 指令ssl_protocols和ssl_ciphers可用于限制连接,使其仅包括ssl/TLS的强版本和密码。By default nginx uses “默认情况下,nginx使用“ssl_protocols TLSv1 TLSv1.1 TLSv1.2
” and “ssl_ciphers HIGH:!aNULL:!MD5
”, so configuring them explicitly is generally not needed. ssl_protocols TLSv1 TLSv1.1 TLSv1.2
”和“ssl_ciphers HIGH:!aNULL:!MD5
”,因此通常不需要显式配置它们。Note that default values of these directives were changed several times.请注意,这些指令的默认值已更改多次。
HTTPS server optimizationHTTPS服务器优化
SSL operations consume extra CPU resources. SSL操作会消耗额外的CPU资源。On multi-processor systems several worker processes should be run, no less than the number of available CPU cores. 在多处理器系统上,应运行多个工作进程,不少于可用CPU内核的数量。The most CPU-intensive operation is the SSL handshake. CPU最密集的操作是SSL握手。There are two ways to minimize the number of these operations per client:有两种方法可以最大限度地减少每个客户端的这些操作数:
the first is by enabling keepalive connections to send several requests via one connection and the second is to reuse SSL session parameters to avoid SSL handshakes for parallel and subsequent connections. 第一种是通过启用keepalive连接通过一个连接发送多个请求,第二种是重用SSL会话参数,以避免并行和后续连接的SSL握手。The sessions are stored in an SSL session cache shared between workers and configured by the ssl_session_cache directive. 会话存储在工作者之间共享的SSL会话缓存中,并由ssl_session_cache指令配置。One megabyte of the cache contains about 4000 sessions. 1兆字节的缓存包含大约4000个会话。The default cache timeout is 5 minutes. 默认缓存超时为5分钟。It can be increased by using the ssl_session_timeout directive. 它可以通过使用ssl_session_timeout指令来增加。Here is a sample configuration optimized for a multi-core system with 10 megabyte shared session cache:以下是一个针对具有10 MB共享会话缓存的多核系统优化的示例配置:
worker_processes auto; http { ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; server { listen 443 ssl; server_name www.example.com; keepalive_timeout 70; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ...
SSL certificate chainsSSL证书链
Some browsers may complain about a certificate signed by a well-known certificate authority, while other browsers may accept the certificate without issues. 一些浏览器可能会抱怨由著名的证书颁发机构签署的证书,而其他浏览器可能会接受没有问题的证书。This occurs because the issuing authority has signed the server certificate using an intermediate certificate that is not present in the certificate base of well-known trusted certificate authorities which is distributed with a particular browser. 发生这种情况的原因是,颁发机构已使用中间证书对服务器证书进行了签名,该中间证书不存在于与特定浏览器一起分发的知名可信证书颁发机构的证书库中。In this case the authority provides a bundle of chained certificates which should be concatenated to the signed server certificate. 在这种情况下,授权机构提供了一组链接证书,这些证书应连接到已签名的服务器证书。The server certificate must appear before the chained certificates in the combined file:在组合文件中,服务器证书必须出现在链接证书之前:
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt
The resulting file should be used in the ssl_certificate directive:生成的文件应在ssl_certificate指令中使用:
server { listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.chained.crt; ssl_certificate_key www.example.com.key; ... }
If the server certificate and the bundle have been concatenated in the wrong order, nginx will fail to start and will display the error message:如果服务器证书和捆绑包以错误的顺序连接,nginx将无法启动并显示错误消息:
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed (SSL: error:0B080074:x509 certificate routines: X509_check_private_key:key values mismatch)
because nginx has tried to use the private key with the bundle’s first certificate instead of the server certificate.因为nginx尝试将私钥与捆绑包的第一个证书而不是服务器证书一起使用。
Browsers usually store intermediate certificates which they receive and which are signed by trusted authorities, so actively used browsers may already have the required intermediate certificates and may not complain about a certificate sent without a chained bundle. 浏览器通常存储它们接收的中间证书,这些证书由受信任的权威机构签名,因此积极使用的浏览器可能已经具有所需的中间证书,并且可能不会抱怨没有链接包发送的证书。To ensure the server sends the complete certificate chain, the 为了确保服务器发送完整的证书链,可以使用openssl
command-line utility may be used, for example:openssl
命令行实用程序,例如:
$ openssl s_client -connect www.godaddy.com:443 ... Certificate chain 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc /OU=MIS Department/CN=www.GoDaddy.com /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b) i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc. /OU=http://certificates.godaddy.com/repository /CN=Go Daddy Secure Certification Authority /serialNumber=07969287 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc. /OU=http://certificates.godaddy.com/repository /CN=Go Daddy Secure Certification Authority /serialNumber=07969287 i:/C=US/O=The Go Daddy Group, Inc. /OU=Go Daddy Class 2 Certification Authority 2 s:/C=US/O=The Go Daddy Group, Inc. /OU=Go Daddy Class 2 Certification Authority i:/L=ValiCert Validation Network/O=ValiCert, Inc. /OU=ValiCert Class 2 Policy Validation Authority /CN=http://www.valicert.com//emailAddress=info@valicert.com ...
When testing configurations with SNI, it is important to specify the使用SNI测试配置时,必须指定-servername
option asopenssl
does not use SNI by default.-servername
选项,因为openssl
默认情况下不使用SNI。
In this example the subject (“s”) of the 在本例中,www.GoDaddy.com
server certificate #0 is signed by an issuer (“i”) which itself is the subject of the certificate #1, which is signed by an issuer which itself is the subject of the certificate #2, which signed by the well-known issuer ValiCert, Inc. whose certificate is stored in the browsers’ built-in certificate base (that lay in the house that Jack built).www.GoDaddy.com
服务器证书#0的主体(“s”)由证书#1主体的发行人(“i”)签署,证书#1主体由著名发行人ValiCert, Inc.签署,证书#2,其证书存储在浏览器内置的证书库中(位于Jack建造的房子中)。
If a certificate bundle has not been added, only the server certificate #0 will be shown.如果未添加证书捆绑包,则仅显示服务器证书#0。
A single HTTP/HTTPS server单个HTTP/HTTPS服务器
It is possible to configure a single server that handles both HTTP and HTTPS requests:可以配置一台同时处理HTTP和HTTPS请求的服务器:
server { listen 80; listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ... }
Prior to 0.7.14 SSL could not be enabled selectively for individual listening sockets, as shown above.如上所示,0.7.14之前的版本无法为单个侦听套接字选择性地启用SSL。SSL could only be enabled for the entire server using the ssl directive, making it impossible to set up a single HTTP/HTTPS server.只能使用ssl指令为整个服务器启用SSL,因此无法设置单个HTTP/HTTPS服务器。The添加了listen指令的ssl
parameter of the listen directive was added to solve this issue.ssl
参数以解决此问题。The use of the ssl directive in modern versions is thus discouraged.因此,不鼓励在现代版本中使用ssl指令。
Name-based HTTPS servers基于名称的HTTPS服务器
A common issue arises when configuring two or more HTTPS servers listening on a single IP address:配置两个或多个HTTPS服务器侦听单个IP地址时,会出现一个常见问题:
server { listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ... } server { listen 443 ssl; server_name www.example.org; ssl_certificate www.example.org.crt; ... }
With this configuration a browser receives the default server’s certificate, i.e. 通过此配置,浏览器将接收默认服务器的证书,即www.example.com
regardless of the requested server name. www.example.com
,而不考虑请求的服务器名称。This is caused by SSL protocol behaviour. 这是由SSL协议行为引起的。The SSL connection is established before the browser sends an HTTP request and nginx does not know the name of the requested server. SSL连接在浏览器发送HTTP请求之前建立,nginx不知道请求服务器的名称。Therefore, it may only offer the default server’s certificate.因此,它可能只提供默认服务器的证书。
The oldest and most robust method to resolve the issue is to assign a separate IP address for every HTTPS server:解决此问题最古老、最可靠的方法是为每个HTTPS服务器分配一个单独的IP地址:
server { listen 192.168.1.1:443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ... } server { listen 192.168.1.2:443 ssl; server_name www.example.org; ssl_certificate www.example.org.crt; ... }
An SSL certificate with several names具有多个名称的SSL证书
There are other ways that allow sharing a single IP address between several HTTPS servers. 还有其他方法允许在多个HTTPS服务器之间共享单个IP地址。However, all of them have their drawbacks. 然而,它们都有各自的缺点。One way is to use a certificate with several names in the SubjectAltName certificate field, for example, 一种方法是在SubjectAltName证书字段中使用具有多个名称的证书,例如www.example.com
and www.example.org
. www.example.com
和www.example.org
。However, the SubjectAltName field length is limited.但是,SubjectAltName字段长度是有限的。
Another way is to use a certificate with a wildcard name, for example, 另一种方法是使用带有通配符名称的证书,例如,*.example.org
. *.example.org
。A wildcard certificate secures all subdomains of the specified domain, but only on one level. 通配符证书保护指定域的所有子域,但仅在一个级别上。This certificate matches 此证书与www.example.org
, but does not match example.org
and www.sub.example.org
. www.example.org
匹配,但与example.org
和www.sub.example.org
不匹配。These two methods can also be combined. 这两种方法也可以结合使用。A certificate may contain exact and wildcard names in the SubjectAltName field, for example, 证书的SubjectAltName字段中可能包含精确的通配符名称,例如example.org
and *.example.org
.example.org
和*.example.org
。
It is better to place a certificate file with several names and its private key file at the http level of configuration to inherit their single memory copy in all servers:最好将具有多个名称的证书文件及其私钥文件置于http配置级别,以便在所有服务器中继承它们的单个内存副本:
ssl_certificate common.crt; ssl_certificate_key common.key; server { listen 443 ssl; server_name www.example.com; ... } server { listen 443 ssl; server_name www.example.org; ... }
Server Name Indication服务器名称指示
A more generic solution for running several HTTPS servers on a single IP address is TLS Server Name Indication extension (SNI, RFC 6066), which allows a browser to pass a requested server name during the SSL handshake and, therefore, the server will know which certificate it should use for the connection. 在一个IP地址上运行多个HTTPS服务器的一个更通用的解决方案是TLS服务器名称指示扩展(SNI,RFC 6066),它允许浏览器在SSL握手期间传递请求的服务器名称,因此,服务器将知道其应用于连接的证书。SNI is currently supported by most modern browsers, though may not be used by some old or special clients.目前大多数现代浏览器都支持SNI,但一些旧的或特殊的客户端可能不使用SNI。
Only domain names can be passed in SNI, however some browsers may erroneously pass an IP address of the server as its name if a request includes literal IP address.SNI中只能传递域名,但如果请求包含文字IP地址,则某些浏览器可能会错误地将服务器的IP地址作为其名称传递。One should not rely on this.我们不应该依赖这一点。
In order to use SNI in nginx, it must be supported in both the OpenSSL library with which the nginx binary has been built as well as the library to which it is being dynamically linked at run time. 为了在nginx中使用SNI,构建nginx二进制文件的OpenSSL库以及运行时动态链接到的库都必须支持SNI。OpenSSL supports SNI since 0.9.8f version if it was built with config option OpenSSL从0.9.8f版本开始就支持SNI,如果它是使用配置选项Since OpenSSL 0.9.8j this option is enabled by default. 由于OpenSSL 0.9.8j,默认情况下会启用此选项。If nginx was built with SNI support, then nginx will show this when run with the “-V” switch:如果nginx是使用SNI支持构建的,那么nginx在使用“-V”开关运行时将显示:
$ nginx -V ... TLS SNI support enabled ...
However, if the SNI-enabled nginx is linked dynamically to an OpenSSL library without SNI support, nginx displays the warning:但是,如果启用SNI的nginx动态链接到不支持SNI的OpenSSL库,nginx将显示警告:
nginx was built with SNI support, however, now it is linked dynamically to an OpenSSL library which has no tlsext support, therefore SNI is not available
Compatibility兼容性
The SNI support status has been shown by the “-V” switch since 0.8.21 and 0.7.62.自0.8.21和0.7.62起,SNI支持状态由“-V”开关显示。Thelisten指令的ssl
parameter of the listen directive has been supported since 0.7.14. Prior to 0.8.21 it could only be specified along with thedefault
parameter.ssl
参数自0.7.14以来一直受支持。在0.8.21之前,它只能与默认参数一起指定。SNI has been supported since 0.5.23.SNI自0.5.23以来一直受到支持。The shared SSL session cache has been supported since 0.5.6.自0.5.6以来,已支持共享SSL会话缓存。
Version 1.9.1 and later: the default SSL protocols are TLSv1, TLSv1.1, and TLSv1.2 (if supported by the OpenSSL library).版本1.9.1及更高版本:默认SSL协议为TLSv1、TLSv1.1和TLSv1.2(如果OpenSSL库支持)。Version 0.7.65, 0.8.19 and later: the default SSL protocols are SSLv3, TLSv1, TLSv1.1, and TLSv1.2 (if supported by the OpenSSL library).版本0.7.65、0.8.19及更高版本:默认SSL协议为SSLv3、TLSv1、TLSv1.1和TLSv1.2(如果OpenSSL库支持)。Version 0.7.64, 0.8.18 and earlier: the default SSL protocols are SSLv2, SSLv3, and TLSv1.版本0.7.64、0.8.18和更早版本:默认SSL协议为SSLv2、SSLv3和TLSv1。
Version 1.0.5 and later: the default SSL ciphers are “版本1.0.5及更高版本:默认SSL密码为“HIGH:!aNULL:!MD5
”.HIGH:!aNULL:!MD5
”。Version 0.7.65, 0.8.20 and later: the default SSL ciphers are “版本0.7.65、0.8.20及更高版本:默认SSL密码为“HIGH:!ADH:!MD5
”.HIGH:!ADH:!MD5
”。Version 0.8.19: the default SSL ciphers are “版本0.8.19:默认SSL密码为“ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM
”.ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM
”。Version 0.7.64, 0.8.18 and earlier: the default SSL ciphers are “版本0.7.64、0.8.18和更早版本:默认SSL密码为“ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
”.ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
”。
written by Igor Sysoev edited by Brian Mercer |