现在网络安全越来越高,需要使用https访问,下面我就介绍在redhat7.x上安装比较新的nginx 1.15版,并配置ssl证书。
本次采用的安全证书是天威诚信的SSL证书。天威诚信是由中华人民共和国工业和信息化部(原信息产业部)授权设立的电子认证服务机构,首批全国性商业PKI/CA企业。可以申请。

一、生成证书请求

您需要使用CSR生成工具来创建证书请求。
1.下载AutoCSR:
http://www.itrus.cn/soft/autocsr.rar

  1. 生成服务器证书私钥及证书请求
    运行AutoCSR.bat文件,按照操作提示填写证书注册信息。
    以下是示例信息:
    通用名(域名): test.itrus.com.cn
    组织名称: iTrus China Co.,Ltd.
    部门名称: VTN Support
    省市名称: Beijing
    市或区名: Beijing

    3.备份私钥并提交证书请求
    在程序目录下,将生成Cert目录。请妥善保存该目录下证书私钥文件server.key,并将证书请求文件certreq.csr提交给天威诚信。

二、安装服务器证书

1.获取服务器证书文件
将证书签发邮件中的包含服务器证书代码的文本复制出来(包括“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”)粘贴到记事本等文本编辑器中。
为保障服务器证书在客户端的兼容性,服务器证书需要安装两张中级CA证书(不同品牌证书,可能只有一张中级证书)。
在服务器证书代码文本结尾,回车换行不留空行,并分别粘贴两张中级CA证书代码(包括“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”,每串证书代码之间均需要使用回车换行不留空行),修改文件扩展名,保存包含三段证书代码的文本文件为server.pem文件(如果只有一张中级证书,则只需要粘贴一张中级证书代码与服务器证书代码即可,并回车换行)。

三、安装nginx
下载地址:http://nginx.org/en/download.html
下载:nginx-1.15.12.tar.gz
上传到/opt,解压

tar -zxvf nginx-1.15.12.tar.gz

安装:

cd nginx-1.15.12
./configure  --with-http_stub_status_module --with-http_ssl_module
make && make install

注意,一定要加上--with-http_ssl_module 不然,后面可能后报如下的错:

nginx: [emerg] unknown directive "ssl" in /usr/local/nginx/conf/nginx.conf:1

2.安装服务器证书
复制server.key、server.pem文件到Nginx安装目录下的conf目录。
打开Nginx安装目录下conf目录中的nginx.conf文件
找到

    #HTTPS server     
    #server { 
    #listen       443; 
    #server_name  localhost; 
    #    ssl                  on; 
    #    ssl_certificate      cert.pem; 
    #    ssl_certificate_key  cert.key; 
    #    ssl_session_timeout  5m; 
    #    ssl_protocols  SSLv2 SSLv3 TLSv1; 
    #    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    #    ssl_prefer_server_ciphers   on; 
    #    location / { 
    #        root   html; 
    #        index  index.html index.htm; 
    #    } 
    #} 

将其修改为
server { 
    listen       443; 
    server_name  localhost; 
    ssl                  on; 
    ssl_certificate      server.pem; 
    ssl_certificate_key  server.key; 
    ssl_session_timeout  5m; 
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;    

#启用TLS1.1、TLS1.2要求OpenSSL1.0.1及以上版本,若您的OpenSSL版本低于要求,请使用 ssl_protocols TLSv1;
ssl_ciphers HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}

```

保存退出,并重启Nginx。
通过https方式访问您的站点,测试站点证书的安装配置。
重启后报如下的错:

nginx: [warn] the "ssl" directive is deprecated, use the "listen ... ssl" directive instead in /usr/local/nginx/conf/nginx.conf:101

经应该是说 nginx 1.15 及以后的版本,不需要再写 ssl on了 ,
改为如下:

 listen       443 ssl  ;
 listen       [::]:443 ssl ;

常见问题:

1、 nginx日志文件中文乱码

可以参考博客https://www.jianshu.com/p/8f8c2b5ca2d1,
设置转义方式,这个方法我试过escape=none或者json都无效,应该是这个方法是针对nginx 1.11.8 以上版本

log_format postdata escape=json '$remote_addr | $request_body | $resp_body';

针对我这个版本的nginx,采用以下方法可以解决:
直接在 nginx.conf的记录日志的location部分里面配置下面这一行就好了:

    log_escape_non_ascii off;

2、谷歌浏览器报ERR_SSL_PROTOCOL_ERROR

改如下:

server {
        listen       443 default ssl;

3、配置文件SSL部分说明
配置HTTPS主机,必须在server配置块中打开SSL协议,还需要指定服务器端证书和密钥文件的位置:

server {
    listen              443;
    server_name         www.example.com;
    ssl                 on;
    ssl_certificate      server.pem;
    ssl_certificate_key  server.key;
    ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

服务器证书是公开的,会被传送到每一个连接到服务器的客户端。而私钥不是公开的,需要存放在访问受限的文件中,当然,nginx主进程必须有读取密钥的权限。私钥和证书可以存放在同一个文件中:

ssl_certificate      server.pem;
ssl_certificate_key  server.key;

这种情况下,证书文件同样得设置访问限制。当然,虽然证书和密钥存放在同一个文件,只有证书会发送给客户端,密钥不会发送。
ssl_protocols和ssl_ciphers指令可以用来强制用户连接只能引入SSL/TLS那些强壮的协议版本和强大的加密算法。从1.0.5版本开始,nginx默认使用ssl_protocols SSLv3 TLSv1ssl_ciphers HIGH:!aNULL:!MD5,所以只有在之前的版本,明确地配置它们才是有意义的。从1.1.13和1.0.12版本开始,nginx默认使用ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2
CBC模式的加密算法容易受到一些攻击,尤其是BEAST攻击(参见CVE-2011-3389)。可以通过下面配置调整为优先使用RC4-SHA加密算法:

ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

4、HTTPS服务器优化

SSL操作需要消耗CPU资源,所以在多处理器的系统,需要启动多个工作进程,而且数量需要不少于可用CPU的个数。最消耗CPU资源的SSL操作是SSL握手,有两种方法可以将每个客户端的握手操作数量降到最低:第一种是保持客户端长连接,在一个SSL连接发送多个请求,第二种是在并发的连接或者后续的连接中重用SSL会话参数,这样可以避免SSL握手的操作。会话缓存用于保存SSL会话,这些缓存在工作进程间共享,可以使用ssl_session_cache指令进行配置。1M缓存可以存放大约4000个会话。默认的缓存超时是5分钟,可以使用ssl_session_timeout加大它。下面是一个针对4核系统的配置优化的例子,使用10M的共享会话缓存:

worker_processes  4;
http {
    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;
    server {
        listen              443;
        server_name         www.example.com;
        keepalive_timeout   70;

        ssl                 on;
        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
        ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ...

5、SSL证书链

有些浏览器不接受那些众所周知的证书认证机构签署的证书,而另外一些浏览器却接受它们。这是由于证书签发使用了一些中间认证机构,这些中间机构被众所周知的证书认证机构授权代为签发证书,但是它们自己却不被广泛认知,所以有些客户端不予识别。针对这种情况,证书认证机构提供一个证书链的包裹,用来声明众所周知的认证机构和自己的关系,需要将这个证书链包裹与服务器证书合并成一个文件。在这个文件里,服务器证书需要出现在认证方证书链的前面:

$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt

这个文件需要使用ssl_certificate指令来引用:

server {
    listen              443;
    server_name         www.example.com;
    ssl                 on;
    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

6、合并HTTP/HTTPS主机

如果HTTP和HTTPS虚拟主机的功能是一致的,可以配置一个虚拟主机,既处理HTTP请求,又处理HTTPS请求。 配置的方法是删除ssl on的指令,并在*:443端口添加参数ssl:

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.8.21版本以前,只有添加了default参数的监听端口才能添加ssl参数:

listen  443  default ssl;

7、基于名字的HTTPS主机

如果在同一个IP上配置多个HTTPS主机,会出现一个很普遍的问题:

server {
    listen          443;
    server_name     www.example.com;
    ssl             on;
    ssl_certificate www.example.com.crt;
    ...
}

server {
    listen          443;
    server_name     www.example.org;
    ssl             on;
    ssl_certificate www.example.org.crt;
    ...
}

使用上面的配置,不论浏览器请求哪个主机,都只会收到默认主机www.example.com的证书。这是由SSL协议本身的行为引起的——先建立SSL连接,再发送HTTP请求,所以nginx建立SSL连接时不知道所请求主机的名字,因此,它只会返回默认主机的证书。

最古老的也是最稳定的解决方法就是每个HTTPS主机使用不同的IP地址:

server {
    listen          192.168.1.1:443;
    server_name     www.example.com;
    ssl             on;
    ssl_certificate www.example.com.crt;
    ...
}

server {
    listen          192.168.1.2:443;
    server_name     www.example.org;
    ssl             on;
    ssl_certificate www.example.org.crt;
    ...
}

8、带有多个主机名的SSL证书

也有其他一些方法可以实现多个HTTPS主机共享一个IP地址,但都有不足。其中一种方法是使用在“SubjectAltName”字段中存放多个名字的证书,比如www.example.comwww.example.org。但是,“SubjectAltName”字段的长度有限制。

另一种方式是使用主机名中含有通配符的证书,比如*.example.org。这个证书匹配www.example.org,但是不匹配example.orgwww.sub.example.org。这两种方法可以结合在一起——使用在“SubjectAltName”字段中存放的多个名字的证书,这些名字既可以是确切的名字,也可以是通配符,比如example.org*.example.org

最好将带有多个名字的证书和它的密钥文件配置在http配置块中,这样可以只保存一份内容拷贝,所有主机的配置都从中继承:

ssl_certificate      common.crt;
ssl_certificate_key  common.key;

server {
    listen          443;
    server_name     www.example.com;
    ssl             on;
    ...
}

server {
    listen          443;
    server_name     www.example.org;
    ssl             on;
    ...
}