nginx-7 配置HTTPS服务器

2019-03-26  本文已影响0人  苍老的小孩_a1fe

想要配置一个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的master进程是可读取的。私钥可以与证书交替存储在同一个文件中。

ssl_certificate     www.example.com.cert;
ssl_certificate_key www.example.com.cert;

在这种情况下,文件访问权限也应该受到限制。尽管证书和密钥存储在一个文件中,但只有证书被发送到客户机。

指令ssl_protocols和ssl_ciphers可以用来限制连接只包括SSL/TLS的强版本和加密算法。默认情况下,nginx使用ssl_protocols TLSv1 TLSv1.1 TLSv1.2ssl_ciphers HIGH:!aNULL:!MD5,所以没必要显示配置他们,但是要注意nginx的不同版本他们对应的默认值可能是不一样的。下面会讲到。

HTTPS服务器性能优化

SSL操作会消耗CPU资源,其中,SSL握手最为突出。因此,要提高HTTPS服务器的性能,就要最小化每个客户端连接SSL操作的次数。nginx对此有两种应对方式。

  1. 启用keepalive,使得通过一个连接可以发送多个请求,而不是一个连接一个请求
  2. 重用ssl session,对于并行和后续连接,避免SSL握手
    ssl_session_cache
    ssl_session_timeout 默认5m
worker_processes auto;

http {
    # shared 在worker进程间共享
    # SSL
    # 10m/10M  10兆内存空间(megabyte)
    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

如果服务器证书在链接证书之后,nginx会启动失败,并展示以下错误信息。

SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
   (SSL: error:0B080074:x509 certificate routines:
    X509_check_private_key:key values mismatch)

生成的文件应作为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;
    ...
}

一个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;
    ...
}

基于名称的HTTPS服务器

当在一个ip地址上配两个或两个以上的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还是www.example.org,只会收到www.example.com.crt证书。因为在建立SSL连接的时候,服务器名称是未知的,这种情况下,IP地址一样,nginx会选择一个默认服务器,也就是第一个,来处理请求,所以客户端收到的总是第一个服务器的证书。可以通过配置不同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;
    ...
}

除此之外,解决方法还有拥有多个域名的证书SNI(Server Name Indication)

可以匹配多个域名的证书

  1. 拥有多个全称域名的证书
    全称域名的长度是有限制的
# 这种证书,可以提升作用域,不必写在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;
    ...
}
  1. 通配符域名证书
    与在服务器名称中讲的不一致,这里的通配符只能匹配一个部分。比如*.example.org,只能匹配www.example.org,而不能匹配example.org或者www.sub.example.org

SNI(Server Name Indication)

SNI允许在SSL握手的时候,客户端传递一个服务器名称给服务器。这种情况下,即使多个HTTPS服务器使用同一个IP,只要服务器名称不同,nginx就知道使用哪个服务器了。这是一种更常用的解决方法。现在大多数浏览器都支持SNI。

注意:SNI只传递域名,不应该是IP

为了在nginx中使用sni,必须在构建nginx二进制文件的openssl库以及在运行时动态链接到的库中都支持它。OpenSSL从0.9.8f版本开始支持SNI,前提OpenSSL使用配置选项 --enable-tlsext 构建。自从0.9.8j这个配置选项是默认的。如果nginx是支持SNI的,使用 nginx -V 如下。

$ nginx -V
...
TLS SNI support enabled
...

但是,如果支持SNI的nginx动态链接的OpenSSL库不支持SNI,将会有如下警告。

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

考虑兼容性

上一篇 下一篇

猜你喜欢

热点阅读