openssl https证书
今天摸索了下 HTTPS 的证书生成,以及它在 Nginx 上的部署。由于博客托管在 github 上,没办法部署证书,先记录下,后续有需要方便快捷操作。本文的阐述不一定完善,但是可以让一个初学者了解大致的原理,同时跟着操作可以为自己的博客/网站部署一个 HTTPS 证书。
网站部署 HTTPS 的重要性
看看下面,部分电信用户访问京东首页的时候,会看到右下角有一个浮动广告:
小白用户以为是京东有意放置的,细心的用户会发现,这个 iframe 一层嵌一层的恶心广告很明显是电信/中间人通过 DNS 劫持注入进去的,十分恶心,没有关闭按钮。
随着互联网的快速发展,我们几乎离不开网络了,聊天、预订酒店、购物等等,我们的隐私无时无刻不暴露在这庞大的网络之中,HTTPS 能够让信息在网络中的传递更加安全,增加了 haker 的攻击成本。
HTTPS 区别于 HTTP,它多了加密(encryption),认证(verification),鉴定(identification)。它的安全源自非对称加密以及第三方的 CA 认证。
简述 HTTPS 的运作
如上图所示,简述如下:
客户端生成一个随机数 random-client
,传到服务器端(Say Hello)
服务器端生成一个随机数 random-server
,和着公钥,一起回馈给客户端(I got it)
客户端收到的东西原封不动,加上 premaster secret
(通过 random-client
、 random-server
经过一定算法生成的东西),再一次送给服务器端,这次传过去的东西会使用公钥加密
服务器端先使用私钥解密,拿到 premaster secret
,此时客户端和服务器端都拥有了三个要素: random-client
、 random-server
和 premaster secret
此时安全通道已经建立,以后的交流都会校检上面的三个要素通过算法算出的session key
CA 数字证书认证中心
如果网站只靠上图运作,可能会被中间人攻击,试想一下,在客户端和服务端中间有一个中间人,两者之间的传输对中间人来说是透明的,那么中间人完全可以获取两端之间的任何数据,然后将数据原封不动的转发给两端,由于中间人也拿到了三要素和公钥,它照样可以解密传输内容,并且还可以篡改内容。
为了确保我们的数据安全,我们还需要一个 CA
数字证书。HTTPS的传输采用的是非对称加密,一组非对称加密密钥包含公钥和私钥,通过公钥加密的内容只有私钥能够解密。上面我们看到,整个传输过程,服务器端是没有透露私钥的。而
CA 数字认证涉及到私钥,整个过程比较复杂,我也没有很深入的了解,后续有详细了解之后再补充下。
CA 认证分为三类:DV ( domain validation),OV ( organization validation),EV ( extended validation),证书申请难度从前往后递增,貌似 EV 这种不仅仅是有钱就可以申请的。
对于一般的小型网站尤其是博客,可以使用自签名证书来构建安全网络,所谓自签名证书,就是自己扮演 CA 机构,自己给自己的服务器颁发证书。
生成密钥、证书
第一步,为服务器端和客户端准备公钥、私钥
- # 生成服务器端私钥
- openssl genrsa -out server.key 1024
- # 生成服务器端公钥
- openssl rsa -in server.key -pubout -out server.pem
- # 生成客户端私钥
- openssl genrsa -out client.key 1024
- # 生成客户端公钥
- openssl rsa -in client.key -pubout -out client.pem
第二步,生成 CA 证书
- # 生成 CA 私钥
- openssl genrsa -out ca.key 1024
- # X.509 Certificate Signing Request (CSR) Management.
- openssl req -new -key ca.key -out ca.csr
- # X.509 Certificate Data Management.
- openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
在执行第二步时会出现:
- ➜ keys openssl req -new -key ca.key -out ca.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) [AU]:CN
- State or Province Name (full name) [Some-State]:Zhejiang
- Locality Name (eg, city) []:Hangzhou
- Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
- Organizational Unit Name (eg, section) []:
- Common Name (e.g. server FQDN or YOUR name) []:localhost
- Email Address []:
注意,这里的 Organization Name (eg, company) [Internet Widgits Pty Ltd]:
后面生成客户端和服务器端证书的时候也需要填写,不要写成一样的!!!可以随意写如:My CA, My Server, My Client。
然后 Common Name (e.g. server FQDN or YOUR name) []:
这一项,是最后可以访问的域名,我这里为了方便测试,写成 localhost
,如果是为了给我的网站生成证书,需要写成 barretlee.com
。
第三步,生成服务器端证书和客户端证书
- # 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件
- openssl req -new -key server.key -out server.csr
- # 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书
- openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
- # client 端
- openssl req -new -key client.key -out client.csr
- # client 端到 CA 签名
- openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt
此时,我们的 keys 文件夹下已经有如下内容了:
- .
- ├── https-client.js
- ├── https-server.js
- └── keys
- ├── ca.crt
- ├── ca.csr
- ├── ca.key
- ├── ca.pem
- ├── ca.srl
- ├── client.crt
- ├── client.csr
- ├── client.key
- ├── client.pem
- ├── server.crt
- ├── server.csr
- ├── server.key
- └── server.pem
看到上面两个 js 文件了么,我们来跑几个demo。
HTTPS本地测试
服务器代码:
- // file http-server.js
- var https = require('https');
- var fs = require('fs');
- var options = {
- key: fs.readFileSync('./keys/server.key'),
- cert: fs.readFileSync('./keys/server.crt')
- };
- https.createServer(options, function(req, res) {
- res.writeHead(200);
- res.end('hello world');
- }).listen(8000);
短短几行代码就构建了一个简单的 https 服务器,options 将私钥和证书带上。然后利用 curl 测试:
- ➜ https curl https://localhost:8000
- curl: (60) SSL certificate problem: Invalid certificate chain
- 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.
当我们直接访问时, curl https://localhost:8000
一堆提示,原因是没有经过 CA 认证,添加 -k
参数能够解决这个问题:
- ➜ https curl -k https://localhost:8000
- hello world%
这样的方式是不安全的,存在我们上面提到的中间人攻击问题。可以搞一个客户端带上 CA 证书试试:
- // file http-client.js
- var https = require('https');
- var fs = require('fs');
- var options = {
- hostname: "localhost",
- port: 8000,
- path: '/',
- methed: 'GET',
- key: fs.readFileSync('./keys/client.key'),
- cert: fs.readFileSync('./keys/client.crt'),
- ca: [fs.readFileSync('./keys/ca.crt')]
- };
- options.agent = new https.Agent(options);
- var req = https.request(options, function(res) {
- res.setEncoding('utf-8');
- res.on('data', function(d) {
- console.log(d);
- });
- });
- req.end();
- req.on('error', function(e) {
- console.log(e);
- });
先打开服务器 node http-server.js
,然后执行
- ➜ https node https-client.js
- hello world
如果你的代码没有输出
hello world
,说明证书生成的时候存在问题。也可以通过浏览器访问:
提示错误:
此服务器无法证明它是localhost;您计算机的操作系统不信任其安全证书。出现此问题的原因可能是配置有误或您的连接被拦截了。
原因是浏览器没有 CA 证书,只有 CA 证书,服务器才能够确定,这个用户就是真实的来自 localhost 的访问请求(比如不是代理过来的)。
你可以点击 继续前往localhost(不安全)
这个链接,相当于执行 curl -k https://localhost:8000
。如果我们的证书不是自己颁发,而是去靠谱的机构去申请的,那就不会出现这样的问题,因为靠谱机构的证书会放到浏览器中,浏览器会帮我们做很多事情。初次尝试的同学可以去 startssl.com 申请一个免费的证书。
Nginx 部署
ssh 到你的服务器,对 Nginx 做如下配置:
- 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";
会发现,网页 URL 地址框左边已经多出了一个小绿锁。当然,部署好了之后可以去这个网站 看看测评分数,如果分数是 A+,说明你的 HTTPS 的各项配置都还不错,速度也很快。
openssl https证书的更多相关文章
- openssl生成https证书
openssl生成https证书 分类: 其它2009-09-03 16:20 452人阅读 评论(0) 收藏 举报 includemoduleaccessapachessl服务器 openssl生成 ...
- CentOS6系统openssl生成证书和自签证书
CentOS6系统openssl生成证书和自签证书的过程,记录一下,本文基于CentOS 6 64bit.$ yum install openssl openssl-devel 1,生成服务器端的私钥 ...
- 自制Https证书并在Spring Boot和Nginx中使用
白话Https一文中, 介绍了Https存在的目的和工作原理,但多是偏向于原理性的介绍,本文介绍如何一步一步自制一个能够通过浏览器认证的Https证书,并讲解在Spring Boot环境和Nginx环 ...
- 如何申请https证书、搭建https网站
如何申请https证书.搭建https网站 随着国内搜索引擎巨头百度启用全站https加密服务,全国掀起了网站https加密浪潮.越来越多的站点希望通过部署https证书来解决“第三方”对用户隐私的嗅 ...
- https证书申请
因为要为海外组的aws设置https证书,由于使用的是新的域名,所以要先申请购买证书,然后设置上去.由于是第一次做这件事.所以过程有些坎坷. 先购买https证书.看了几家,感觉GoDad ...
- 自制Https证书并在Spring Boot和Nginx中使用(转)
白话Https一文中, 介绍了Https存在的目的和工作原理,但多是偏向于原理性的介绍,本文介绍如何一步一步自制一个能够通过浏览器认证的Https证书,并讲解在Spring Boot环境和Nginx环 ...
- nginx使用openssl的证书-泛解析
一.需求分析 我们公司测试环境,域名更换,原来的*.dev.devbao.cn 变为 *.dev.vdai.cn ,此处的*表示多个二级域名,导致原来为dev.devbao.cn制作的ssl ...
- HTTPS 证书配置
HTTPS 证书配置 现在阿里云和腾讯云都支持申请 HTTPS 证书,这里不再提,有需要的可自行google解决方案. 本文主要介绍的是通过 letsencrypt 申请免费的HTTPS证书,并将其配 ...
- 免费 Https 证书(Let's Encrypt)申请与配置
之前要申请免费的 https 证书操作步骤相当麻烦,今天看到有人在讨论,就搜索了一下.发现现在申请步骤简单多了. 1. 下载 certbot git clone https://github.com/ ...
随机推荐
- FormCollection获取请求数据
public ActionResult Add(FormCollection fm) //通过FormCollection 对象获取表单数据 { string message = "&quo ...
- esp32(M5STACK)在线体验(Ubuntu)
我们往m5stack烧录的固件是可以在线编程的 具体使用方法可以参考 https://github.com/m5stack/M5Cloud/blob/master/README_CN.md ...
- eas之添加表格列宽自动调整设置
设置表格整体宽度自动调整为所在panel的宽度 KDTable table=new KDTable(); table. setAutoResize (boolean); 注意:该功能在冻结功能启用后, ...
- java8方式日期比较
static ZoneId ZONEID_BJ = ZoneId.of("GMT+08:00"); private boolean sameDate(Date d1, Date d ...
- POJ3617 Best Cow Line【贪心】
Description 给定长度为n的字符串S,要构造一个长度为n的字符串T.起初,T是空串,随后反复进行下列任意操作: 1.从S的头部删除一个字符,加到T的尾部 2.从S的尾部删除一个字符,加 ...
- Centos 7.x 源码编译搭建Nginx
环境: centos 7 防火墙关闭 Selinx关闭 Nginx Web安装 安装依赖库 yum install pcre-devel pcre gcc gcc-c++ zlib zlib-deve ...
- CSS 利用transform达到居中效果
<body> <div class="center"> .... </div> </body> 让left和top都是50%,这在水 ...
- VirtualBox安装增强包实现文件共享
环境: win10 64位 Virtualbox 5.1.30 ubuntu-16.04.3-server-amd64.iso 1. 安装好ubuntu后,打开virtualbox安装路径文件夹,找到 ...
- 单元测试代码:SpringTest+JUnit
/** * JUnit单元测试父类,配置了Spring的基础环境. <br/> * 可以作为Controller.Service.Dao单元测试的父类. * * @author leiwe ...
- springboot启动报:Error creating bean with name 'dataSource' defined in class path resource
需要在启动类的@EnableAutoConfiguration或@SpringBootApplication中添加exclude = {DataSourceAutoConfiguration.clas ...