Winse Blog

走走停停, 熙熙攘攘, 忙忙碌碌, 不知何畏.

Nginx配置https

很早前弄过https,当时只是玩玩实际工作中并没有用到。现在业务需要得配置https。欠的债总是要还的,使用puppet的时刻默认全部信任不走证书认证。这里为了安装tomcat的https还是绕不过去。硬着头皮整吧。

编译

1
2
3
4
5
6
7
8
[... nginx-1.10.2]$ tar zxvf zlib-1.2.8.tar.gz 
[... nginx-1.10.2]$ tar zxvf pcre-8.36.tar.gz 

[... nginx-1.10.2]$ mv zlib-1.2.8 src/zlib
[... nginx-1.10.2]$ mv pcre-8.36 src/pcre

[... nginx-1.10.2]$ ./configure --prefix=/home/hadoop/nginx --with-http_ssl_module --with-pcre=src/pcre --with-zlib=src/zlib
[... nginx-1.10.2]$ make && make install

生成证书

先整一个能访问的https,再通过本地CA来进行授权(本地浏览器安装这个CA),最后处理chrome sha-1的问题。

  • 自己签发(无CA)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# RSA密钥
[hadoop@cu1 conf]$ openssl genrsa -des3 -out server.key 1024
Generating RSA private key, 1024 bit long modulus
...........++++++
................++++++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
# 拷贝一个不需要输入密码的密钥文件
[hadoop@cu1 conf]$ cp server.key server.key.org
[hadoop@cu1 conf]$ openssl rsa -in server.key.org -out server.key
Enter pass phrase for server.key.org:
writing RSA key

# 需要提交给 SSL 认证机构的(也叫作:生成一个证书请求)
[hadoop@cu1 conf]$ openssl req -new -key server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GD
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:Eshore
Organizational Unit Name (eg, section) []:CU
Common Name (eg, your name or your server's hostname) []:cu.eshore.cn
Email Address []:ca@eshore.cn

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

# 认证机构颁发(自己签发证书)
[hadoop@cu1 conf]$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=CN/ST=Guangdong/L=Guangzhou/O=Eshore/OU=CU/CN=cu1
Getting Private key
  • 本地CA授权 & SHA2(推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
[root@cu1 apache-tomcat-8.0.38]# ll /etc/pki/CA
total 16
drwxr-xr-x. 2 root root 4096 Mar  1  2016 certs 存放CA签署(颁发)过的数字证书(证书备份目录)
drwxr-xr-x. 2 root root 4096 Mar  1  2016 crl 吊销的证书
drwxr-xr-x. 2 root root 4096 Mar  1  2016 newcerts
drwx------. 2 root root 4096 Mar  1  2016 private 用于存放CA的私钥
[root@cu1 apache-tomcat-8.0.38]# ll /etc/pki/tls/
total 24
lrwxrwxrwx  1 root root    19 May 22  2015 cert.pem -> certs/ca-bundle.crt
drwxr-xr-x. 2 root root  4096 Mar 22  2016 certs
drwxr-xr-x. 2 root root  4096 Mar 22  2016 misc
-rw-r--r--  1 root root 10906 Feb 24  2016 openssl.cnf openssl的CA主配置文件
drwxr-xr-x. 2 root root  4096 Mar  1  2016 private 证书密钥存放目录

# 修改配置(一部分为默认值,一部分与sha2有关)
[root@cu1 pki]# pwd
/etc/pki
[root@cu1 pki]# vi tls/openssl.cnf 
修改一些参数,后面的是修改后的
[root@cu1 pki]# diff /home/hadoop/openssl.cnf tls/openssl.cnf 
50c50
< certificate   = $dir/cacert.pem       # The CA certificate
---
> certificate   = $dir/ca.crt   # The CA certificate
55c55
< private_key   = $dir/private/cakey.pem# The private key
---
> private_key   = $dir/private/ca.key # The private key
74c74
< default_crl_days= 30                  # how long before next CRL
---
> default_crl_days= 365                 # how long before next CRL
86,87c86,87
< stateOrProvinceName   = match
< organizationName      = match
---
> stateOrProvinceName   = optional
> organizationName      = optional
107c107
< default_md            = sha1
---
> default_md            = sha256
126c126
< # req_extensions = v3_req # The extensions to add to a certificate request
---
> req_extensions = v3_req # The extensions to add to a certificate request
130c130
< countryName_default           = XX
---
> countryName_default           = CN
135c135
< #stateOrProvinceName_default  = Default Province
---
> #stateOrProvinceName_default  = GD

# CA证书
清理原来的旧文件
[root@cu1 pki]# cd CA
[root@cu1 CA]# rm -rf index.txt* serial*
[root@cu1 CA]# rm cacert.pem private/cakey.pem 
初始化
[root@cu1 CA]# touch index.txt serial
[root@cu1 CA]# echo 01 > serial 

[root@cu1 CA]# openssl genrsa -out private/ca.key 2048
Generating RSA private key, 2048 bit long modulus
.........................................................................+++
...........................+++
e is 65537 (0x10001)

[root@cu1 CA]# chmod 600 private/ca.key 

[root@cu1 CA]# openssl req -new -x509 -key private/ca.key -out ca.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:CN
State or Province Name (full name) []:GD
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:Eshore
Organizational Unit Name (eg, section) []:CU   
Common Name (eg, your name or your server's hostname) []:eshore.cn
Email Address []:ca@eshore.cn

# 应用端证书的新建
[root@cu1 conf]# openssl genrsa -out nginx.key 2048
Generating RSA private key, 2048 bit long modulus
...................................................................+++
.....+++
e is 65537 (0x10001)
[root@cu1 conf]# 

[root@cu1 conf]# openssl req -new -key nginx.key -out nginx.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:CN
State or Province Name (full name) []:GD
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:Eshore
Organizational Unit Name (eg, section) []:Cu
Common Name (eg, your name or your server's hostname) []:cu.eshore.cn
Email Address []:cu@eshore.cn

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

查看是否为sha-2
[root@cu1 conf]# openssl req -in nginx.csr -text | grep sha256

# 应用端证书颁发 方式二选一
* 默认的方式,但不是sha-2。把生成的证书请求csr文件发到CA服务器上,在CA上执行:
签发过程 其实默认使用了 配置文件中指定的ca.crt和ca.key这两个文件.
[root@cu1 conf]# openssl ca -in nginx.csr -out nginx.crt
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Jan 19 07:24:24 2017 GMT
            Not After : Jan 19 07:24:24 2018 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = GD
            organizationName          = Eshore
            organizationalUnitName    = Cu
            commonName                = cu.eshore.cn
            emailAddress              = cu@eshore.cn
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                7B:3D:E8:18:D9:77:20:8F:A2:76:7F:6C:F2:01:65:49:3F:92:1A:7F
            X509v3 Authority Key Identifier: 
                keyid:5F:8C:1E:3D:F7:A1:86:82:22:F5:88:12:36:16:82:49:B6:9C:84:F1

Certificate is to be certified until Jan 19 07:24:24 2018 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
[root@cu1 conf]# 

* sha-2签名算法
http://www.ibm.com/support/knowledgecenter/zh/SSPMR3_9.0.0/com.ibm.tivoli.tem.doc_9.0/SUA_9.0/com.ibm.license.mgmt.doc/security/t_generate_certificate_CA.html
[root@cu1 conf]# openssl x509 -req -days 365 -in nginx.csr -CA /etc/pki/CA/ca.crt -CAkey /etc/pki/CA/private/ca.key -CAserial /etc/pki/CA/serial -sha256 -out nginx.crt 
Signature ok
subject=/C=CN/ST=GD/L=GZ/O=Eshore/OU=Cu/CN=cu.eshore.cn/emailAddress=cu@eshore.cn
Getting CA Private Key

生成key和csr请求可以一条命令搞定( 这是后期增加的,和本文的一些配置有出处 ):

1
2
3
https://www.digicert.com/easy-csr/openssl.htm

openssl req -new -newkey rsa:2048 -nodes -out star_winse_com.csr -keyout star_winse_com.key -subj "/C=CN/ST=GD/L=GZ/O=winse/CN=*.winse.com"

nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
server {
    listen       14443 ssl;
    server_name  cu.eshore.cn;

    ssl on;
    ssl_certificate      nginx.crt;
    ssl_certificate_key  nginx.key;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

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

    location / {
        root   html;
        index  index.html index.htm;
    }

    location /omc {
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        Host $http_host;

        proxy_pass http://localhost:9000;
    }

}

MAKR

同时,为了统一,你可以把这三个文件都移动到 /etc/ssl/private/ 目录。 然后可以修改 Nginx 配置文件 server {
listen 80; listen [::]:80 ssl ipv6only=on;
listen 443 ssl; listen [::]:443 ssl ipv6only=on; server_name example.com; ssl on; ssl_certificate /etc/ssl/private/example_com.crt; ssl_certificate_key /etc/ssl/private/example_com.key; }

server_names barretlee.com *.barretlee.com ssl on; ssl_certificate /etc/nginx/ssl/barretlee.com.crt; ssl_certificate_key /etc/nginx/ssl/barretlee.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers “EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !MEDIUM”;

Add perfect forward secrecy

ssl_prefer_server_ciphers on; add_header Strict-Transport-Security “max-age=31536000; includeSubdomains”;

同时,如果是全站 HTTPS 并且不考虑 HTTP 的话,可以加入 HSTS 告诉你的浏览器本 网站全站加密,并且强制用 HTTPS 访问 add_header Strict-Transport-Security max-age=63072000; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; 同时也可以单独开一个 Nginx 配置,把 HTTP 的访问请求都用 301 跳转到 HTTPS

浏览器访问HTTP的请求重定向到HTTPS If they come here using HTTP, bounce them to the correct scheme error_page 497 https://$host:$server_port$request_uri;

curl访问:正常访问HTTPS需要把CA证书内容加入到ca-bundle.crt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@hadoop-master2 nginx]# curl https://www.winse.com
curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
 
[root@hadoop-master2 CA]# cp /etc/pki/tls/certs/ca-bundle.crt{,.bak}
[root@hadoop-master2 CA]# cat /etc/pki/CA/ca.crt >> /etc/pki/tls/certs/ca-bundle.crt
[root@hadoop-master2 CA]# 
[root@hadoop-master2 CA]# curl https://www.winse.com
curl: (51) SSL: certificate subject name 'winse.com' does not match target host name 'www.winse.com'
[root@hadoop-master2 CA]# curl https://winse.com
...

tomcat配置https

直接使用nginx的key和crt,需要安装APR.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@cu1 apache-tomcat-8.0.38]# yum install tomcat-native
[root@cu1 apache-tomcat-8.0.38]# less conf/server.xml 
<Connector
           protocol="org.apache.coyote.http11.Http11AprProtocol"
           port="9443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           SSLCertificateFile="/home/cu/tools/apache-tomcat-8.0.38/conf/nginx.crt"
           SSLCertificateKeyFile="/home/cu/tools/apache-tomcat-8.0.38/conf/nginx.key"
           SSLVerifyClient="optional" SSLProtocol="TLSv1+TLSv1.1+TLSv1.2"/>
           
#另一种keystore
<Connector
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           port="8443" maxThreads="200" SSLEnabled="true"
           scheme="https" secure="true" 
           keystoreFile="/root/.keystore" keystorePass="changeit"
           clientAuth="false" sslProtocol="TLS" />
           

本地CURL访问

把/etc/pki/CA目录下的ca.crt拷贝本地,安装到受信任的根证书颁发机构目录下面。然后https访问即可。

参考

–END

Comments