在自己颁发证书的测试环境下,不同域名下(相同的二级域名)的服务之间调用https服务,需要给每一台机器的jdk都安装指定域名的证书才可以发起请求,否则jdk拒绝发送请求,因为自己颁发的证书是不在jdk的信任列表里的。但是我们不能给A【a.test.com】和B【b.test.com】分别生成对应全域名的证书再分别安装到对方的jdk中,因为如果还有C,D..等等多个服务的话,我们就需要生成a.test.com,b.test.com,c.test.com, d.test.com 等等的域名,再分别把这些证书装到所有服务器的jdk中,那工作量可就大了。因此,我们生成一个泛域名证书,所有服务都使用这一个证书,相互之间依旧可以沟通。
为了完成服务的https功能,需要两个文件:证书【.crt】文件和对应的KeyStore【.keystore】文件。
A. crt安装到每一台机器的jdk上,从而使得jdk信任该域名。
B. keystore文件引用到每一台机器中,开启服务器的https端口。
做完上面的两点后,服务A,B,C...等等的服务都在一个二级域名下就可以通信(当然了,因为是我们自己的服务,所以都是相同的二级域名)。
步骤综述就是:
1. 生成CA的群文件【key,csr,crt】
2. 再利用CA的群文件给应用服务器生成群文件【key,csr,crt】
3. 利用上述的一些文件生成tomcat和resin能识别的keystore文件,
4. 开启服务器的https服务:给所有服务器安装keystore文件
5. 添加证书到信任列表:将证书添加到jdk信任列表
6. nginx配置:最后,别忘了给nginx指定证书,它与tomcat、resin不同,需要的 【.crt】 和【 .key】 这两个文件。
实现
1 生成CA證書
1.1 生成 CA 私钥
- openssl genrsa -out ca.key 1024
1.2 生成csr
- openssl req -new -key ca.key -out ca.csr
linux的反馈示例:
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) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:My CA
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:test
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
1.3 生成crt
- openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
2. 为服务器端和客户端【這裏服務器端和客戶端都當作同一個服務器,正如介紹中講的】准备公钥、私钥
2.1 生成服务器端私钥
- openssl genrsa -out server.key 1024
2.2 生成服务器端公钥【这一步的文件在后面没有直接用到,先记录下来】
- openssl rsa -in server.key -pubout -out server.pem
3.生成服务器端证书和客户端证书【這裏服務器端和客戶端都當作同一個服務器,正如介紹中講的】
3.1 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件
- openssl req -new -key server.key -out server.csr
linux反馈示例:
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) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:My Server
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:*.test.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
3.2 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书
- openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
4. 接下來就是讓所有的服務支持https,因爲所有的服務都用的nginx生成的那個crt,所以我們把這個crt配置到每一個server【tomcat 、resin】中:
4.1 tomcat 、resin里面需要安装的是keystore文件,所以我们需要先生成这个文件。实现步骤:
I. 首先利用crt和key以及ca的crt生成p12 文件:
- openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name tomcat -CAfile ca.crt -caname root -chain
Enter Export Password:
Verifying - Enter Export Password:
[root@nginx-104-230 ssl]# ll
total 36
II. 接下来生成它们需要的keystore:
- keytool -importkeystore -v -srckeystore server.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore server.keystore -deststoretype jks -deststorepass 123456
Importing keystore server.p12 to server.keystore...
Entry for alias tomcat successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
[Storing server.keystore]
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore server.keystore -destkeystore server.keystore -deststoretype pkcs12".
4.2 将keystore引用到服务器里面:
tomcat:
<Connector
SSLEnabled="true" clientAuth="false" keystoreFile="/data/server.keystore"
keystorePass="123456" maxThreads="200" port="443"
protocol="org.apache.coyote.http11.Http11Protocol"
scheme="https" secure="true" sslProtocol="TLS"
/>
resin:
jsse_keystore_type : jks
jsse_keystore_file : /data/server.keystore
jsse_keystore_password : 123456
5. 还需要给jdk添加信任证书
将server.crt导入到集群中各个服务的jdk中:
- keytool -importcert -trustcacerts -alias server -file /data/server.crt -keystore cacerts -storepass changeit
6. 给nginx引用key和crt
server {
listen 443;
server_name email.test.com;
index index.html index.htm;
ssl on;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
ssl_session_timeout 5m;
#ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
proxy_next_upstream http_502 http_504 http_503 http_404 error timeout invalid_header;
proxy_pass https://tdts_email;
}
location ~ .*\.(php|jsp|cgi|do|action|shtml)?$ {
proxy_next_upstream http_502 http_504 http_503 http_404 error timeout invalid_header;
proxy_pass https://tdts_email;
}
access_log /data/logs/nginx_www/access.log main;
error_log /data/logs/nginx_www/error.log debug;
}
7. 完成
至此就可以在浏览器上访问集群中的某一个服务了,并且与此同时,各个子服务之间也可以直接java通信。
感谢
在研究的时候参考了很多文章,以下文章给予了很大的帮助,谢谢这些大神: