看看下面,部分电信用户访问京东首页的时候,会看到右下角有一个浮动广告:

小白用户以为是京东有意放置的,细心的用户会发现,这个 iframe 一层嵌一层的恶心广告很明显是电信/中间人通过 DNS 劫持注入进去的,十分恶心,没有关闭按钮。

随着互联网的快速发展,我们几乎离不开网络了,聊天、预订酒店、购物等等,我们的隐私无时无刻不暴露在这庞大的网络之中,HTTPS 能够让信息在网络中的传递更加安全,增加了 haker 的攻击成本。

HTTPS 区别于 HTTP,它多了加密(encryption),认证(verification),鉴定(identification)。它的安全源自非对称加密以及第三方的 CA 认证。

简述 HTTPS 的运作

如上图所示,简述如下:

  • 客户端生成一个随机数 random-client,传到服务器端(Say Hello)

  • 服务器端生成一个随机数 random-server,和着公钥,一起回馈给客户端(I got it)

  • 客户端收到的东西原封不动,加上 premaster secret(通过 random-clientrandom-server 经过一定算法生成的东西),再一次送给服务器端,这次传过去的东西会使用公钥加密

  • 服务器端先使用私钥解密,拿到 premaster secret,此时客户端和服务器端都拥有了三个要素:random-clientrandom-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.csrYou are about to be asked to enter information that will be incorporatedinto 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 blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [AU]:CNState or Province Name (full name) [Some-State]:ZhejiangLocality Name (eg, city) []:HangzhouOrganization Name (eg, company) [Internet Widgits Pty Ltd]:My CAOrganizational Unit Name (eg, section) []:Common Name (e.g. server FQDN or YOUR name) []:localhostEmail 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.jsvar 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:8000curl: (60) SSL certificate problem: Invalid certificate chainMore 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:8000hello world%

这样的方式是不安全的,存在我们上面提到的中间人攻击问题。可以搞一个客户端带上 CA 证书试试:

// file http-client.jsvar 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.jshello world

如果你的代码没有输出 hello world,说明证书生成的时候存在问题。也可以通过浏览器访问:

提示错误:

此服务器无法证明它是localhost;您计算机的操作系统不信任其安全证书。出现此问题的原因可能是配置有误或您的连接被拦截了。

原因是浏览器没有 CA 证书,只有 CA 证书,服务器才能够确定,这个用户就是真实的来自 localhost 的访问请求(比如不是代理过来的)。

你可以点击 继续前往localhost(不安全) 这个链接,相当于执行 curl -k https://localhost:8000。如果我们的证书不是自己颁发,而是去靠谱的机构去申请的,那就不会出现这样的问题,因为靠谱机构的证书会放到浏览器中,浏览器会帮我们做很多事情。初次尝试的同学可以去 startssl.com 申请一个免费的证书。

Nginx 部署

ssh 到你的服务器,对 Nginx 做如下配置:

server_names barretlee.com *.barretlee.comssl 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 secrecyssl_prefer_server_cipherson;add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";

会发现,网页 URL 地址框左边已经多出了一个小绿锁。当然,部署好了之后可以去这个网站看看测评分数,如果分数是 A+,说明你的 HTTPS 的各项配置都还不错,速度也很快。

小结

好吧,我也是初次尝试,本地测试是 ok 的,由于买的阿里云服务器到期了也没续费,就没远程折腾,其实本地 Nginx + Nodejs,然后 Hosts 配置域名也是可以较好模拟的。文中很多地方描述的可能不是十分准确,提到的点也不够全面,如果有错误,还请斧正!

HTTPS证书生成原理和部署细节的更多相关文章

  1. [svc]HTTPS证书生成原理和部署细节

    参考: http://www.barretlee.com/blog/2015/10/05/how-to-build-a-https-server/ 今天摸索了下 HTTPS 的证书生成,以及它在 Ng ...

  2. Golang代码实现HTTPs(HTTPS证书生成和部署)

    在win7下试试: 1.实现一个最简单的HTTPS Web Server // gohttps/2-https/server.go package main import ( "fmt&qu ...

  3. TLS/HTTPS 证书生成与验证

    最近在研究基于ssl的传输加密,涉及到了key和证书相关的话题,走了不少弯路,现在总结一下做个备忘 科普:TLS.SSL.HTTPS以及证书 不少人可能听过其中的超过3个名词,但它们究竟有什么关联呢? ...

  4. tomcat https 证书生成与配置

    第一步:生成证书 命令行输入: keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore &quo ...

  5. HTTPS证书生成方法,也适用于APP

    步骤: 一.登录服务器,创建ioscert目录 cd ~/servers/APP mkdir ioscert 二.cd到ioscert目录下,执行以下命令: 1.openssl genrsa -out ...

  6. https证书最佳实战目录

    [svc]openssl对称加密,非对称加密最佳实战 http://blog.csdn.net/iiiiher/article/details/78593464 [svc]证书的生成和各个字段的含义 ...

  7. HTTPS 证书配置

    HTTPS 证书配置 现在阿里云和腾讯云都支持申请 HTTPS 证书,这里不再提,有需要的可自行google解决方案. 本文主要介绍的是通过 letsencrypt 申请免费的HTTPS证书,并将其配 ...

  8. 一个空行引起的阿里云负载均衡上部署https证书的问题

    今天在阿里云上购买了WoSign的https证书,在证书签发后,在控制台下载证书文件,一共有2个文件,一个是.key文件(私钥文件),一个是.pem文件(证书文件). 然后在阿里云负载均衡“证书管理” ...

  9. Https系列之二:https的SSL证书在服务器端的部署,基于tomcat,spring boot

    Https系列会在下面几篇文章中分别作介绍: 一:https的简单介绍及SSL证书的生成二:https的SSL证书在服务器端的部署,基于tomcat,spring boot三:让服务器同时支持http ...

随机推荐

  1. 百度Clouda的初步探索

    最近一直比较关注百度Clouda,参加了数次百度Clouda团队举办的技术沙龙,也利用了一些时间读了开发文档,下面谈谈我对这个框架的初步理解: 1.  轻应用和Clouda的区别和联系:       ...

  2. python3-day4(yield)

    1.yield 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一 ...

  3. 【转】WCF、WebAPI、WCFREST、WebService之间的区别

    在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下,你有很多的选择来构建一个HTTP Services.我分享一下我对 ...

  4. linux自动交互工具expect,tcl安装和安装包,以及自动互信脚本

    linux自动交互工具expect,tcl安装,以及自动互信脚本 工作中需要对几十台服务器做自动互信,无意中发现expect命令,研究一番. 在网上找了许多资料也没有安装成功,摸索着总算成功了.现分享 ...

  5. [RxJS] Reactive Programming - New requests from refresh clicks -- merge()

    Now we want each time we click refresh button, we will get new group of users. So we need to get the ...

  6. Builder模式 初体验

        看来Java构造器模式,决定动手体验下.构造器模式是什么?干什么用的?推荐大家看下ITEYE的一篇文章     http://www.iteye.com/topic/71175     了解构 ...

  7. webpack的配置及使用

    webpack 安装 命令行输入 npm install webpack 配置文件 webpack.config.js moudule.exports = { //Import 入口文件 entry: ...

  8. python网络编程之socket

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  9. WinForm窗体设置

    属性: 软件启动后在屏幕中间 StartPosition = CenterScreen取消放大按钮 MaximizeBox = false不能拖动边框 FormBorderStyle = FixedD ...

  10. Android SQLite API的使用(非原创)

    1.使用SQLite的API来进行数据库的添加.删除.修改.查询 package com.example.sqlitedatabase.test; import android.content.Con ...