配置HTTPS服务器
要配置HTTPS服务器,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;
...
}
服务器证书是一个公共实体。它被发送到连接到服务器的每个客户端。私钥是一个安全实体,应该存储在一个受访问限制的文件中,但是它必须是nginx的主进程可读的。私钥可以替代地存储在与证书相同的文件中:
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.2”和“ ssl_ciphers HIGH:!aNULL:!MD5”,因此通常不需要明确配置它们。请注意,这些指令的默认值已更改多次。
HTTPS服务器优化
SSL操作会占用更多的CPU资源。在多处理器系统上, 应该运行几个 工作进程,不少于可用CPU内核的数量。最多的CPU密集型操作是SSL握手。有两种方法可以最大程度地减少每个客户端的这些操作数量:首先是通过使 Keepalive 连接通过一个连接发送多个请求,第二个是重用SSL会话参数,以避免并行和后续连接的SSL握手。会话存储在工作人员共享的SSL会话高速缓存中,并由ssl_session_cache 指令配置 。一兆字节的缓存包含约4000个会话。默认缓存超时时间为5分钟,它可以通过使用 ssl_session_timeout 指令来增加。以下是针对具有10兆字节共享会话缓存的多核系统优化的示例配置:
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
生成的文件应该在 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已尝试使用使用捆绑包的第一个证书的私钥而不是服务器证书。
浏览器通常存储他们收到的和那些由受信任的机构签名的中间证书,所以积极使用的浏览器可能已经具有所需的中间证书,并且可能不会抱怨没有链接捆绑包发送的证书。为了确保服务器发送完整的证书链,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
...
在该示例中,服务器证书#0 的主体(“ s ”) www.GoDaddy.com由发行人(“ i ”)签名,发行人本身是证书#1的主体,由发行人本身是主体证书#2,由知名发行人ValiCert,Inc.签署, 其证书存储在浏览器的内置证书库(位于Jack建造的房屋中)。
如果未添加证书包,则仅显示服务器证书#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,如上所示。只能使用 ssl 指令为整个服务器启用 SSL,从而无法设置单个HTTP / HTTPS服务器。添加 listen 指令的ssl参数来解决这个问题。因此,在现代版本中使用 ssl 指令是不鼓励的。
基于名称的HTTPS服务器
配置两个或多个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;
...
}
使用此配置,浏览器接收默认服务器的证书,即www.example.com不管所请求的服务器名称如何。这是由SSL协议行为引起的。在浏览器发送HTTP请求之前建立SSL连接,并且nginx不知道请求的服务器的名称。因此,它只能提供默认服务器的证书。
解决问题的最古老和最强大的方法是为每个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;
...
}
具有多个名称的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级别的私钥文件放在所有服务器中继承其单个内存副本:
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服务器名称指示扩展(SNI,RFC 6066),允许浏览器在SSL握手期间传递所请求的服务器名称,因此服务器将知道哪个应该用于连接的证书。 大多数现代浏览器目前都 支持 SNI ,尽管可能不会被某些旧的或特殊的客户端使用。
只有域名可以在SNI中传递,但是如果请求包含文字IP地址,某些浏览器可能会错误地将服务器的IP地址作为其名称传递。不应该依赖这个。
为了在nginx中使用SNI,必须在已经构建了nginx二进制文件的OpenSSL库以及在运行时被动态链接的库中支持它。如果使用配置选项“–enable-tlsext”构建,则OpenSSL支持SNI,因为0.9.8f版本 。 由于OpenSSL 0.9.8j此选项默认启用。如果nginx是用SNI支持构建的,那么当使用“-V”开关运行时,nginx会显示这个:
$ 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
兼容性
- 自从0.8.21和0.7.62,SNI支持状态由“-V”开关显示。
- 从0.7.14开始,支持 listen 指令的ssl参数 。在0.8.21之前,只能与default参数一起指定 。
- 自0.5.23以来,SNI得到了支持。
- 从0.5.6起,共享的SSL会话缓存已被支持。
- 版本1.9.1及更高版本:默认SSL协议为TLSv1,TLSv1.1和TLSv1.2(如果OpenSSL库支持)。
- 版本0.7.65,0.8.19及更高版本:默认SSL协议是SSLv3,TLSv1,TLSv1.1和TLSv1.2(如果OpenSSL库支持)。
- 版本0.7.64,0.8.18及更早版本:默认SSL协议为SSLv2,SSLv3和TLSv1。
- 版本1.0.5及更高版本:默认SSL密码为“ HIGH:!aNULL:!MD5”。
- 版本0.7.65,0.8.20及更高版本:默认SSL密码为“ HIGH:!ADH:!MD5”。
- 版本0.8.19:默认SSL密码为“ ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM”。
- 版本0.7.64,0.8.18及更早版本:默认SSL密码为 “ ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP”。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/99674.html