首页 > 系统 > Linux >

nginx.org的Configuring HTTPS servers页面翻译

2016-10-09

nginx org的Configuring HTTPS servers页面翻译。国庆期间,抽时间翻译。英文水平太差,翻译太费劲了。。。英文文档对应页面:Configuring HTTPS servers。

国庆期间,抽时间翻译。英文水平太差,翻译太费劲了。。。

英文文档对应页面:Configuring HTTPS servers

配置https服务

为了配置https服务,必须开启 "server"块的 "listen" 指令的 "ssl" 参数,并且需要指定 "server_certificate" 和 "private_key" 文件位置:


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;
}

服务器证书是一个公共的实体。会发送给每个连接到这台服务器的客户端。密钥是一个安全的(私有到)实体,并且应该被存储到一个访问受限的文件中,但必须保证针nginx的主进程是可读的。密钥也可以被存储到同证书相同的文件中(一个文件中,同时包含了证书和密钥),例如:
ssl_certificate     www.example.com.cert;
ssl_certificate_key www.example.com.cert;

当文件中同时包含了证书和密钥,这个文件的访问权限也应该被限制(因为密钥的访问权限需要被限制)。虽然证书和密钥存储在同一个文件中,但是连接时只有证书内容会被发送给客户端。
"ssl_protocols" 和 "sll_ciphers" 指令,可用来限制连接的SSL/TLS版本和ciphers。默认情况下,nginx使用 "ssl_protocols TLSv1 TLSv1.1 TLSv1.2" 和 "ssl_ciphers HIGH:!aNULL:!MD5",所以通常情况下,不需要准确配置它们。注意:这些指令的值被改变过好几次了。


HTTPS服务器优化

ssl操作消耗额外的cpu资源。在多处理器系统中,运行的工作进程(worker_processes)数不应该低于可用的cpu核心的数量。最密集的cpu操作是:ssl的握手操作。有2种方式去减少每个客户端的这些操作数量:第一种方式是:启用 'keepalive' 长连接,在一个连接中可发送多个请求;第二种方式是:重新使用ssl的session参数,避免并发连接和后续连接原本需要的的ssl握手操作。session存储在一个ssl的session缓存中,被工作进程(workers)和"ssl_session_cache"指令所设置的值所共享。1m缓存可包含大约4000条session。默认的缓存过期时间是5分钟。使用 "ssl_session_timeout"指令可延长缓存的过期时间。下面是使用了10m共享session缓存空间来优化一个多核系统的配置实例:
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证书链

一些浏览器抱怨,其他浏览器接受知名证书机构未发布的签名证书(某些浏览器支持一些未发布的证书,而有些浏览器并不支持)。出现这种情况是因为:发布机构使用了一个中间证书签署了服务器证书。这个证书并不是基于知名、信任的证书机构发布的证书,而是由一个特殊浏览器发布。在这种情况下,该机构提供了一个同已签名的服务器证书相关联的捆绑证书链(服务器证书同捆绑证书链在同一个文件中)。在合并的文件中,服务器证书必需出现在所有证书链之前:
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt      // 服务器证书在最前面(bundle.crt-是证书链文件)
最终的结果文件,应该被使用到 "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;
    ...
}

如果服务器证书和捆绑的证书,以错误的方式关联在一起,nginx启动失败,并且显示如下错误信息:
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
   (SSL: error:0B080074:x509 certificate routines:
    X509_check_private_key:key values mismatch)

因为nginx首先会尝试绑定证书中的第一个的私钥,替代之前的服务器证书私钥。
浏览器通常存储它们接收到的,以及信任机构签名过的中间证书,因此积极使用的浏览器可能已经有所需的中间证书,所以可能不会抱怨(complain about)一个发送过来的没有chained绑定证书(因为浏览器可能已经存储过,该证书的chained绑定证书)。为了确保服务器发送完整的证书链,可能需要使用 "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
...

在这个例子中, 'www.GoDaddy.com'服务器证书 "#0" 的主题("S")被发行人("/")签名。而发行人("/")自己又是证书 "#1"的主题,被发行人签名,该发行人自身又是 证书 "#2" 的主题,被知名发行人 "ValiCert,inc" 签名。发行人 "ValiCert,inc" 的证书存储在浏览器的内置证书基地(that lay in the house that Jack built - 不知道是啥意思)
------
太难翻译,太难懂了,总之可以理解为一个首位相关联的证书链。。。
------
如果已经添加了一个证书捆绑,仅仅会显示服务器证书 "#0"

单个HTTP/HTTPS服务器

配置同时处理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;
    ...
}

在0.7.14版本之前,SSL无法对单个监听sockets选择性地启用,就像上面展示的那样(现在是可以对单个sockets启用的)。SSL仅仅可以对使用了 "ssl" 指令的整个服务器("server"块)启用,使得配置单个HTTP/HTTPS服务器是不可能的。"listen"指令的 "ssl"参数的引入,就是为了解决这个问题。因此,在现代的这些版本中,不鼓励使用 "ssl" 指令。

基于名称的HTTPS服务器

一个普遍的问题是:一个IP地址,配置2个或更多的HTTPS服务器。
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;
    ...
}

使用这个配置,浏览器接收默认服务器的证书,即:www.example.com,而忽略请求的服务器名称。这是由 "ssl" 协议自身行为导致的。在浏览器发送HTTP请求之前,已经建立了 "ssl" 连接,这样浏览器不知道请求服务器的名字。因此,它仅仅提供默认服务器的证书。
解决这一问题的最古老、最健壮的方法是:为每个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;
    ...
}

多个server使用一个ssl证书

有其他方式,允许在几个HTTPS服务器之间分享一个单独的IP地址。然而,所有方法都有它们的缺点。一种方式是:使用一个证书,并且在 "SubjectAltName" 证书字段中使用多个服务器名称,例如:"www.example.com" 和 "www.example.org"。然而,"SubjectAltName" 字段长度有限制(只能添加有限个服务器名称)。
另一种方式是:使用一个证书和一个通配符表示的服务器名称,例如:"*.example.org"。一个通配符证书,会保证指定域名的所有子域名的安全,但仅仅是一级域名。这个证书匹配到 "www.example.org",但是不会匹配到 "example.org" 和 "www.sub.example.org"。
上面的这两种方法也可以结合使用。一个证书的 "SubjectAltName" 字段,可以包含准确的服务器名称和通配符表示的服务器名称,例如:"example.org" 和 "*.example.org"。
更好的方式是:多个服务器名称,然后在配置文件的 "http" 块中,指定 "证书文件" 和 "证书文件的密钥文件",让所有服务器都可以继承它们都配置(配置在"server"块的上层上下文中,使每个"server"块都可以共享该配置):
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;
    ...
}

服务器名称说明

在一个单独的IP地址上,运行多个HTTPS服务器的更通用的解决方案是:TLS 服务器名称说明扩展(TLS Server Name Indication extension - SNI, RFC 6066,链接地址:http://en.wikipedia.org/wiki/Server_Name_Indication),允许浏览器在SSL握手期间传递请求服务器的名称,因此,ssl握手连接时,服务器将知道它应该使用哪个证书。然而,"SNI" 受浏览器支持的限制。目前,支持SNI的浏览器版本有:
Opera 8.0;
MSIE 7.0 (but only on Windows Vista or higher);
Firefox 2.0 and other browsers using Mozilla Platform rv:1.8.1;
Safari 3.2.1 (Windows version supports SNI on Vista or higher);
and Chrome (Windows version supports SNI on Vista or higher, too).

注意:SNI中,仅可以传递域名,然而如果一个请求包含一个IP地址,一些浏览器可能错误的传递一个IP地址作为服务器名字。这是不应该依赖SNI的一个理由。(One should not rely on this - 翻译出来应该是这个意思)
为了在nginx中使用SNI,OpenSSL库和nginx二进制文件(nginx程序)都必须支持SNI,nginx中已经内置SNI的支持(不支持,可能得我们安装其他补丁或扩展?),运行时会动态链接到OpenSSL库。OpenSSL在0.9.8f版本后,开始支持SNI,安装时只需要指定配置选项 "--enable-tlsext"。OpenSSL在0.9.8f版本后,该选项是默认启用的。如果nginx内置了SNI支持,当运行'nginx -V',将显示如下信息:
$ nginx -V
...
TLS SNI support enabled
...

如果内置了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

兼容性

关于版本方面的一些支持,就不翻译了,自己查看原文档
相关文章
最新文章
热点推荐