nginx https ssl 传输 双向加密(已使用)

实现 nginx https ssl 传输 双向加密(已使用)

理论过程参考博客 http://blog.chinaunix.net/uid-26335251-id-3508651.html
单向认证只是客户端认证服务端, 双向认证就是相互都要认证(双向认证这种,在浏览器一般都体现为需要证书)

在使用openssl自己生成证书的时候,会发现网上很多例子生成的证书格式都不同,同一篇文章里也会有很多种格式.
所以就需要了解下 不同格式有什么区别和联系
参考博客http://blog.csdn.net/justinjing0612/article/details/7770301
参考博客http://www.cnblogs.com/lzjsky/archive/2010/11/14/1877143.html

der,cer文件一般是二进制格式的,只放证书,不含私钥
crt文件可能是二进制的,也可能是文本格式的,应该以文本格式居多,功能同der/cer
pem文件一般是文本格式的,可以放证书或者私钥,或者两者都有
pem如果只含私钥的话,一般用.key扩展名,而且可以有密码保护
pfx,p12文件是二进制格式,同时含私钥和证书,通常有保护密码

nginx 安装

#安装epel 源
yum install epel-release
#安装nginx
yum install nginx

配置https 单向加密

1.创建服务器证书密钥文件 server.key:

openssl genrsa -des3 -out server.key 1024
输入密码,确认密码,自己随便定义,但是要记住,后面会用到。

2.创建服务器证书的申请文件 server.csr

openssl req -new -key server.key -out server.csr
输出内容为:
Enter pass phrase for root.key: ← 输入前面创建的密码
Country Name (2 letter code) [AU]:CN ← 国家代号,中国输入CN
State or Province Name (full name) [Some-State]:BeiJing ← 省的全名,拼音
Locality Name (eg, city) []:BeiJing ← 市的全名,拼音
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany Corp. ← 公司英文名
Organizational Unit Name (eg, section) []: ← 可以不输入
Common Name (eg, YOUR name) []: ← 此时不输入
Email Address []:admin@mycompany.com ← 电子邮箱,可随意填
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []: ← 可以不输入
An optional company name []: ← 可以不输入

4.备份一份服务器密钥文件

cp server.key server.key.org

5.去除文件口令

openssl rsa -in server.key.org -out server.key

6.生成证书文件server.crt

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

如果想把http的请求强制转到https的话:
server {
listen 80;
server_name example.me;
rewrite ^ https:// s e r v e r n a m e server_name servernamerequest_uri? permanent;
#//使用return的效率会更高
#//return 301 https:// s e r v e r n a m e server_name servernamerequest_uri;
}

添加如下内容:

server {
listen 443 ssl; #默认的web访问端口
ssl on;
ssl_certificate /ssl/server.crt;
ssl_certificate_key /ssl/server.key;
server_name gateway.com; #服务器名
access_log ./nginx.access.log; #服务器接收的请求日志,logs目录若不存在需要创建,否则nginx报错
error_log ./nginx.error.log; #错误日志

    location  / {
        include        uwsgi_params;     #这里是导入的uwsgi配置
        uwsgi_pass     127.0.0.1:8888;   #需要和uwsgi的配置文件里socket项的地址
                                         #需要和uwsgi的配置文件里socket项的地址
        uwsgi_param UWSGI_CHDIR  /var/lib/jenkins/workspace/iotplatform;     #项目根目录
        uwsgi_param UWSGI_SCRIPT flasky:app;     #启动项目的主程序(在本地上运行
        #root /usr/share/nginx/html;
    }
   location /web/ {
        root   /usr/share/nginx/html;
        index  index.html;
    }
   location /project-s/ {
        root   /usr/share/nginx/html;
        index  index.html;
    }

}

其他参考
  1. ssl_session_cache shared:SSL:10m; : 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,和off差不多,停用缓存。如shared:SSL:10m表示我所有的nginx工作进程共享ssl会话缓存,官网介绍说1M可以存放约4000个sessions。 详细参考serverfault上的问答ssl_session_cache。
  2. ssl_session_timeout : 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
  3. 设置较长的keepalive_timeout也可以减少请求ssl会话协商的开销,但同时得考虑线程的并发数了。

配置https 双向加密

对于 NGINX 的 HTTPS 配置,通常情况下我们只需要实现服务端认证就行,因为浏览器内置了一些受信任的证书颁发机构(CA),服务器端只需要拿到这些机构颁发的证书并配置好,浏览器会自己校验证书的可用性并通过 SSL 进行通讯加密。

但特殊情况下我们也需要对客户端进行验证,只有受信任的客户端才能使用服务接口,此时我们就需要启用双向认证来达到这个目的,只有 当客户端请求带了可用的证书才能调通服务端接口 。

3.使用openssl生成证书

创建一个文件夹存放生成的证书

复制代码
1)创建根证私钥

openssl genrsa -out root-key.key 2048

2)创建根证书请求文件

openssl req -new -out root-req.csr -key root-key.key

具体如下

[root@localhost sslKey]# openssl req -new -out root-req.csr -key root-key.key

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) []:bj

Locality Name (eg, city) [Default City]:bj

Organization Name (eg, company) [Default Company Ltd]:dc

Organizational Unit Name (eg, section) []:dc

Common Name (eg, your name or your server’s hostname) []:root

Email Address []:

Please enter the following ‘extra’ attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:
复制代码

在2)的时候,会让填写信息,其中国家,省市,公司等需要和后面的证书保持一致.后面challenge password的地方直接回车就好

复制代码
3)自签根证书

openssl x509 -req -in root-req.csr -out root-cert.cer -signkey root-key.key -CAcreateserial -days 3650

4)生成p12格式根证书,密码填写123456

openssl pkcs12 -export -clcerts -in root-cert.cer -inkey root-key.key -out root.p12

5)生成服务端key

openssl genrsa -out server-key.key 2048

6)生成服务端请求文件

openssl req -new -out server-req.csr -key server-key.key

具体如下

[root@localhost sslKey]# openssl req -new -out server-req.csr -key server-key.key

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) []:bj

Locality Name (eg, city) [Default City]:bj

Organization Name (eg, company) [Default Company Ltd]:dc

Organizational Unit Name (eg, section) []:dc

Common Name (eg, your name or your server’s hostname) []?.ttt.com

Email Address []:

Please enter the following ‘extra’ attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:
复制代码

在6)的时候,国家省市公司和2)保持一致, Common Name 要特别注意, 要用你服务器的域名,我们测试用ttt.com

复制代码
7)生成服务端证书(root证书,rootkey,服务端key,服务端请求文件这4个生成服务端证书)

openssl x509 -req -in server-req.csr -out server-cert.cer -signkey server-key.key -CA root-cert.cer -CAkey root-key.key -CAcreateserial -days 3650

8)生成客户端key

openssl genrsa -out client-key.key 2048

9)生成客户端请求文件

openssl req -new -out client-req.csr -key client-key.key

具体如下

[root@localhost sslKey]# openssl req -new -out client-req.csr -key client-key.key

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) []:bj

Locality Name (eg, city) [Default City]:bj

Organization Name (eg, company) [Default Company Ltd]:dc

Organizational Unit Name (eg, section) []:dc

Common Name (eg, your name or your server’s hostname) []:client common

Email Address []:

Please enter the following ‘extra’ attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:

10)生成客户端证书(root证书,rootkey,客户端key,客户端请求文件这4个生成客户端证书)

openssl x509 -req -in client-req.csr -out client-cert.cer -signkey client-key.key -CA root-cert.cer -CAkey root-key.key -CAcreateserial -days 3650

11)生成客户端p12格式根证书(密码设置123456)

openssl pkcs12 -export -clcerts -in client-cert.cer -inkey client-key.key -out client.p12
复制代码

4.nginx配置(服务器端)

第3步证书生成完毕,就可以使用这些证书了,首先在服务端进行配置,nginx的安装就不多说了,参考http://blog.csdn.net/qq315737546/article/details/51834866

注意下 ./configure 的时候,要增加ssl支持,需要换成 ./configure–with-http_ssl_module

下面贴出nginx的简易版配置文件

复制代码
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

server {
    listen       443 ssl;
    server_name  ttt.com;
    ssl                  on;  
    ssl_certificate      /data/sslKey/server-cert.cer;  #server证书公钥
    ssl_certificate_key  /data/sslKey/server-key.key;  #server私钥
    ssl_client_certificate /data/sslKey/root-cert.cer;  #根级证书公钥,用于验证各个二级client
    ssl_verify_client on;  #开启客户端证书验证  

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

}
复制代码

启动nginx,然后在我们浏览器访问测试下.

5.浏览器访问(客户端)

(先在C:\Windows\System32\drivers\etc\hosts 里面做好 域名和ip的映射192.168.234.132 www.ttt.com)

点击继续浏览此网站,则如下图

出现400错误,是因为我们没有带客户端证书的原因, 将client.p12 导入浏览器,则如下图

可以访问,但是证书会有红色x号.因为是我们自己签的.浏览器不信任

这时候我们将我们的root.p12也导入,证书存储不用默认的个人,选择 受信任的根证书颁发机构, 如果再访问如下图(可能要重启浏览器)

6.java代码访问(客户端)

根据我们在第1点里面的了解,双向认证是需要互相认证证书的. 所以客户端需要认证服务器证书,也要把客户端证书发送给服务器. 用浏览器做客户端的时候,认证服务器证书自动进行,提交客户端证书也是自动进行(需要导入证书到浏览器)

当我们用java代码来做的时候, 也是需要这些步骤.

1)首先是认证服务器证书, jdk有默认的信任证书列表$JRE/lib/security/cacerts

也会默认信任 $JRE/lib/security/jssecacerts 里的证书.

如果你把证书放到别的地方,则需要在代码中指定

(理论上如果是买的根机构签发的证书,是不需要导入到java自己的库里,但是java的和操作系统的信任库可能不一样,我们买的在浏览器就OK,在java中就必须手动导入服务端证书到信任列表中)

用keytool导入的时候注意下 keystore的路径. cacerts的默认密码是changeit

复制代码
D:>cd jdk1.7.0_80\jre7\lib\security
D:\jdk1.7.0_80\jre7\lib\security>keytool -import -alias ttt -keystore cacerts -file e:/HttpsDemo/server-cert.cer
输入密钥库口令:
所有者: CN=*.ttt.com, OU=dc, O=dc, L=bj, ST=bj, C=cn
发布者: CN=root, OU=dc, O=dc, L=bj, ST=bj, C=cn
序列号: a034f5e5d4b1c825
有效期开始日期: Thu Oct 20 00:01:52 CST 2016, 截止日期: Sun Oct 18 00:01:52 CST 2026
证书指纹:
MD5: 65:CB:C9:0D:C4:E7:66:F9:09:3D:B4:17:E6:6B:E5:AB
SHA1: 41:AD:9E:EB:61:88:AE:1B:A3:76:CE:F8:2C:BB:5D:74:C8:0D:2D:0D
SHA256: 0D:17:D4:EF:2E:9D:89:EA:3A:1F:32:44:D5:12:DF:E0:EE:58:61:04:1A:28:BC:91:D4:7C:3F:AF:FE:99:79:16
签名算法名称: SHA1withRSA
版本: 1
是否信任此证书? [否]: y
证书已添加到密钥库中
D:\jdk1.7.0_80\jre7\lib\security>
复制代码

  1. java代码(包含加载客户端证书)

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

public class HttpsDemo {
private final static String PFX_PATH = “e:/HttpsDemo/client.p12”; //客户端证书路径
private final static String PFX_PWD = “123456”; //客户端证书密码

public static String sslRequestGet(String url) throws Exception {
KeyStore keyStore = KeyStore.getInstance(“PKCS12”);
InputStream instream = new FileInputStream(new File(PFX_PATH));
try {
keyStore.load(instream, PFX_PWD.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, PFX_PWD.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext
, new String[] { “TLSv1” } // supportedProtocols ,这里可以按需要设置
, null // supportedCipherSuites
, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    try {
        HttpGet httpget = new HttpGet(url); 

// httpost.addHeader(“Connection”, “keep-alive”);// 设置一些heander等
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(), “UTF-8”);//返回结果
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}

public static void main(String[] args) throws Exception {
    System.out.println(System.getProperty("java.home"));
    System.out.println(sslRequestGet("https://www.ttt.com/"));
}

}
复制代码

我这里使用了 httpClient的包,具体如下

  1. 编译运行2)里面的java文件

复制代码
E:\HttpsDemo>javac -encoding utf-8 -cp commons-logging-1.1.1.jar;httpclient-4.5.jar;httpcore-4.4.1.jar; HttpsDemo.java
E:\HttpsDemo>java -cp commons-logging-1.1.1.jar;httpclient-4.5.jar;httpcore-4.4.1.jar; HttpsDemo
D:\jdk1.7.0_80\jre7

Welcome to nginx!

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

E:\HttpsDemo> 复制代码 可以看到能正常访问了. 大功告成.(代码中增加了jre的输出,因为eclipse和cmd可能用的不是同一个,证书只导入了其中一个jre里,另一个运行不正常)

7.使用购买的证书(信任机构签发的)

如果是公司使用的话,证书一般是从信任机构那里买的.所以就不需要上面测试的root证书.

信任机构提供 服务端证书和私钥,客户端证书 就可以了.

如果报错

Exception in thread “main” javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

则检查下 客户端证书是否加载正确,服务端证书是否导入本地信任库.运行的jre和证书导入的那个jre是否一致.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值