你了解HTTPS但你可能不了解X509

世上根本就没有HTTPS协议,只有HTTP协议。——知乎某答友 某天,收到领导指示:学习一下X.509相关原理。 很多开发者可能和我一样觉得X.509这个词很陌生,但其实我们经常和它打交道,属于典型的“日用而不知”的东西。 那么X.509是什么呢?X.509是一种数字证书的格式标准。应用很广泛,现在HTTPS依赖的SSL证书使用的就是使用的X.509格式。这也就是说,每当我们打开https开头的网站都会用到它。 格式标准简单地说,格式标准就像写HTML文件时的规范:开头声明文档类型,html作为根标签,元信息放在head标签中,页面内容放在body标签中等等。当然这个例子不是那么贴切,因为实际上不按照这个格式编写的html文件浏览器也能解析出来。更贴切的例子应该是JSON文件格式,规定了嵌套关系必须用大括号,数组必须用中括号,字符串必须用双引号等等,如果违反了一条其中的规则,那么就无法被正确的解析。 这个标准的具体内容是什么呢?X.509规定的格式大致如下: 版本号序列号签名算法颁发者证书有效期 开始日期 终止日期主题主题公钥信息 公钥算法 主体公钥颁发者唯一身份信息(可选)主题唯一身份信息(可选)扩展信息(可选)签名下图是某网站的 X.509 证书信息 {% asset_img certificate.jpg %} 数字证书那么数字证书又是什么?简单的说,数字证书就是通过加密算法来制造的一个网络“身份证”,用来证明通信方的真实身份。这个“身份证”的制作过程也很有意思,并不是由一个机构统一发放,而是层层颁发。比如 A 持有了可信证书,那么它颁发给的 B 的证书也是可信的, B 再颁发给 C 的证书也是可信的。整体结构很像数据结构中的“树”,其中 A 的证书为“根证书”,B 的为“中介证书”,C 的为“终端证书”。而 A、B 都被称作认证机构,简称 CA(Certificate authority)。 根证书 |中介证书 |终端证书根证书:通常预先安装在操作系统和浏览器中,是由大公司和政府联合制作的(用户也可以自己制作,但是会有安全风险),作为证书链的起点。中介证书:持有中介证书的CA主要负责给终端颁发证书,这些终端证书既有收费的也有免费的,免费终端证书一般使用期限是1年。终端证书:终端证书一般就是我们在浏览器上可以查看到的证书,通常用于具体网站服务中。这类证书不会再用作颁发新的证书。每个证书都可以沿着树往上追溯到根证书,从而形成一条信任链。比如下面这种图就是某网站证书的信任链信息。 {% asset_img certificate-chain.jpg %} 关于 X.509 的内容就分享完了。 但是心中的疑惑驱使着我继续探索,这证书靠谱么?如果黑客伪造认证机构给木马网站颁发证书呢? 安全机制证书采用的是一种非对称加密机制来保证信息不被窃取和复制。 加密技术这里稍稍解释下非对称机密,先说说密码学。 信息加密的需求其实一直都存在,从古代开始就使用各种技术来加密重要的信息,但是古代的加密安全程度都是基于加密方式的。 也就是说,别人如果知道了加密方式,那么就可以解密密文信息。 而现代的加密技术安全性在于密钥的安全,也就是说加密方式(算法)是公开的,只要密钥不被窃取或泄露,信息就是安全的。 虽然加密算法有很多种,但是大致上可以分为两类:对称加密和非对称加密。 对称加密的通信双方都是用同一个密钥进行加解密,而非对称加密则要求使用不同的密钥进行加密和解密。 再回到证书的颁发过程,现在很多云服务厂商都提供了申请数字证书的功能,它会像CA发起申请,CA收到申请之后,做了下面的事情: 使用加密算法生成公私钥对。私钥一般是以.key为后缀名的文件,公钥存储于以.csr结尾的文件中。在.csr文件中补充一些信息比如有效期限等,颁发者,并用自己的私钥对证书进行签名。这样就生成符合X.509格式的证书。用户收到证书后,在web服务器(或负载均衡等设备)上进行部署。SSL证书符合X.509格式的证书有多种,这里以SSL证书为例。 常见的场景会是下面这样: 客户端,比如浏览器会向服务端发送请求,服务端为了证明自己的身份,会发送证书给对方。浏览器读取证书的数字签名部分,用自身根证书列表中对应的公钥证书对其进行解密。如果解密成功,并且证书哈希值与签名内的哈希值匹配一致,可证明站点提供的证书确实是该CA根证书签发的,否则给出风险提示。验证通过之后,使用证书中的公钥对随机数和对称加密算法加密,发送给服务端,服务端用私钥进行解密,获得密钥和加密算法。服务端与浏览器后续通信将会使用新的对称加密算法和随机密钥加密信息。证书在整个流程起到了重要的作用,那么能不能通过窃取和伪造的方式来获取通信内容呢? 窃取。首先证书当然是可以被窃取的,因为它是公开的,但是拿到了证书后也只能和服务端进行通信,不能用来窃取其它信息,至于证书的私钥存储在服务端,更加不可能随意被窃取了。伪造。如果有人伪造了一张网站证书,那么浏览器在向CA查询证书信息的时候就会验证失败。那这么说就是绝对安全了吗?非也~ 对于DNS劫持的情况还是无解的。比如浏览器访问网站的时候给了一个假证书,然后向CA验证证书的时候又访问了一个假网站,证书就有可能被验证通过。从而黑客可以作为中间方获取并转发双方的数据。 总结SSL证书从生成到使用涉及到了三次加解密过程: 证书生成的时候利用私钥签名,验证证书的时候利用公钥解密。确认证书有效后,利用证书中的公钥进行加密,服务端利用私钥解密。双方使用新生成的随机密钥进行数据加解密。用一张结构图表示下HTTPS和X.509的关系: HTTPS / \HTTP TLS/SSL / \ 通信内容 确认身份

June 18, 2019 · 1 min · jiezi

一文教您如何通过-Docker-搭建反向代理-Ngnix并配置-Https-SSL-证书

欢迎关注个人微信公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习、面试资源哟!!个人网站: https://www.exception.site/docker/how-to-config-ssl-with-docker-nginx 一、背景小哈最近收到阿里云短信,提示个站 www.exception.site 的云盾 SSL 证书(Https 证书)即将到期,需要赶快续费,不然无法继续使用 Https 协议来访问网站! 这个 SSL 证书当时用的是阿里云免费型的,有效期为 1 年,到期后, 如果想继续使用这个证书,就得续费,而且费用还不低! 其实,要想继续使用 Https 协议,我们可以在阿里云上再次申请一张 SSL 证书就可以了,时间一年,嗨呀,又能免费用一年。 本文小哈就主要介绍如何在 Ngnix 上配置 SSL 证书,从而让我们的网站能够使用 Https 来访问,另外再附带说一下如何配置反向代理。 二、Docker 快速安装&搭建 Ngnix 环境小哈的个站 Ngnix 搭建在容器当中,也就顺便说一下如何通过 Docker 快速安装&搭建 Ngnix 环境。 2.1 下载 Nginx 镜像docker pull nginx:alpinePS:我这里用的是 alipne 轻量级的镜像.下载完成后,通过 docker images 命令检查一下镜像是否下载成功: 2.2 先以简单的方式运行镜像docker run -d -p 80:80 --name nginx nginx:alpine-p 80:80: 将容器的 80 端口映射到宿主机的 80 端口上;-d: 以后台方式运行镜像;--name: 指定容器的名称为 nginx;命令执行完成后,通过 docker ps命令确认一下容器是否启动成功。确认成功后,再访问一下 80 端口,看看 nginx 服务是否启动成功: ...

June 12, 2019 · 2 min · jiezi

SSL证书购买需要多少钱

SSL证书可以用来对网站进行信息加密,防止被劫持、窃取和篡改,同时可以防止钓鱼网站,提高企业形象,增加用户的安全感。那么大家在选择SSL证书的时候,最关心的一个问题就是价格了。市场上的SSL证书价格天差地别,小到几百大到几万元,那么为什么SSL证书价格会这么大差别呢。这就和SSL证书的类型有关了。SSL证书主要有三种:DV SSL证书 、OV SSL证书 、 EV SSL证书。域名型(DV)SSL证书:DVSSL价格通常在300-1000元左右,信任等级一般只需验证网站的真实性便可颁发证书保护网站 普通加锁标记,小时级极速签发适合个人开发者,个人网址。企业型(OV)SSL证书:OVSSL证书价格一般在2000-4000元不等,信任等级强须要验证企业的身份,审核严格,安全性更高普通加锁标记,3-5个工作日快速签发适合电商、网店、企业官网。企业增强型(EV)SSL证书:EVSSL证书价格一般在4000-6000元不等,信任等级最高须要验证企业的身份,审核严格,安全性最高 绿色安全地址栏,3-5个工作日签发一般用于银行证券金融等机构。SSL证书的设计初衷,就是由国际顶尖的CA安全机构来做颁发, Symantec、GeoTrust、comodo、digicert等机构进行颁发。所以大家在选择SSL证书的时候最好选择权威的受信任的证书机构颁发的证书。SSL证书申请一站式服务,为网站、移动应用提供安全可靠HTTPS解决方案,最大限度简化了SSL证书申购的流程。

June 10, 2019 · 1 min · jiezi

如何生成自己的根证书

背景由于公司研发人员增加,测试服务器不够用了,所以加了新服务器,新服务器的https证书就成问题了,总不能每次新增服务器都要重新生成https证书吧,而且还得让全公司研发都信任一遍,那是相当费事了。 解决方案公司自己当证书颁发机构,所有人将公司设为受信任的证书颁发机构,这样公司颁发的所有证书就会被自动信任 生成rootCA什么是CA?数字证书认证机构(英语:Certificate Authority,缩写为CA),下面是生成ca的方法 生成私钥openssl genrsa -des3 -out myCA.key 2048命令执行过程中会要求输入密码,由于是测试环境,对安全性没那么高,可以随便输一个。 生成rootCAopenssl req -x509 -new -nodes -key myCA.key -sha256 -days 36500 -out myCA.pem执行过程中会要求输入各种信息,按要求输入即可 完成现在我们有myCA.pem,这就root CA。 然后在操作系统里信任myCA.pem。 使用rootCA生成证书生成私钥 openssl genrsa -out dev.com.key 2048生成签名请求 openssl req -new -key dev.com.key -out dev.com.csr创建配置文件dev.com.ext authorityKeyIdentifier=keyid,issuerbasicConstraints=CA:FALSEkeyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEnciphermentsubjectAltName = @alt_names[alt_names]DNS.1 = dev.com最后生成证书 openssl x509 -req -in dev.com.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial \-out dev.com.crt -days 1825 -sha256 -extfile dev.com.ext现在有3个文件dev.com.key(私钥),dev.com.csr(证书签名请求),dev.com.crt(证书) nginx配置 ...

June 10, 2019 · 1 min · jiezi

Https在各种Web服务器下配置

前言前端很多情况需要用启动web服务器,而为了保证数据的安全性,都需要用Https对传输的数据进行加密传输,而且有些web-view只允许https通过访问,所以学习怎么配置https也成为大前端不可以少的功课之一。下面本妹子将先简单介绍下 Https,再依次介绍怎么在Node、webpack-dev-server和nginx这三个最常见的前端web服务器下配置Https,以及关于证书的扩展干货。 Https简介Https协议的主要作用可以分为两点:1.建立一个信息安全通道,来保证数据传输的安全;2.确认网站的真实性;而https的加密方式主要是非对称加密,所以会有一对密钥,分别是一个公钥(证书)和私钥。 浏览器allen访问的时候,客户端会接受这个证书,并利用这个证书里的公钥对数据加密,加密后,服务端tony用自己的私钥解密就行了。 Web服务一般使用OpenSSL工具提供的密码库,生成PEM、KEY、CRT等格式的证书文件。其中.crt后缀一般存放证书,.key后缀一般存放私钥,.pem后缀的可以同时存放把CA证书和密钥。 生成证书和密钥可以直接用命令生成 #使用以下命令生成一个证书密钥对 key.pem 和 cert.pem,它将有效期约10年(准确地说是3650天)openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.key -out cert.crt#或者直接生成到一个pem文件中openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout all.pem -out all.pem可以用selfsigned插件生成 const selfsigned = require('selfsigned');var selfsigned = require('selfsigned');var attrs = [{ name: 'commonName', value: 'contoso.com' }];//有效期约10年var pems = selfsigned.generate(attrs, { days: 3650 });fs.writeFileSync('all.pem', pems.private + pems.cert, { encoding: 'utf-8' });node配置https用openssl生成all.pem openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout all.pem -out all.pem在同目录编写app.js,并运行node app.js,启动node服务监听88端口 ...

June 5, 2019 · 2 min · jiezi

SSL证书是什么

SSL证书又称“服务器证书、https证书、CA证书、网站安全证书”等,是一种数字证书。SSL证书可以用来对网站信息进行https加密,防止信息被监听、截取和,验证网站身份,防止钓鱼网站,同时提高企业形象,增加用户安全感,有利于提高在百度谷歌等搜索中的排名权重和收录优势。 如图所示,会在地址栏显示绿色小锁标志,点击小锁可以查看证书信息。更多SSL证书详情,可参考合信SSL

June 1, 2019 · 1 min · jiezi

SSL证书如何选择

网站的加密一般会用到SSL证书,但是SSL证书在市场上也有不少不同种类的,用户可以根据自己的实际需求情况选择对应的证书。ssl证书通常分为以下三种:1、DV型SSL证书DV型证书安全等级是三者中最低的,一般适合个人网站或小型的企业网站,但是该证书审核快,无需递交任何材料。2、OV型SSL证书企业型证书,需要验证网站所有单位的真实身份的标准型SSL证书,此类证书也就是正常的SSL证书,不仅能起到网站机密信息加密的作用,而且能向用户证明网站的真实身份。3、EV型SSL证书增强型证书,可以看做是DV、OV的加强版,安全等级最高,但是审核最严格。

May 30, 2019 · 1 min · jiezi

什么是https加密

https通常是用来给网站数据传输进行加密保护的,防止传输过程中,网站信息发生泄密,导致被别人窃取,造成损失。那么什么是https加密呢https也就是加密的http,就是在http的基础上加了一个SSL层。 单一使用对称加密 拦截客户端报文,伪造秘钥当客户端初次向服务器请求秘钥时,报文可能被黑客截获,黑客伪装服务器向客户端返回一个黑客生成的秘钥,当客户端使用该虚假秘钥发送报文时,黑客就可以解密客户端发送的报文信息。 拦截服务器报文,截获秘钥当客户端初次向服务器请求秘钥是,服务器返回秘钥报文,中途被黑客截获,获得秘钥信息。当客户端发送加密报文给服务器或者服务器返回加密报文时都可能被截获报文信息并且解密。单一使用非对称加密(RSA) 拦截客户端报文,伪造公钥当客户端初次向服务器请求公钥时,报文可能被黑客截获,黑客伪装服务器向客户端返回一个黑客生成的公钥,并且自己保留私钥。当客户端使用该黑客虚假公钥加密发送报文时,黑客就可以用私钥解密客户端发送的报文信息。 拦截服务端报文,伪造公钥当客户端初次向服务器请求秘钥时,服务器返回公钥报文,中途被黑客截获,并且黑客修改报文中的公钥信息为黑客生成的公钥。当客户端发送使用黑客虚假公钥加密的报文给服务器时,可能被黑客截获报文信息并且用黑客私钥解密。 拦截服务端报文,解密返回给客户的报文信息当客户端安全获得服务器发放公钥并且请求服务器时,服务器返回加密后报文信息。黑客可以截获服务器返回的报文信息,并且用公钥解密(因为公钥是大家都知道的),从而盗取服务器响应报文。https加密的原理如下图所示: 1、 客户端发起https请求2、 服务器端的配置3、 传送证书4、 客户端解析证书5、 传送加密信息6、 服务段解密信息7、 传输加密后的信息8、 客户端解密信息

May 30, 2019 · 1 min · jiezi

网站为什么需要ssl证书

网站部署SSL证书后,用户就可以很方便的了解到网站的真实身份信息,从而放心的浏览网站。没有部署SSL证书保护的网站,消费者没法判断网站的真实与否,考虑到自身的安全,很有可能选择放弃继续浏览网站。这就无形中影响了网站的效益,同时SSL证书对于提高网站品牌的建设也有很好的推动作用。网站没有安装ssl证书可能会出现如图所示的警告: 网站没有加密,会被别人利用制造一个与网站类似的钓鱼网站,进行了https加密后,可以有效的区分钓鱼网站和官方网站。使用SSL证书可以防止数据被篡改,防止信息被窃取,同时 可以提高网站的排名和信任度。想要了解更多ssl证书,详情咨询合信SSL

May 27, 2019 · 1 min · jiezi

为什么https要使用证书

最近看了一本关于网络的书,叫做《图解http》,觉得这本书写的很好,看完之后印象比较深的是这本书的https的解释,为此在此总结一下自己的理解。文中的很多截图出自http图解,在此表示感谢。 什么是httpshttps不是一种新的协议,只是http的通信接口部分使用了ssl和tsl协议替代,加入了加密、证书、完整性保护的功能,下面解释一下加密和证书,如下图所示 加密:共享密钥加密加密和解密公用一套秘钥,这样就会产生问题,已共享秘钥加密方式必须将秘钥传送给对方,但如果通信被监听,那么秘钥可能会被泄漏产生危险。 公开秘钥加密公开秘钥加密使用一种非对称加密的算法,使用一对非对称的秘钥,一把叫做共有秘钥,一把叫做私有秘钥,在加密的时候,通信的一方使用共有秘钥进行加密,通信的另一方使用私有秘钥进行解密,利用这种方式不需要发送私有秘钥,也就不存在泄漏的风险了。 https加密方式因为公开秘钥加密的方式比共享秘钥加密的方式钥消耗cpu资源,https采取了混合加密的方式,来结合两者的优点。 在秘钥交换阶段使用公开加密的方式,之后建立连接后使用共享秘钥加密方式进行加密,如下图。 为什么要使用证书:因为公开加密还存在一些问题就是无法证明公开秘钥的正确性,为了解决这个问题,https采取了有数字证实认证机构和其相关机构颁发的公开秘钥证书,通信过程如下图所示。 解释一下上图的步骤:1.服务器将自己的公开秘钥传到数字证书认证机构2.数字证书认证机构使用自己的秘钥来对传来的服务器公钥进行加密,,并颁发数字证书3.服务器将传回的公钥证书发送给客户端,客户端使用数字机构颁发的公开秘钥来验证证书的有效性,以及公开秘钥的真实性4.客户端使用服务器的公开秘钥进行消息加密,后发送给服务器。5.服务器使用私有秘钥进行解密。 浏览器在安装的时候会内置可信的数字证书机构的共有秘钥,如下图所示。 这就是为什么我们使用自己生成的证书的时候会产生安全警告的原因。 再附一张https的具体通信步骤和图解。 最后用了人家这么多图给个购买链接吧图解http

May 24, 2019 · 1 min · jiezi

HTTPS加密真的有效吗

HTTPS简单来讲就是在http的基础上加一个SSL层,也就是http的安全版本。HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。HTTPS的工作原理如下图所示: 客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤:(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。(5)Web服务器利用自己的私钥解密出会话密钥。(6)Web服务器利用会话密钥加密与客户端之间的通信。目前来讲HTTPS是现下最优选的解决方案,具体有以下几个好处:(1)使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;(2)HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。(3)HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。(4)谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。

May 24, 2019 · 1 min · jiezi

SSL证书错误如何解决

现在网站的安全基本上都是依靠SSL证书来实现的,但是我们在使用SSL证书的时候,难免会遇到一些问题。那么为什么有时候我们会遇到SSL证书无效的情况呢?1、证书过期或未生效通常我们使用的SSL证书都是有一个时效性的,超过了SSL证书的有效期,就会提示SSL证书无效。这是先检查下计算机系统时间是否正确,如果错误,将其改为正确的时间即可 2、网站证书不是由受信任的证书颁发机构颁发SSL证书不是由信任的CA证书颁发机构颁发的,不在浏览器厂商的信任列表中。方法:Internet——内容——证书导入即可。3、ssl证书包含的域名与网站地址不一致。每一个ssl证书所对应的域名都具有唯一性,当网站出具的证书所包含的域名和网站域名不一致时,系统就会自动发出报告,提示证书域名不匹配。方法:需要重新申请ssl证书。可根据自己的需求申请对应的SSL证书。

May 22, 2019 · 1 min · jiezi

五分钟搞定-HTTPS-配置二哥手把手教

01、关于 FreeSSL.cnFreeSSL.cn 是一个免费提供 HTTPS 证书申请、HTTPS 证书管理和 HTTPS 证书到期提醒服务的网站,旨在推进 HTTPS 证书的普及与应用,简化证书申请的流程。 当然了,我看重的不是免费,而是 FreeSSL 使用起来非常人性化。我是一个计算机常识非常薄弱的程序员(羞愧一下),但通过 FreeSSL,我竟然可以独自完成 Tomcat 的 HTTPS 配置! 很多年以前,公司要做华夏银行的接口对接,需要 HTTPS 访问,大概花了 3000 块买的证书,最后证书还有问题,HTTPS 也没搞定。总之,坑的很! FreeSSL.cn 有很大的不同,申请非常便捷,优点很多,值得推荐一波。毕竟再也不用邮件、电话各种联系了(也许时代进步了)。 100% 永久免费;这要感谢 Let's Encrypt 与 TrustAsia 提供的免费 SSL 证书。在 HTTPS 证书到期前,FreeSSL.cn 会及时地提醒更换证书,免费的服务。私钥不在网络中传播,确保 HTTPS 证书的安全。02、使用 FreeSSL 申请证书第一步,填写域名,点击「创建免费的 SSL 证书」 第二步,填写邮箱,点击「创建」 1)证书类型默认为 RSA RSA 和 ECC 有什么区别呢?可以通过下面几段文字了解一下。 HTTPS 通过 TLS 层和证书机制提供了内容加密、身份认证和数据完整性三大功能,可以有效防止数据被监听或篡改,还能抵御 MITM(中间人)攻击。TLS 在实施加密过程中,需要用到非对称密钥交换和对称内容加密两大算法。 对称内容加密强度非常高,加解密速度也很快,只是无法安全地生成和保管密钥。在 TLS 协议中,应用数据都是经过对称加密后传输的,传输中所使用的对称密钥,则是在握手阶段通过非对称密钥交换而来。常见的 AES-GCM、ChaCha20-Poly1305,都是对称加密算法。 非对称密钥交换能在不安全的数据通道中,产生只有通信双方才知道的对称加密密钥。目前最常用的密钥交换算法有 RSA 和 ECDHE:RSA 历史悠久,支持度好,但不支持 PFS(Perfect Forward Secrecy);而 ECDHE 是使用了 ECC(椭圆曲线)的 DH(Diffie-Hellman)算法,计算速度快,支持 PFS。 ...

May 10, 2019 · 1 min · jiezi

使用openSSL构造一个支持https的nodejs服务器

首先通过下面的链接下载openSSLhttps://slproweb.com/products... 下载完毕后,执行openssl进入交互式界面: 使用命令生成privatekey.pem 1024意思是1024位长度。 openssl genrsa -out privatekey.pem 1024 生成的privatekey.pem,打开看一看长啥样: 什么是pem文件? .pem - Defined in RFCs 1421 through 1424, this is a container format that may include just the public certificate (such as with Apache installs, and CA certificate files /etc/ssl/certs), or may include an entire certificate chain including public key, private key, and root certificates. Confusingly, it may also encode a CSR (e.g. as used here) as the PKCS10 format can be translated into PEM. The name is from Privacy Enhanced Mail (PEM), a failed method for secure email but the container format it used lives on, and is a base64 translation of the x509 ASN.1 keys.简单的说,就是一个密钥文件。 ...

May 9, 2019 · 2 min · jiezi

https浅析

概念HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。 HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 区别超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。 为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。 HTTPS和HTTP的区别主要为以下四点: 一、https协议需要到ca申请证书,一般免费证书很少,需要交费。 二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。 三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。 四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。 HTTPS的工作原理客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。 (1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。 (2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。 (3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。 (4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。 (5)Web服务器利用自己的私钥解密出会话密钥。 (6)Web服务器利用会话密钥加密与客户端之间的通信。 HTTPS的优点 尽管HTTPS并非绝对安全,掌握根证书的机构、掌握加密算法的组织同样可以进行中间人形式的攻击,但HTTPS仍是现行架构下最安全的解决方案,主要有以下几个好处: (1)使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器; (2)HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。 (3)HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。 (4)谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。 HTTPS的缺点 虽然说HTTPS有很大的优势,但其相对来说,还是存在不足之处的: (1)HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电; (2)HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响; (3)SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。 (4)SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。 (5)HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。 http切换到HTTPS可以通过代理服务器nginx等把http请求代理成https,服务端需要添加证书支持https

May 8, 2019 · 1 min · jiezi

nodejs中request库使用HTTPS代理

正在尝试改用NodeJS编写爬虫,http请求库选择了request,用起来还是挺简单的。现在有个需求,需要用Fiddler抓包我发出去的请求,以便和浏览器发出去的包进行对比。因为需要解密HTTPS报文,需要让node要么忽略证书安全,要么信任Fiddler的CA证书。网上找了一圈,总结如下: 设置环境变量设置环境变量NODE_TLS_REJECT_UNAUTHORIZED=0即"不拒绝未认证的证书"但是直接修改系统环境变量比较危险,因为会影响到所有nodejs的程序;比较稳妥的办法是脚本中调用process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; 这样仅对本进程生效每请求单独设置忽略证书安全上述方法还是有一定风险,因为当前nodejs进程都受此全局设置影响可以在request的options中添加rejectUnauthorized: false选项来针对单个请求忽略证书检查当然也可以用request.defaults直接设置默认选项 const request = require("request").defaults({ proxy: "http://127.0.0.1:8888", rejectUnauthorized: false, }) request.get("https://www.baidu.com").on("response", console.log)直接使用Fiddler的CA证书这个方法是最稳妥的,不会对你的子系统之外产生任何溢出影响首先在Fiddler内把其根证书导出到桌面:Tools -> Options -> HTTPS -> Actions -> Export Root Certificate to Desktop导出的文件是个.cer证书,经测试nodejs不直接支持,需要用openssl转换成PEM格式(我的openssl是cygwin装的)openssl x509 -inform DER -in FiddlerRoot.cer -outform PEM -out fiddler.pem把转换出来的fiddler.pem放到你的程序能访问的位置使用ca选项来指定CA证书 const request = require("request").defaults({ proxy: "http://127.0.0.1:8888", ca: require("fs").readFileSync("path/to/fiddler.pem", {encoding: "utf-8"}), }) request.get("https://www.baidu.com").on("response", console.log)另外:request当然也支持自签名证书,不过我暂时没这方面需求,就没继续摸索了

April 29, 2019 · 1 min · jiezi

Nginx-配置-Https-免费证书访问

配置HTTPS现在做博客或者做网站没有 https 已经不行了,就记录一下我在腾讯云配置 https 的过程吧,非常简单,1个小时就可以了。 还涉及到 http 访问自动转发到 https 访问路径。同时把不带 www 的顶级域名转发到带 www 的二级域名上,有利于 SEO. 申请证书不管是腾讯云还是阿里云都提供免费的证书使用,不过有效期是 1 年,到时候我们重新申请就可以了。我们以腾讯云为例子,申请证书。 然后验证一下 DNS 记录就好了,如果域名是在使用腾讯云解析的话直接选用自动 DNS 验证即可。 官方说法是申请证书需要10分钟-1天的时间,我大概就是十几分钟吧,很快就收到通知了。下载的证书包含 Apache、Nginx、Tomcat、IIS等服务器的配置文件。我们把 Nginx 文件夹下的两个文件传到服务器就行了。 配置证书我们在 etc/nginx/ 目录下新建 ssl 文件夹来存放证书。把 crt 证书文件和 key 私钥文件上传到这里。然后就可以配置 Nginx 配置文件了。 我的配置文件放在 sites-enabled 文件夹里,我们删掉默认的文件新建一个,具体配置内容可以参考腾讯云的操作指导。 下面是我的配置文件 # 配置 http 访问时通过 301 转发到 https 上。server{ listen 80; server_name example.com www.example.com; return 301 https://www.example.com$request_uri;}# 证书部分内容配置,注意证书路径写对,其他地方照抄就行了server { listen 443 ssl default_server; server_name www.example.com; ssl on; ssl_certificate /etc/nginx/ssl/1_www.example.com_bundle.crt; ssl_certificate_key /etc/nginx/ssl/2_www.example.com.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8000; }}# 这一步把 顶级域名转发到 www 二级域名上,有利于 SEOserver { listen 443 ssl; server_name example.com; return 301 https://www.example.com$request_uri;}第一个server 配置的是把普通 80 端口访问的 http 协议转发到 https 访问。第二个server 配置的就是证书路径和一些参数,这个照抄就行了,只要把证书路径写对第三个server 配置的是把不带 www 的顶级域名转发到带 www 的二级域名,利于 SEO. 比如 example.com 会自动跳转到 www.example.com 。 ...

April 29, 2019 · 1 min · jiezi

为什么HTTPS比HTTP更安全

前言近几年,互联网发生着翻天覆地的变化,尤其是我们一直习以为常的HTTP协议,在逐渐的被HTTPS协议所取代,在浏览器、搜索引擎、CA机构、大型互联网企业的共同促进下,互联网迎来了“HTTPS加密时代”,HTTPS将在未来的几年内全面取代HTTP成为传输协议的主流。 读完本文,希望你能明白: HTTP通信存在什么问题HTTPS如何改进HTTP存在那些问题HTTPS工作原理是什么想阅读更多优质文章请猛戳GitHub博客,一年五十篇优质文章等着你! 一、什么是HTTPSHTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。 HTTPS主要作用是: (1)对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全; (2)对网站服务器进行真实身份认证。 我们经常会在Web的登录页面和购物结算界面等使用HTTPS通信。使用HTTPS通信时,不再用http://,而是改用https://。另外,当浏览器访问HTTPS通信有效的Web网站时,浏览器的地址栏内会出现一个带锁的标记。对HTTPS的显示方式会因浏览器的不同而有所改变。 二、为什么需要HTTPS在HTTP协议中有可能存在信息窃取或身份伪装等安全问题。使用HTTPS通信机制可以有效地防止这些问题,接下来,我们先来了解下HTTP协议存在的哪些问题: 通信使用明文(不加密),内容可能被窃听由于HTTP本身不具备加密的功能,所以也无法做到对通信整体(使用HTTP协议通信的请求和响应的内容)进行加密。即,HTTP报文使用明文(指未经过加密的报文)方式发送。 HTTP明文协议的缺陷是导致数据泄露、数据篡改、流量劫持、钓鱼攻击等安全问题的重要原因。HTTP协议无法加密数据,所有通信数据都在网络中明文“裸奔”。通过网络的嗅探设备及一些技术手段,就可还原HTTP报文内容。 无法证明报文的完整性,所以可能遭篡改所谓完整性是指信息的准确度。若无法证明其完整性,通常也就意味着无法判断信息是否准确。由于HTTP协议无法证明通信的报文完整性,因此,在请求或响应送出之后直到对方接收之前的这段时间内,即使请求或响应的内容遭到篡改,也没有办法获悉。换句话说,没有任何办法确认,发出的请求/响应和接收到的请求/响应是前后相同的。 不验证通信方的身份,因此有可能遭遇伪装HTTP协议中的请求和响应不会对通信方进行确认。在HTTP协议通信时,由于不存在确认通信方的处理步骤,任何人都可以发起请求。另外,服务器只要接收到请求,不管对方是谁都会返回一个响应(但也仅限于发送端的IP地址和端口号没有被Web服务器设定限制访问的前提下) HTTP协议无法验证通信方身份,任何人都可以伪造虚假服务器欺骗用户,实现“钓鱼欺诈”,用户无法察觉。 反观HTTPS协议,它比HTTP协议相比多了以下优势(下文会详细介绍): 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥数据完整性:内容传输经过完整性校验身份认证:第三方无法伪造服务端(客户端)身份三、HTTPS如何解决HTTP上述问题?HTTPS并非是应用层的一种新协议。只是HTTP通信接口部分用SSL和TLS协议代替而已。 通常,HTTP直接和TCP通信。当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了。简言之,所谓HTTPS,其实就是身披SSL协议这层外壳的HTTP。 在采用SSL后,HTTP就拥有了HTTPS的加密、证书和完整性保护这些功能。也就是说HTTP加上加密处理和认证以及完整性保护后即是HTTPS。 HTTPS 协议的主要功能基本都依赖于 TLS/SSL 协议,TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。 1.解决内容可能被窃听的问题——加密方法1.对称加密这种方式加密和解密同用一个密钥。加密和解密都会用到密钥。没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了。 以对称加密方式加密时必须将密钥也发给对方。可究竟怎样才能安全地转交?在互联网上转发密钥时,如果通信被监听那么密钥就可会落人攻击者之手,同时也就失去了加密的意义。另外还得设法安全地保管接收到的密钥。 方法2.非对称加密公开密钥加密使用一对非对称的密钥。一把叫做私有密钥,另一把叫做公开密钥。顾名思义,私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。 使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。 非对称加密的特点是信息传输一对多,服务器只需要维持一个私钥就能够和多个客户端进行加密通信。 这种方式有以下缺点: 公钥是公开的,所以针对私钥加密的信息,黑客截获后可以使用公钥进行解密,获取其中的内容;公钥并不包含服务器的信息,使用非对称加密算法无法确保服务器身份的合法性,存在中间人攻击的风险,服务器发送给客户端的公钥可能在传送过程中被中间人截获并篡改;使用非对称加密在数据加密解密过程需要消耗一定时间,降低了数据传输效率;方法3.对称加密+非对称加密(HTTPS采用这种方式)使用对称密钥的好处是解密的效率比较快,使用非对称密钥的好处是可以使得传输的内容不能被破解,因为就算你拦截到了数据,但是没有对应的私钥,也是不能破解内容的。就比如说你抢到了一个保险柜,但是没有保险柜的钥匙也不能打开保险柜。那我们就将对称加密与非对称加密结合起来,充分利用两者各自的优势,在交换密钥环节使用非对称加密方式,之后的建立通信交换报文阶段则使用对称加密方式。 具体做法是:发送密文的一方使用对方的公钥进行加密处理“对称的密钥”,然后对方用自己的私钥解密拿到“对称的密钥”,这样可以确保交换的密钥是安全的前提下,使用对称加密方式进行通信。所以,HTTPS采用对称加密和非对称加密两者并用的混合加密机制。 2.解决报文可能遭篡改问题——数字签名网络传输过程中需要经过很多中间节点,虽然数据无法被解密,但可能被篡改,那如何校验数据的完整性呢?----校验数字签名。 数字签名有两种功效: 能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。数字签名能确定消息的完整性,证明数据是否未被篡改过。数字签名如何生成: 将一段文本先用Hash函数生成消息摘要,然后用发送者的私钥加密生成数字签名,与原文文一起传送给接收者。接下来就是接收者校验数字签名的流程了。 校验数字签名流程: 接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与上一步得到的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。 假设消息传递在Kobe,James两人之间发生。James将消息连同数字签名一起发送给Kobe,Kobe接收到消息后,通过校验数字签名,就可以验证接收到的消息就是James发送的。当然,这个过程的前提是Kobe知道James的公钥。问题的关键的是,和消息本身一样,公钥不能在不安全的网络中直接发送给Kobe,或者说拿到的公钥如何证明是James的。 此时就需要引入了证书颁发机构(Certificate Authority,简称CA),CA数量并不多,Kobe客户端内置了所有受信任CA的证书。CA对James的公钥(和其他信息)数字签名后生成证书。 3.解决通信方身份可能被伪装的问题——数字证书数字证书认证机构处于客户端与服务器双方都可信赖的第三方机构的立场上。我们来介绍一下数字证书认证机构的业务流程: 服务器的运营人员向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;如信息审核通过,CA会向申请者签发认证文件-证书。证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名。 其中签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA的私钥对信息摘要进行加密,密文即签名;客户端 Client 向服务器 Server 发出请求时,Server 返回证书文件;客户端 Client 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即服务器的公开密钥是值得信赖的。客户端还会验证证书相关的域名信息、有效时间等信息; 客户端会内置信任CA的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA的证书,证书也会被判定非法。四、 HTTPS工作流程 1.Client发起一个HTTPS(比如https://juejin.im/user/5a9a9cdcf265da238b7d771c)的请求,根据RFC2818的规定,Client知道需要连接Server的443(默认)端口。 2.Server把事先配置好的公钥证书(public key certificate)返回给客户端。 ...

April 26, 2019 · 1 min · jiezi

Nginx下Frp强制重定向为https配置

迫于家里的路由将300M的带宽强行降到80M的速度,所以入手了一个3205U的软路由,果真没有令人失望,速度飞起O(∩_∩)O哈哈~ 当然,由于宽带没有公网IP所以DDNS就不能使用,转而使用frp,在折腾的过程中踩到了一些坑,所以记录下来,希望能帮助有需要的同学。 frps.ini(服务端配置)[common]bind_port = 5443kcp_bind_port = 5443vhost_http_port = 8080vhost_https_port = 4443# Frp的服务器指示面板配置admin_addr = frp.test.comdashboard_port = 6443dashboard_user = testdashboard_pwd = testlog_file = ./frps.log# trace, debug, info, warn, errorlog_level = infolog_max_days = 3# auth token 可自主生成一些字符串token = sfsfgsdgsdgsgddgsgtcp_mux = truemax_pool_count = 50# 用户自定义域名subdomain_host = frp.test.comfrpc.ini (客户端配置)[common]# 远程服务器IP地址server_addr = 8.8.8.8server_port = 5443token = sfsfgsdgsdgsgddgsgtls_enable = true[lede]type = httplocal_ip = 10.10.10.1local_port = 80# 这里的值最终会被解析为lede.frp.test.com(需要在你的域名服务器做指向你自己公网服务器的*.frp.test.com的# 域名泛解析)subdomain = ledeuse_encryption = false use_compression = true# HTTP基础认证可以不填写http_user = testhttp_pwd = testvhosts.conf(Nginx配置)server { listen 80; listen 443 ssl http2; ssl_certificate /usr/local/nginx/conf/ssl/lede.frp.test.com.crt; ssl_certificate_key /usr/local/nginx/conf/ssl/lede.frp.test.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; ssl_prefer_server_ciphers on; ssl_session_timeout 10m; ssl_session_cache builtin:1000 shared:SSL:10m; ssl_buffer_size 1400; add_header Strict-Transport-Security max-age=15768000; ssl_stapling on; ssl_stapling_verify on; server_name lede.frp.okuka.com; access_log /data/wwwlogs/lede.frp.test.com_nginx.log combined; if ($ssl_protocol = "") { return 301 https://$host$request_uri; } location / { proxy_pass http://127.0.0.1:8080;#端口号一定要和frps.ini的vhost_http_port一致 proxy_set_header Host $host; proxy_set_header X-Real-IP 8.8.8.8;#这里填写你的公网服务器IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}注意!!!!!以上操作就能需要重启服务后才能使用 ...

April 25, 2019 · 1 min · jiezi

安卓手机微信7.0.4调试小程序抓包https请求失败的问题和解决

注意:阅读本文需要一台已经root的安卓手机!说明系统:MacOS 10.13.6手机:小米6(已root)抓包工具:Charles微信版本:7.0.4现象安卓手机无法通过Charles代理抓包https请求,我前天(2019年04月16日)用的7.0.3不知道为什么能抓到,昨天手残更新到7.0.4就不行了。而iOS(iPhone5S 12.1.4)没有问题。查找相关资料,都说微信升级到版本7之后就限制了用户证书凭据。根据网上较多的推荐方案,建议把证书放在系统证书存放目录下,那这就需要Root手机了,如果没有,以下内容不适合阅读。接下来,我尝试将Charles生成的证书放在手机的系统证书中,并没有那么顺利,很失败!我慢慢来讲解一下。步骤生成Charles证书我们要生成一个可以存放在系统证书目录下的可被识别的证书。手机代理设置好了后,手机访问:<chls.pro/ssl>下载下来证书,名称是这样的charles-proxy-ssl-proxying-certificate.pem(你把这个文件搞到电脑上,假设该证书存在电脑的路径:~/charles-proxy-ssl-proxying-certificate.pem)。在你的电脑终端通过这个命令生成一个hash值:openssl x509 -subject_hash_old -in ~/charles-proxy-ssl-proxying-certificate.pem可以看到输出了类似如下P750TM:webs whidy$ openssl x509 -subject_hash_old -in ~/certificate.pem 07e87b3d—–BEGIN CERTIFICATE—–MIIFYjCCBEqgAwIBAgIGAWeQpfWHMA…….77JclxPc0UdJHi5rOf7w+LU8YZFPdMTLa/c2JjMlspt08UeQVDE=—–END CERTIFICATE—–将证书更名07e87b3d.0注意后缀!接下来你可以用任意手段将该文件拷贝至手机的/system/etc/security/cacerts/目录,如果成功则再次尝试抓包,如果失败,请继续看。超级终端操作如果不嫌麻烦的话,你完全可以在安卓手机上面的超级终端(自行下载的工具)进行以下操作,但是我没有这样,我在MacOSX中启用adb连接操作手机,如果你正有此意,请按照我的方式操作。电脑终端执行以下命令(这里不介绍brew,不理解的自行学习)brew cask install android-platform-tools装好后,数据线连上手机,测试一下adb devices没报错,且大概出现以下信息则正常:List of devices attached* daemon not running; starting now at tcp:5037* daemon started successfullyfa8a05fd device然后获取root权限,尝试将文件07e87b3d.0拷贝到/system/etc/security/cacerts/adb root获得权限后,直接执行下面命令将证书放入系统目录。push ~/07e87b3d.0 /system/etc/security/cacerts/如果成功了,请尝试抓包。如果提示失败,比如权限不足,只读啥的,反正大概错误信息如下:P750TM:/ whidy$ adb push ~/07e87b3d.0 /system/etc/security/cacerts/adb: error: failed to copy ‘/Users/whidy/07e87b3d.0’ to ‘/system/etc/security/cacerts/07e87b3d.0’: remote couldn’t create file: Read-only file system/Users/whidy/07e87b3d.0: 0 files pushed. 0.0 MB/s (1947 bytes in 0.119s)那就要继续折腾了。网上抄到的chmod 777目前是不管用的。要通过mount的相关操作来解决这个问题。装载可写的system目录查看当前system目录挂载在哪里mount,可以得到大致如下:rootfs on / type rootfs (ro,seclabel,size=2828452k,nr_inodes=707113)tmpfs on /dev type tmpfs (rw,seclabel,nosuid,relatime,size=2912600k,nr_inodes=728150,mode=755)devpts on /dev/pts type devpts (rw,seclabel,relatime,mode=600)proc on /proc type proc (rw,relatime,gid=3009,hidepid=2)sysfs on /sys type sysfs (rw,seclabel,relatime)selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)/dev/block/dm-0 on /system type ext4 (ro,seclabel,relatime,discard,data=ordered)debugfs on /sys/kernel/debug type debugfs (rw,seclabel,relatime)none on /acct type cgroup (rw,relatime,cpuacct)none on /dev/stune type cgroup (rw,relatime,schedtune)tmpfs on /mnt type tmpfs (rw,seclabel,relatime,size=2912600k,nr_inodes=728150,mode=755,gid=1000)none on /config type configfs (rw,relatime)none on /dev/memcg type cgroup (rw,relatime,memory)注意到/dev/block/dm-0 on /system type ext4 (ro,seclabel,relatime,discard,data=ordered)这一行,后面括号有个ro,代表readonly!接下来尝试修改为可写(rw)状态:mount -o rw,remount /dev/block/dm-0 /system如果成功了,就试试将文件拷贝进去,失败了,例如提示:’/dev/block/dm-0’ is read-only,请继续阅读。这里参考Android O, failed to mount /system, /dev/block/dm-0 is read only,一顿操作!我这边是这样的:adb disable-verityadb reboot关闭验证是要重启设备的。执行重启后,继续:adb rootadb remountadb shell再执行mount发现结果跟刚才不一样了,找到有system的那一行发现这样的/dev/block/sde43 on /system type ext4 (rw,seclabel,relatime,discard,data=ordered)已经可写了,我试试拷贝进去。执行adb push /07e87b3d.0 /system/etc/security/cacerts/,出现以下结果:P750TM:/ whidy$ adb push /07e87b3d.0 /system/etc/security/cacerts//Users/whidy/07e87b3d.0: 1 file pushed. 0.1 MB/s (1947 bytes in 0.022s)应该就完成了。再去我的小米6手机里面的设置 > 更多设置 > 系统安全 > 加密与凭据 > 信任的凭据 > 系统里面看看,滚到最低部,ok,证书导入成功了。再去抓包看看我这文章是边写边记录的,现在可以看到https请求的抓包已经Ok啦最后我建议最后还原之前操作的disable-verity,这样操作一下:adb rootadb enable-verityadb reboot行了差不多就这些了。 ...

April 18, 2019 · 1 min · jiezi

如何在生产环境中重启Spring Boot应用?

通过HTTP重启Spring Boot应用程序需求背景在一个很奇葩的需求下,要求在客户端动态修改Spring Boot配置文件中的属性,例如端口号、应用名称、数据库连接信息等,然后通过一个Http请求重启Spring Boot程序。这个需求类似于操作系统更新配置后需要进行重启系统才能生效的应用场景。动态配置系统并更新生效是应用的一种通用性需求,实现的方式也有很多种。例如监听配置文件变化、使用配置中心等等。网络上也有很多类似的教程存在,但大多数都是在开发阶段,借助Spring Boot DevTools插件实现应用程序的重启,或者是使用spring-boot-starter-actuator和spring-cloud-starter-config来提供端点(Endpoint)的刷新。第一种方式无法在生产环境中使用(不考虑),第二种方式需要引入Spring Cloud相关内容,这无疑是杀鸡用了宰牛刀。接下来,我将尝试采用另外一种方式实现HTTP请求重启Spring Boot应用程序这个怪异的需求。尝试思路重启Spring Boot应用程序的关键步骤是对主类中SpringApplication.run(Application.class,args);方法返回值的处理。SpringApplication#run()方法将会返回一个ConfigurableApplicationContext类型对象,通过查看官方文档可以看到,ConfigurableApplicationContext接口类中定义了一个close()方法,可以用来关闭当前应用的上下文:package org.springframework.context;import java.io.Closeable;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.core.env.ConfigurableEnvironment;import org.springframework.core.io.ProtocolResolver;import org.springframework.lang.Nullable;public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {void close(); } 继续看官方源码,AbstractApplicationContext类中实现close()方法,下面是实现类中的方法摘要:public void close() { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.doClose(); if (this.shutdownHook != null) { try { Runtime.getRuntime().removeShutdownHook(this.shutdownHook); } catch (IllegalStateException var4) { ; } } } }#close()方法将会调用#doClose()方法,我们再来看看#doClose()方法做了哪些操作,下面是doClose()方法的摘要:protected void doClose() { if (this.active.get() && this.closed.compareAndSet(false, true)) { … LiveBeansView.unregisterApplicationContext(this); … this.destroyBeans(); this.closeBeanFactory(); this.onClose(); if (this.earlyApplicationListeners != null) { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } this.active.set(false); } }在#doClose()方法中,首先将应用上下文从注册表中清除掉,然后是销毁Bean工厂中的Beans,紧接着关闭Bean工厂。官方文档看到这里,就产生了解决一个结局重启应用应用程序的大胆猜想。在应用程序的main()方法中,我们可以使用一个临时变量来存放SpringApplication.run()返回的ConfigurableApplicationContext对象,当我们完成对Spring Boot应用程序中属性的设置后,调用ConfigurableApplicationContext的#close()方法,最后再调用SpringApplication.run()方法重新给ConfigurableApplicationContext对象进行赋值已达到重启的效果。现在,我们再来看一下SpringApplication.run()方法中是如何重新创建ConfigurableApplicationContext对象的。在SpringApplication类中,run()方法会调用createApplicationContext()方法来创建一个ApplicationContext对象:protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch(this.webApplicationType) { case SERVLET: contextClass = Class.forName(“org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext”); break; case REACTIVE: contextClass = Class.forName(“org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext”); break; default: contextClass = Class.forName(“org.springframework.context.annotation.AnnotationConfigApplicationContext”); } } catch (ClassNotFoundException var3) { throw new IllegalStateException(“Unable create a default ApplicationContext, please specify an ApplicationContextClass”, var3); } } return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass); }createApplicationContext()方法会根据WebApplicationType类型来创建ApplicationContext对象。在WebApplicationType中定义了三种种类型:NONE、SERVLET和REACTIVE。通常情况下,将会创建servlet类型的ApplicationContext对象。接下来,我将以一个简单的Spring Boot工程来验证上述的猜想是否能够达到重启Spring Boot应用程序的需求。编码实现首先,在application.properties文件中加入如下的配置信息,为动态修改配置信息提供数据:spring.application.name= SPRING-BOOT-APPLICATION接下来,在Spring Boot主类中定义两个私有变量,用于存放main()方法的参数和SpringApplication.run()方法返回的值。下面的代码给出了主类的示例:public class ExampleRestartApplication { @Value ( “${spring.application.name}” ) String appName; private static Logger logger = LoggerFactory.getLogger ( ExampleRestartApplication.class ); private static String[] args; private static ConfigurableApplicationContext context; public static void main(String[] args) { ExampleRestartApplication.args = args; ExampleRestartApplication.context = SpringApplication.run(ExampleRestartApplication.class, args); }}最后,直接在主类中定义用于刷新并重启Spring Boot应用程序的端点(Endpoint),并使用@RestController注解对主类进行注释。@GetMapping("/refresh")public String restart(){ logger.info ( “spring.application.name:"+appName); try { PropUtil.init ().write ( “spring.application.name”,“SPRING-DYNAMIC-SERVER” ); } catch (IOException e) { e.printStackTrace ( ); } ExecutorService threadPool = new ThreadPoolExecutor (1,1,0, TimeUnit.SECONDS,new ArrayBlockingQueue<> ( 1 ),new ThreadPoolExecutor.DiscardOldestPolicy ()); threadPool.execute (()->{ context.close (); context = SpringApplication.run ( ExampleRestartApplication.class,args ); } ); threadPool.shutdown (); return “spring.application.name:"+appName;}说明:为了能够重新启动Spring Boot应用程序,需要将close()和run()方法放在一个独立的线程中执行。为了验证Spring Boot应用程序在被修改重启有相关的属性有没有生效,再添加一个获取属性信息的端点,返回配置属性的信息。@GetMapping("/info”)public String info(){ logger.info ( “spring.application.name:"+appName); return appName;}完整的代码下面给出了主类的全部代码:package com.ramostear.application;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.io.IOException;import java.util.concurrent.*;/** * @author ramostear */@SpringBootApplication@RestControllerpublic class ExampleRestartApplication { @Value ( “${spring.application.name}” ) String appName; private static Logger logger = LoggerFactory.getLogger ( ExampleRestartApplication.class ); private static String[] args; private static ConfigurableApplicationContext context; public static void main(String[] args) { ExampleRestartApplication.args = args; ExampleRestartApplication.context = SpringApplication.run(ExampleRestartApplication.class, args); } @GetMapping("/refresh”) public String restart(){ logger.info ( “spring.application.name:"+appName); try { PropUtil.init ().write ( “spring.application.name”,“SPRING-DYNAMIC-SERVER” ); } catch (IOException e) { e.printStackTrace ( ); } ExecutorService threadPool = new ThreadPoolExecutor (1,1,0, TimeUnit.SECONDS,new ArrayBlockingQueue<> ( 1 ),new ThreadPoolExecutor.DiscardOldestPolicy ()); threadPool.execute (()->{ context.close (); context = SpringApplication.run ( ExampleRestartApplication.class,args ); } ); threadPool.shutdown (); return “spring.application.name:"+appName; } @GetMapping("/info”) public String info(){ logger.info ( “spring.application.name:"+appName); return appName; }}接下来,运行Spring Boot程序,下面是应用程序启动成功后控制台输出的日志信息:[2019-03-12T19:05:53.053z][org.springframework.scheduling.concurrent.ExecutorConfigurationSupport][main][171][INFO ] Initializing ExecutorService ‘applicationTaskExecutor’[2019-03-12T19:05:53.053z][org.apache.juli.logging.DirectJDKLog][main][173][INFO ] Starting ProtocolHandler [“http-nio-8080”][2019-03-12T19:05:53.053z][org.springframework.boot.web.embedded.tomcat.TomcatWebServer][main][204][INFO ] Tomcat started on port(s): 8080 (http) with context path ‘’[2019-03-12T19:05:53.053z][org.springframework.boot.StartupInfoLogger][main][59][INFO ] Started ExampleRestartApplication in 1.587 seconds (JVM running for 2.058)在测试修改系统配置并重启之前,使用Postman测试工具访问:http://localhost:8080/info ,查看一下返回的信息:成功返回SPRING-BOOT-APPLICATION提示信息。然后,访问:http://localhost:8080/refresh ,设置应用应用程序spring.application.name的值为SPRING-DYNAMIC-SERVER,观察控制台输出的日志信息:可以看到,Spring Boot应用程序已经重新启动成功,最后,在此访问:http://localhost:8080/info ,验证之前的修改是否生效:请求成功返回了SPRING-DYNAMIC-SERVER信息,最后在看一眼application.properties文件中的配置信息是否真的被修改了:配置文件的属性也被成功的修改,证明之前的猜想验证成功了。本次内容所描述的方法不适用于以JAR文件启动的Spring Boot应用程序,以WAR包的方式启动应用程序亲测可用。┏ (^^)=☞目前该药方副作用未知,如有大牛路过,还望留步指点迷津,不胜感激。结束语本次内容记录了自己验证HTTP请求重启Spring Boot应用程序试验的一次经历,文章中所涉及到的内容仅代表个人的一些观点和不成熟的想法,并未将此方法应用到实际的项目中去,如因引用本次内容中的方法应用到实际生产开发工作中所带来的风险,需引用者自行承担因风险带来的后遗症(→←)——此药方还有待商榷(O_o)(o_O)。原文作者:谭朝红原文标题:如何在生产环境中重启Spring Boot应用? ...

April 13, 2019 · 2 min · jiezi

前端应该知道的http

作为互联网通信协议的一员老将,HTTP 协议走到今天已经经历了三次版本的变动,现在最新的版本是 HTTP2.0,相信大家早已耳熟能详。今天就给大家好好介绍一下 HTTP 的前世今生。1、http的历史简介先简单的介绍一下,后面再具体详解1.1、HTTP/0.9HTTP 的最早版本诞生在 1991 年,这个最早版本和现在比起来极其简单,没有 HTTP 头,没有状态码,甚至版本号也没有,后来它的版本号才被定为 0.9 来和其他版本的 HTTP 区分。HTTP/0.9 只支持一种方法—— Get,请求只有一行。GET /hello.html响应也是非常简单的,只包含 html 文档本身。<HTML>Hello world</HTML>当 TCP 建立连接之后,服务器向客户端返回 HTML 格式的字符串。发送完毕后,就关闭 TCP 连接。由于没有状态码和错误代码,如果服务器处理的时候发生错误,只会传回一个特殊的包含问题描述信息的 HTML 文件。这就是最早的 HTTP/0.9 版本。1.2、HTTP/1.01996 年,HTTP/1.0 版本发布,大大丰富了 HTTP 的传输内容,除了文字,还可以发送图片、视频等,这为互联网的发展奠定了基础。相比 HTTP/0.9,HTTP/1.0 主要有如下特性:请求与响应支持 HTTP 头,增加了状态码,响应对象的一开始是一个响应状态行协议版本信息需要随着请求一起发送,支持 HEAD,POST 方法支持传输 HTML 文件以外其他类型的内容 一个典型的 HTTP/1.0 的请求像这样:GET /hello.html HTTP/1.0User-Agent:NCSA_Mosaic/2.0(Windows3.1)200 OKDate: Tue, 15 Nov 1996 08:12:31 GMTServer: CERN/3.0 libwww/2.17Content-Type: text/html<HTML>一个包含图片的页面<IMGSRC="/smile.gif"></HTML>1.3、HTTP/1.1在 HTTP/1.0 发布几个月后,HTTP/1.1 就发布了。HTTP/1.1 更多的是作为对 HTTP/1.0 的完善,在 HTTP1.1 中,主要具有如下改进:可以复用连接增加 pipelinechunked 编码传输引入更多缓存控制机制引入内容协商机制请求消息和响应消息都支持 Host 头域新增了 OPTIONS,PUT, DELETE, TRACE, CONNECT 方法1.4、 HTTPSHTTPS 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。HTTPS 协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。 HTTPS 和 HTTP 的区别主要如下:HTTPS 协议使用 ca 申请证书,由于免费证书较少,需要一定费用。HTTP 是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。HTTP 和 HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。1.5、SPDY在 2010 年到 2015 年,谷歌通过实践一个实验性的 SPDY 协议,证明了一个在客户端和服务器端交换数据的另类方式。其收集了浏览器和服务器端的开发者的焦点问题,明确了响应数量的增加和解决复杂的数据传输。在启动 SPDY 这个项目时预设的目标是:页面加载时间 (PLT) 减少 50%。无需网站作者修改任何内容。将部署复杂性降至最低,无需变更网络基础设施。与开源社区合作开发这个新协议。收集真实性能数据,验证这个实验性协议是否有效。为了达到降低目标,减少页面加载时间的目标,SPDY 引入了一个新的二进制分帧数据层,以实现多向请求和响应、优先次序、最小化及消除不必要的网络延迟,目的是更有效地利用底层 TCP 连接。1.6、 HTTP/2.0时间来到 2015 年,HTTP/2.0 问世。先来介绍一下 HTTP/2.0 的特点吧:使用二进制分帧层多路复用数据流优先级服务端推送头部压缩2、http原理详解HTTP协议是构建在TCP/IP协议之上的,是TCP/IP协议的一个子集,所以要理解HTTP协议,有必要先了解下TCP/IP协议相关的知识。2.1 TCP/IP协议TCP/IP协议族是由一个四层协议组成的系统,这四层分别为:应用层、传输层、网络层和数据链路层分层的好处是把各个相对独立的功能解耦,层与层之间通过规定好的接口来通信。如果以后需要修改或者重写某一个层的实现,只要接口保持不变也不会影响到其他层的功能。接下来,我们将会介绍各个层的主要作用。1) 应用层应用层一般是我们编写的应用程序,其决定了向用户提供的应用服务。应用层可以通过系统调用与传输层进行通信。处于应用层的协议非常多,比如:FTP(File Transfer Protocol,文件传输协议)、DNS(Domain Name System,域名系统)和我们本章讨论的HTTP(HyperText Transfer Protocol,超文本传输协议)等。2) 传输层传输层通过系统调用向应用层提供处于网络连接中的两台计算机之间的数据传输功能。在传输层有两个性质不同的协议:TCP(Transmission Control Protocol,传输控制协议)和UDP(User Data Protocol,用户数据报协议)。3) 网络层网络层用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(传输路线)到达对方计算机,并把数据包传输给对方。IP协议4) 链路层链路层用来处理连接网络的硬件部分,包括控制操作系统、硬件设备驱动、NIC(Network Interface Card,网络适配器)以及光纤等物理可见部分。硬件上的范畴均在链路层的作用范围之内。数据包封装上层协议数据是如何转变为下层协议数据的呢?这是通过封装(encapsulate)来实现的。应用程序数据在发送到物理网络之前,会沿着协议栈从上往下传递。每层协议都将在上层协议数据的基础上加上自己的头部信息(链路层还会加上尾部信息),以为实现该层功能提供必要的信息.发送端发送数据时,数据会从上层传输到下层,且每经过一层都会被打上该层的头部信息。而接收端接收数据时,数据会从下层传输到上层,传输前会把下层的头部信息删除.由于下层协议的头部信息对上层协议是没有实际的用途,所以在下层协议传输数据给上层协议的时候会把该层的头部信息去掉,这个封装过程对于上层协议来说是完全透明的。这样做的好处是,应用层只需要关心应用服务的实现,而不用管底层的实现。TCP三次握手从上面的介绍可知,传输层协议主要有两个:TCP协议和UDP协议。TCP协议相对于UDP协议的特点是:TCP协议提供面向连接、字节流和可靠的传输。第一次握手:客户端发送带有SYN标志的连接请求报文段,然后进入SYN_SEND状态,等待服务端的确认。第二次握手:服务端接收到客户端的SYN报文段后,需要发送ACK信息对这个SYN报文段进行确认。同时,还要发送自己的SYN请求信息。服务端会将上述的信息放到一个报文段(SYN+ACK报文段)中,一并发送给客户端,此时服务端将会进入SYN_RECV状态。第三次握手:客户端接收到服务端的SYN+ACK报文段后,会想服务端发送ACK确认报文段,这个报文段发送完毕后,客户端和服务端都进入ESTABLISHED状态,完成TCP三次握手。当三次握手完成后,TCP协议会为连接双方维持连接状态。为了保证数据传输成功,接收端在接收到数据包后必须发送ACK报文作为确认。如果在指定的时间内(这个时间称为重新发送超时时间),发送端没有接收到接收端的ACK报文,那么就会重发超时的数据。2.2、 DNS 域名解析当你在浏览器的地址栏输入 https://juejin.im 后会发生什么,大家在心中肯定是有一个大概的,这里我将 DNS 域名解析 这个步骤详细的讲一遍。在讲概念之前我先放上一张经典的图文供大家思考一分钟。查找域名对应的 IP 地址的具体过程浏览器搜索自己的 DNS 缓存(浏览器维护一张域名与 IP 地址的对应表);如果没有命中,进入下一步;搜索操作系统中的 DNS 缓存;如果没有命中,进入下一步;搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);如果没有命中,进入下一步;列表项目操作系统将域名发送至 LDNS (本地区域名服务器),LDNS 查询自己的 DNS 缓存(一般命中率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求:LDNS向 Root Name Server(根域名服务器,如com、net、im 等的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 im 域的顶级域名服务器的地址;LDNS 向 im 域的顶级域名服务器发起请求,返回 juejin.im 域名服务器地址;LDNS 向 juejin.im 域名服务器发起请求,得到 juejin.im 的 IP 地址;LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来。http工作的简单过程地址解析: 这一步比较重要的是上面的DNS解析封装HTTP请求数据包: 把以上部分结合本机自己的信息,封装成一个HTTP请求数据包封装成TCP包,建立TCP连接(TCP的三次握手)客户机发送请求命令服务器响应服务器关闭TCP连接2.3、http请求方法一些常见的http请求方法。GET: 用于获取数据POST: 用于将实体提交到指定的资源,通常导致状态或服务器上的副作用的更改HEAD: 与GET请求的响应相同的响应,但没有响应体PUT: 用于创建或更新指定资源DELETE: 删除指定的资源关于get与post的一些区别。可以看我的另一篇文章面试经典之http中get与post的区别2.4、 http缓存http很重要的一点还有他的缓存机制。关于这部分的内容可以看一下我之前的文章浏览器缓存看这一篇就够了。这里就不在赘述了。2.5、状态码这里主要讲一些常用的状态码1、 301 永久转移当你想换域名的时候,就可以使用301,如之前的域名叫www.renfed.com,后来换了一个新域名fed.renren.com,希望用户访问老域名的时候能够自动跳转到新的域名,那么就可以使用nginx返回301:server { listen 80; server_name www.renfed.com; root /home/fed/wordpress; return 301 https://fed.renren.com$request_uri;}浏览器收到301之后,就会自动跳转了。搜索引擎在爬的时候如果发现是301,在若干天之后它会把之前收录的网页的域名给换了。还有一个场景,如果希望访问http的时候自动跳转到https也是可以用301,因为如果直接在浏览器地址栏输入域名然后按回车,前面没有带https,那么是默认的http协议,这个时候我们希望用户能够访问安全的https的,不要访问http的,所以要做一个重定向,也可以使用301,如:server { listen 80; server_name fed.renren.com; if ($scheme != “https”) { return 301 https://$host$request_uri; } }2、302 Found 资源暂时转移很多短链接跳转长链接就是使用的302,如下图所示:3、304 Not Modified 没有修改这个主要在上面的缓存哪里出现的比较多。如果服务器没有修改。就会使用浏览器的缓存。4、400 Bad Request 请求无效当必要参数缺失、参数格式不对时,后端通常会返回400,如下图所示:5、403 Forbidden 拒绝服务服务能够理解你的请求,包括传参正确,但是拒绝提供服务。例如,服务允许直接访问静态文件,但是不允许访问某个目录:否则,别人对你服务器上的文件就一览无遗了。403和401的区别在于,401是没有认证,没有登陆验证之类的错误。6、500 内部服务器错误如业务代码出现了异常没有捕获,被tomcat捕获了,就会返回500错误:如:数据库字段长度限制为30个字符,如果没有判断直接插入一条31个字符的记录,就会导致数据库抛异常,如果异常没有捕获处理,就直接返回500。当服务彻底挂了,连返回都没有的时候,那么就是502了。7、502 Bad Gateway 网关错误这种情况是因为nginx收到请求,但是请求没有打过去,可能是因为业务服务挂了,或者是打过去的端口号写错了8、504 Gateway Timeout 网关超时通常是因为服务处理请求太久,导致超时,如PHP服务默认的请求响应最长处理时间为30s,如果超过30s,将会挂掉,返回504,如下图所示:2.6、HTTP的基本优化影响一个HTTP网络请求的因素主要有两个:带宽和延迟。带宽如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。延迟1、浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。2、DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。3、建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大http的发展也就是在不断地优化这些方向上的问题。3、http1.1HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别主要体现在:缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。虽然 HTTP/1.1 已经优化了很多点,作为一个目前使用最广泛的协议版本,已经能够满足很多网络需求,但是随着网页变得越来越复杂,甚至演变成为独立的应用,HTTP/1.1 逐渐暴露出了一些问题:在传输数据时,每次都要重新建立连接,对移动端特别不友好传输内容是明文,不够安全header 内容过大,每次请求 header 变化不大,造成浪费keep-alive 给服务端带来性能压力 为了解决这些问题,HTTPS 和 SPDY 应运而生。4、HTTPSHTTPS 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。5、SPDY:HTTP1.x的优化2012年google如一声惊雷提出了SPDY的方案,优化了HTTP1.X的请求延迟,解决了HTTP1.X的安全性,具体如下:降低延迟,针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率。请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。header压缩。前面提到HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。基于HTTPS的加密协议传输,大大提高了传输数据的可靠性。服务端推送(server push),采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。SPDY构成图:SPDY位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTTP协议(将HTTP1.x的内容封装成一种新的frame格式),同时可以使用已有的SSL功能。6、HTTP2.0HTTP2.0可以说是SPDY的升级版(其实原本也是基于SPDY设计的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,如下:HTTP2.0和SPDY的区别:HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPSHTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATEHTTP/2 新特性6.1、二进制传输HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。接下来我们介绍几个重要的概念:流:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2…N);消息:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。帧:HTTP 2.0 通信的最小单位,每个帧包含帧首部,至少也会标识出当前帧所属的流,承载着特定类型的数据,如 HTTP 首部、负荷,等等HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。6.2、多路复用在 HTTP/2 中引入了多路复用的技术。多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2中:同域名下所有通信都在单个连接上完成。单个连接可以承载任意数量的双向数据流。数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。这一特性,使性能有了极大提升:同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,消除了因多个 TCP 连接而带来的延时和内存消耗。并行交错地发送多个请求,请求之间互不影响。并行交错地发送多个响应,响应之间互不干扰。在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。如上图所示,多路复用的技术可以只通过一个 TCP 连接就可以传输所有的请求数据。6.3、Header 压缩在 HTTP/1 中,我们使用文本的形式传输 header,在 header 携带 cookie 的情况下,可能每次都需要重复传输几百到几千的字节。为了减少这块的资源消耗并提升性能, HTTP/2对这些首部采取了压缩策略:HTTP/2在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值例如下图中的两个请求, 请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销6.4、服务端推送(Server Push)Server Push即服务端能通过push的方式将客户端需要的内容预先推送过去,也叫“cache push”。可以想象以下情况,某些资源客户端是一定会请求的,这时就可以采取服务端 push 的技术,提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。后续更多文章将在我的github第一时间发布,欢迎关注。参考HTTP协议详解前端词典】进阶必备的网络基础我知道的HTTP请求一文读懂HTTP/2 及 HTTP/3特性 ...

April 12, 2019 · 2 min · jiezi

vue-cli3 开启HTTPS

项目里边准备试试html5的录音。然后调研一波,发现大坑:必须使用HTTPS才能录音。然后就想着本地模拟HTTPS录音。项目用的vue-cli3,折腾一波,发现开启非常简单:创建配置文件 项目根目录新建 vue.config.js 文件。粘贴代码module.exports = { devServer: { https: true }}不过,好像模拟的假的HTTPS,调用api还是会报错。然后太过麻烦,放弃这个录音feature。

April 10, 2019 · 1 min · jiezi

???? 如何用 wireshark 抓包 TLS 封包

此前一篇文章用 wireshark 这个抓包工具调试了一下 HTTP 请求和响应。详细阐述了 TCP 连接和断开的整个过程。这篇文章尝试使用 wireshark 来抓取 TLS 封包,了解一下 HTTPS 请求和响应的整个过程。 ????懒得看全文的直接拉到最下看 TLS 流程的图片解释首先准备好 curl 和 wireshark,这些谷歌一下怎么安装。 ????HTTPS 是基于 TLS 之上的,如果没有目标的私钥是没办法解密的,如果直接使用 wireshark 是看不到 TLS 层加密的信息的。打开 wireshark 并开启抓包,在 curl 中发送一个请求:再 wireshark 输入 tls 过滤请求,疑似 ip 地址为目标网站输入该 ip 地址,确认是目标网站 httpbin,然后尝试查看返回的数据信息,因为 TLS 加密是看不到返回的 JSON 数据的因 TLS 使用的是迪菲 - 赫尔曼密钥交换生成对称密钥的加密算法,因此需要获取到一系列生成密钥的必要信息后才可生成密钥解密数据。先不着急怎么解决这个问题,首先回顾一下几个知识点,大概了解一下加密算法和 CA 数字证书和 TLS 加密流程:必要的几个知识点 ????加密算法 ????远古以前用的是对称加密,这种加密和解密的密钥是同一个,因此极为不安全,一旦其中一个密钥泄露,那么就会导致加密文件被破解后来发明了非对称加密,这种加密方式的逻辑就是公钥用来加密,私钥用来解密,一方使用另一方的公钥进行加密,传输密文给另一方,另一方再用私钥进行解密,这样没有拿到私钥就无法解密密文。但这种加密解密效率较低,后来就衍生出了混合加密,这种加密方式综合了非对称加密和对称加密。混合加密首先使用非对称加密生成对称密钥,然后再使用对称密钥进行数据安全传输,这样加密解密的效率要高得多了。TLS 用到的迪菲 - 赫尔曼就是其中的一种关于迪菲 - 赫尔曼密钥交换算法,这里简单提一下,这种算法有几个特点:密钥可以合成但不能分解合成后的密钥可以继续再合成合成后的密钥结果与合成顺序无关本质上是一种生成密钥算法这个算法的加密流程是这样的:A 和 B 想要交换并生成对称密钥A 将 P 发送给 BA 使用 P 和自己的私钥 SA 合成 PSAB 使用 P 和自己的私钥 SB 合成 PSB双方交换 PSA 和 PSBA 使用私钥 SA 与 PSB 合成 PSBSAB 使用私钥 SB 与 PSA 合成 PSASB这样对称密钥 PSASB 和 PSBSA 就合成完毕了,双方就可以使用这个对称密钥对传输的数据进行加密 ????⚠️ 问题是 A 将 P 发送给 B,B 如何确认 P 就是真的来自 A 的呢,而不是受到中间人攻击篡改了 P,这就需要使用 CA 认证了,只要有 CA 认证后的数字签名并且通过 CA 的公钥能够验证那么就可以确认 P 就是来自 A 的。数字证书 ????因此这里提一下 CA 证书也简单提一下原理:一个网站 A 想要获取数字证书,那么要走如下流程:A 将网站信息和公钥 PA 发送给 CA 认证机构CA 认证机构验证网站信息并用自己的私钥 SCA 加密生成数字签名,并回传给 AA 收到的数字签名中就包含了 A 的公钥 PA,那么其他人只需要通过 CA 认证机构的公钥即可认证解密数字签名,获取数字签名中的公钥 PA 了那么其他人就可以确定 PA 确实是来自 A 的这样 A 的公钥 PA 就可以被认为确实是来自 A 的,因为有 CA 签发的数字证书认证和背书。 ????⚠️ 还有一个问题是 CA 的公钥谁来认证呢?要是 CA 的公钥也被恶意替换了怎么办?那么就需要 CA 的 CA 来认证了,那么 CA 的 CA 的公钥谁来认证?根据这个逻辑,最后有一个 root CA,这个 CA 用来做最后的权威鉴定。TLS 加密流程 ????最后来回顾一下 TLS 的加密流程TLS 是建立在 TCP 基础上的,因此必定需要先三次 TCP 握手建立 TCP 连接,然后再是建立 TLSClient HelloClient Hello 报文:客户端对加密算法的支持度不同,因此需要向服务端发送客户端支持的 加密套件(Cipher Suite) ,同时还要生成一个 随机数 同时保存在客户端和发送给服务Server HelloServerCertificate 报文:服务端收到 Client Hello 之后,向客户端发送 CA 认证的数字证书,用来鉴别服务端身份信息,同时还要生成一个 随机数 同时保存在服务端和发送给客户端Server Hello Done 报文:表示服务端宣告第一阶段的客户端服务端握手协商结束可选:Certificate Request 报文:必要情况下,要求客户端发送证书验证身份可选:Server Key Exchange 报文:如果 CA 认证的数字证书提供的信息不够,服务端还可发送提供补充信息Client FinishClient Key Exchange 报文:客户端收到 CA 数字证书并通过验证,然后通过 CA 公钥解密获取到 服务端公钥。Client Key Exchange 报文包括有一个随机数,这个随机数被称为 Pre-master key/secret;一个表示随后的信息使用双方协商好的加密方法和密钥发送的 通知 ;还有一个通过协商好的 HASH 算法对前面所有信息内容的 HASH 计算值,用来提供服务端校验。这些信息都通过服务端公钥加密传送给服务端ClientCipherSpec 报文:该报文通知服务端,此后的通信都将使用协商好的加密算法计算对称密钥进行加密通信(也就是使用两个随机数以及第三个 Pre-master key/secret 随机数一起算出一个对称密钥 session key/secret)Finished 报文:该报文包括连接至此的所有报文的校验值,使用服务端公钥进行加密可选:ClientCertificate 报文:如果服务端请求,客户端需要发送 CA 数字证书可选:CertificateVerify 报文:服务端如果要求 CA 数字证书,那么需要通过 HASH 算法计算一个服务端发送来的信息摘要Server Finish服务端最后对客户端发送过来的 Finished 报文使用服务端私钥进行解密校验ClientCipherSpec 报文:报文通知服务端,此后的通信都将使用协商好的加密算法计算对称密钥 session key/secret 进行加密通信Finished 报文:标志 TLS 连接建立成功TLS 握手成功此后通过对称密钥 session key/secret 加密通信以上,我们看到生成的两个随机数和 Pre-master key 一起计算生成 session key 就是通过上文中提到过的迪菲 - 赫尔曼密钥交换算法实现的。客户端收到 CA 数字证书获取到服务端公钥进行加密,也符合上文中提到的 CA 认证流程。服务端私钥解密客户端使用服务端公钥加密,在上文中的非对称密钥部分也进行了讲解。因此 TLS 是一个运用到多种认证、加密的安全传输技术。除此之外,上文中没有提到的使用 HASH 计算的目的则是为了防止数据遭到篡改,这跟我们大家在网上下载软件,计算 md5 校验是一个原理。⚠️ 如有不正确的地方,各位请在评论区指正谢谢最后抓包验证上述加密流程 ????首先上文提到过 wireshark 直接抓取 TLS 的封包是没办法看到解密后的数据的,那么我们需要通过一些手段获取到解密后的数据那么如何才能解密获取数据呢,这里有篇文章可以看看 https://jimshaver.net/2015/02...It turns out that Firefox and Chrome both support logging the symmetric session key used to encrypt TLS traffic to a file. You can then point Wireshark at said file and presto! decrypted TLS traffic.原理是浏览器会在系统中存在名为 SSLKEYLOGFILE 的环境变量已经设置的情况下,将每个 HTTPS 连接产生的客户端或服务端的随机数、preMasterSecret、MasterSecret 全部获取到并保存在这个环境变量指定的文件中。配置环境变量 ????开始动手实操,这里用的是 windows 系统,我们配置环境变量:配置完成,这样浏览器就会写入密钥信息到指定路径的文件中至于 macOS/Linux 自己谷歌一下如何设置环境变量,很简单不再赘述配置 wireshark ????打开 wireshark,点击配置信息指定 TLS 的 Pre-master key 路径为环境变量指定的那个文件路径这样配置就算完成了,我们尝试一下打开 chrome 浏览器访问一个 https 网址:这里访问了百度的首页,可以看到 wireshark 展现的已经是解密后的数据了开始抓包分析 TLS 握手流程 ????然后打开终端使用 curl 发送一个 https 请求还是以 httpbin 为例,过滤 http 查看 wireshark 的结果:右键 follow 一下这就是整个 TCP 建立到 TLS 握手再到 HTTP 请求响应以及 TCP 断开的整个过程,我们逐一分析一下:TCP 的此前文章已经说过了,这里也不再提了,直接看 TLS 部分:Client HelloClient Hello 阶段,客户端给服务端发送一个随机数,以及 Cipher Suites 客户端支持的所有加密套件Server HelloServer Hello 阶段,服务端给客户端发送一个随机数,以及选中的 Cipher Suite 加密套件然后服务端继续发送给客户端 CA 数字证书以及 Server Key Exchange 和 Hello done 信息完成第一阶段的握手:这个是证书:这个是 Server Key Exchange,可以看到协商了一种加密算法:这个是 Server Hello Done:Client Finish客户端发送一个 Client Key Exchange,Change Cipher Spec 和 Finished 报文Finished Verify Data 包括至此连接的所有报文的校验信息,用服务端提供的公钥加密客户端准备好切换为对称密钥加密Server Finish最后服务端返回一个 Change Cipher Spec 和 Server Finish服务端准备好切换为对称密钥加密TLS 握手成功至此,TLS 握手成功,在 wireshark 中就可以看到接下来就是 HTTP 的请求响应封包了:图片解释 ????最后画了个简化版的脑图方便理解:⚠️ 如有不正确的地方,各位请在评论区指正谢谢请关注我的订阅号,不定期推送有关 JS 的技术文章,只谈技术不谈八卦 ???? ...

April 2, 2019 · 2 min · jiezi

47道HTTP面试题总结(长期更新)

写在前面参考答案在看云平台发布,如果大家想阅读参考答案,可直接购买。一次购买,文档所有部分(vue、http、js等)均可以观看,无时间限制,文档长期更新!有什么意见与建议欢迎您及时联系作者或留言回复!阅读文档 98道vue面试题加入前端开发交流微信群,获取更多资源:本文档基于前端所需要掌握的网络协议知识,总结了:网络基础Http协议HTTP状态码与HTTP协作的 Web 服务器HTTP首部HTTPSSPDY协议websock协议HTTP 2.0等9个关于计算机网络方面的前端面试题。必须掌握问题:输入 URL 到页面渲染的整个流程参考答案: https://www.kancloud.cn/hanxu…网络基础1、什么是TCP/IP协议族2、TCP/IP协议族按层次划分了哪几次?3、TCP/IP协议族各层的作用是什么?4、请画出并说明HTTP请求时,TCP/IP通信传输流5、网络层:IP协议6、TCP协议位于哪一层?7、什么是字节流服务?8、TCP头部有哪些重要字段?9、TCP协议的三次握手10、为什么 TCP 建立连接需要三次握手,明明两次就可以建立起连接?11、UDP 与 TCP 的区别是什么?12、什么是ARQ协议?13、什么是滑动窗口?14、拥塞怎么处理?15、什么是DNS服务?16、什么是RFC?参考答案: https://www.kancloud.cn/hanxu...Http协议1、HTTP请求报文由哪几部分组成?2、HTTP协议的状态3、HTTP方法有哪些?4、GET和POST方法有什么区别的实操回答。5、什么是TCP的持久化连接?6、HTTP是如何利用Cookie进行状态管理的?7、在ajax请求中如何使用Cookie?8、在ajax请求中使用Cookie时,如何解决跨越问题?9、 HTTP报文有哪几种,HTTP报文包含哪写部分?10、常见的状态码有哪些?参考答案: https://www.kancloud.cn/hanxu…与HTTP协作的 Web 服务器1、代理2、网关3、隧道参考答案: https://www.kancloud.cn/hanxu...HTTP首部1、什么是HTTP首部字段2、HTTP首部字段有哪几种类型?3、通用首部字段有哪些?4、请求首部字段有哪些?5、响应首部字段有哪些?6、实体首部字段有哪些?7、非HTTP/1.1 首部字段8、为Cookie服务的首部字段有哪些?9、其他首部字段参考答案: https://www.kancloud.cn/hanxu...HTTPS1、HTTP的缺点有哪些?2、什么是HTTPS3、HTTPS是如何进行加密的?4、HTTPS的通信步骤是什么?5、相比HTTP,HTTPS有哪些缺点?参考答案: https://www.kancloud.cn/hanxu…基于HTTP的功能追加协议1、什么是SPDY协议2、什么是webSocket协议?3、webSocket有什么特点?4、HTTP/2.0 协议的新特性参考答案: https://www.kancloud.cn/hanxu…

April 2, 2019 · 1 min · jiezi

HTTP(S)

原文链接最近又看了一遍 [HTTP权威指南],每次想写一份总结的时候都会拖延症爆发,今天决定总结下我们每天都在接触的HTTP。OSI (Open System Interconnect)先列一张能够体现不同协议在OSI七层模型中的表格层级层级名称应用7应用层例如HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP、TLS6表示层例如XDR、ASN.1、SMB、AFP、NCP5会话层例如ASAP、ISO 8327 / CCITT X.225、RPC、NetBIOS、ASP、IGMP、Winsock、BSD sockets4传输层例如TCP、UDP、RTP、SCTP、SPX、ATP、IL3网络层例如IP、ICMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.252数据链路层例如以太网、令牌环、HDLC、帧中继、ISDN、ATM、IEEE 802.11、FDDI、PPP1物理层例如线路、无线电、光纤先从 TCP/IP 说起IPS(Internet Protocol Suite)又叫做互联网协议套件、是一套网络传输协议家族,也就是我们熟悉的TCP/IP协议族,(又因为TCP、IP为不同层级的协议,当多个层级的协议共同工作时类似计算机科学中的堆栈、所以又叫做TCP/IP协议栈)TCP/IP 中包含一系列用于处理数据通信的协议TCP (传输控制协议) - 应用程序之间通信UDP (用户数据报协议) - 应用程序之间的简单通信IP (网际协议) - 计算机之间的通信ICMP (因特网消息控制协议) - 针对错误和状态DHCP (动态主机配置协议) - 针对动态寻址这里要说一下TCP、HTTP、socket的关系实际上socket只是一个Api,方便我们去调用底层封装好的TCP/IP协议,但是socket与TCP/IP并没有必然的关系,socket接口在设计的时候就希望也能够适应其他协议,而HTTP是基于TCP之上的应用层协议,有一个很有趣的比喻就是如果TCP是高速路,那么HTTP就是高速路上的货车。好,下面重头戏来了,TCP三次握手(建立连接)四次挥手(断开连接)客户端 - Client、 服务端 - Server 两个整型变量 J、K三次握手(建立连接)Server socket绑定端口,等待消息(first) Client 打开socket(connect) 、发送 SYN J(second) Server 收到消息,向客户端发送 SYN K、 ack J+1(third) Client 收到应答、发送 ack K+1Server 开始读取Client发送的信息至此、连接建立完成、这里有一个问题,为什么建立连接不是2次握手、为什么不是4次握手?恰好是三次的原因是三次刚刚好,4次浪费网络资源没必要,而如果改为2次,那么client在向server发送第一次握手的时候因为某些原因舍弃了这次连接(或是因其他原因被迫强制关闭)而并没有通知Server,那么如果只需要2次握手无疑会造成server会一直处于盲等状态。四次挥手(连接拆除)三个整型变量 x、y、z与建立连接不同的是、断开连接可以由任意一方发起主动方发送fin=1、ack=z、seq=x被动方发送ack=x+1、seq=z被动方发送fin=1、ack=x、seq=y主动方发送ack=y、seq=x那么,为何挥手要挥4次呢,原因在于拆除连接时收到fin报文,仅仅代表对方不再发送数据,而接收到fin报文的一方可能还有数据没发送完,所以被动方的fin和ack要分开发送。HTTP 连接那么什么是HTTP连接呢,所谓HTTP,就是基于TCP/IP协议的上层应用层协议,所以我们可以理解HTTP连接就是以TCP/IP为传输层协议,以HTTP协议作为应用层协议的连接就比如我们在浏览器输入 https://k.felixplus.top/ 、会先通过 TCP握手建立连接,这个时候传输的数据会通过HTTP协议进行解析,最后到达我们的浏览器进行绘制展示HTTPSHTTPS = HTTP + (TLS/SSL)其中,TLS/SSL 为 HTTP 提供了安全加密传输的功效相比之下,HTTPS比HTTP多提供了以下几点:数据完整性:内容传输经过完整性校验数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥身份认证:第三方无法伪造服务端(客户端)身份那么,HTTPS的一次传输过程是怎样的呢,先说结论:Server 被动监听Client 发送连接请求Server 返回公钥Client 生成随机值(对称加密的私钥)通过Server返回的公钥加密Client 将密文发送回Server 并等待确认双方开始使用客户端生成的对称加密密钥进行通讯在继续之前我们需要先来回顾一下什么是对称加密,什么是非对称加密:对称方式加密方法风险加解密速度非对称数据的加解密由一个密钥解决风险较高加解密速度快对称数据使用公钥加密、私钥解密风险较小加解密速度慢从这里不难看出,HTTPS同时使用到对称加密和非对称加密的原因是如果数据传输量很大,一直使用非对称加密会消耗更多资源,产生不必要的浪费,而在传输数据之前先通过非对称加密发送客户端生成的私钥在安全性能上足以胜任,所以这里并没有完全使用非对称加密。下面是使用 curl 命令debug HTTPS 请求的输出curl -v https://aground.felixplus.top* Rebuilt URL to: https://aground.felixplus.top/* Trying 47.75.98.166…* TCP_NODELAY set* Connected to aground.felixplus.top (47.75.98.166) port 443 (#0)* ALPN, offering h2* ALPN, offering http/1.1* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH* successfully set certificate verify locations:* CAfile: /etc/ssl/cert.pem CApath: none* TLSv1.2 (OUT), TLS handshake, Client hello (1):* TLSv1.2 (IN), TLS handshake, Server hello (2):* TLSv1.2 (IN), TLS handshake, Certificate (11):* TLSv1.2 (IN), TLS handshake, Server key exchange (12):* TLSv1.2 (IN), TLS handshake, Server finished (14):* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):* TLSv1.2 (OUT), TLS change cipher, Client hello (1):* TLSv1.2 (OUT), TLS handshake, Finished (20):* TLSv1.2 (IN), TLS change cipher, Client hello (1):* TLSv1.2 (IN), TLS handshake, Finished (20):* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305* ALPN, server accepted to use h2* Server certificate:* subject: CN=aground.felixplus.top* start date: Feb 15 10:01:34 2019 GMT* expire date: May 16 10:01:34 2019 GMT* subjectAltName: host “aground.felixplus.top” matched cert’s “aground.felixplus.top”* issuer: C=US; O=Let’s Encrypt; CN=Let’s Encrypt Authority X3* SSL certificate verify ok.* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0* Using Stream ID: 1 (easy handle 0x7feef980b800)> GET / HTTP/2> Host: aground.felixplus.top> User-Agent: curl/7.54.0> Accept: />* Connection state changed (MAX_CONCURRENT_STREAMS updated)!< HTTP/2 200< server: nginx/1.14.0 (Ubuntu)< date: Mon, 25 Mar 2019 07:13:40 GMT< content-type: text/html< content-length: 2121< last-modified: Tue, 19 Mar 2019 09:57:48 GMT< vary: Accept-Encoding< etag: “5c90bd1c-849”< accept-ranges: bytes<* Connection #0 to host aground.felixplus.top left intact<!doctype html><html lang=“en”><head><meta charset=“utf-8”/><link rel=“shortcut icon” href="/panda.png"/><meta name=“viewport” content=“width=device-width,initial-scale=1,shrink-to-fit=no”/><meta name=“theme-color” content="#000000"/><link rel=“manifest” href="/manifest.json"/><title>AGround</title><link href="/static/css/2.4126af51.chunk.css" rel=“stylesheet”><link href="/static/css/main.85ae910b.chunk.css" rel=“stylesheet”></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id=“root”></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r–,1),e=f(f.s=t[0]))}return e}var t={},p={1:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){“undefined”!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:“Module”}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&“object”==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,“default”,{enumerable:!0,value:r}),2&e&&“string”!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,“a”,r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/2.5167ae78.chunk.js"></script><script src="/static/js/main.05967284.chunk.js"></script></body></html>% ...

March 31, 2019 · 2 min · jiezi

如何在Tomcat中做TLS客户端认证

常见的https网站做的是服务端认证(server authentication),浏览器通过证书判断你所访问的https://baidu.com是否真的是百度,而不是其他人伪造的网站。同时还对流量加密,防止别人窃听你的流量。tls还可以做客户端认证(client authentication),即服务端判断客户端是否为其所信任的客户端。由此可见,客户端认证用于那些需要受控访问服务端。在数据中心中,有些服务是非常敏感的,那么我们要做到:客户端和我的流量是加密的,防止别人监听客户端能够确认所访问的服务端的确是我们提供的服务端,而不是别人伪造的服务端只有我信任的客户端可以访问我,防止恶意请求所以很明显,前两个问题可以通过服务端认证解决,最后一个问题可以通过客户端认证解决。顺便一提,如果要使用客户端认证就必须使用服务端认证。先来讲讲概念然后举个tomcat的例子讲讲怎么做。概念服务端认证不论是做Server authentication还是Client authentication都需要证书。证书的来源有两种:由权威CA签发,一般都是去购买。也可以使用let’s encrypt申请免费证书。自己签发在一切可能的情况下都应该使用权威CA签发的证书,为什么这么建议?因为这里牵涉到一个信任问题,浏览器、编程语言SDK和某些工具都维护了一个信任CA证书清单,只要是由这些CA签发的证书那就信任,否则就不信任。而这个链条是可以多级的,这里就不展开了。你只需要知道由信任CA签发的所有证书都是可信的。比如JDK自带的信任CA证书可以通过下面命令看到:keytool -list -keystore $JAVA_HOME/jre/lib/security/cacertsverisignclass2g2ca [jdk], 2016-8-25, trustedCertEntry,证书指纹 (SHA1): B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9Ddigicertassuredidg3 [jdk], 2016-8-25, trustedCertEntry,证书指纹 (SHA1): F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89verisignuniversalrootca [jdk], 2016-8-25, trustedCertEntry,…让你输密码的时候输入changeit。如果这个证书不是由信任CA签发的(比如自己签发)会发生什么?浏览器、编程语言SDK、你所使用的工具会报告以下错误:curl:curl: (60) SSL certificate problem: self signed certificate in certificate chainJava: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 at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)…浏览器:这个错误实际上就是在告诉你这个证书不可信任,可能是一个伪造站点,让你小心点儿。如果这个证书由权威CA签发,那么就没有这个问题了。但是权威CA签发的证书要求申请人拥有域名,如果你这个服务是内部使用的没有域名,那就只能自己签发了。那么如何解决上面的问题呢?你得把自己签发的证书加入到信任CA证书清单里。下图是权威CA签发证书的示例:可以看到客户端有一个truststore,这个就是存放信任CA证书的地方,服务端有一个keystore,存放的自己的证书及对应的私钥。下图是自签发证书的示例:在上面可以看到我们自己成为了一个Root CA,把它放到客户端的truststore里。客户端认证前面讲过客户端认证是服务端来验证客户端是否可信的机制,其实做法和服务端认证类似只不过方向相反。客户端认证大多数情况下只能是自签发的(因为没有域名),虽然不是不可以从权威CA签发但是存在一些问题。下面解释为什么,假设权威CA是let’s encrypt,然后服务端信任它签发的所有证书。但是let’s encrypt是阿猫阿狗都可以申请的,现在有一个黑客申请了这个证书,然后请求你的服务端,服务端就认可了。上面这个问题可以用这个方法解决:比如你用let’s encrypt申请了A证书,黑客用let’s encrypt申请了B证书,你的服务端的truststore只信任A证书,那么黑客用B证书访问你的时候就会被拒绝。但是这就带来另一个问题,比如你在开发的时候客户端证书有这么几套:生产用、调试用、开发用,那么每次客户端签发一个证书都要更新到你的服务器的truststore里,这也太麻烦了。所以结合安全性和便利性,我们把自己变成Root CA,然后服务端信任它,这样一来服务端就可以在开发的时候把Client Root CA内置进去,大大减轻了维护truststore的工作量,看下图:用Tomcat举个例子下面举一个Tomcat做客户端认证的例子,因为是测试用,所以服务端认证也是用的自签发证书。我们用了cfssl这个工具来生成证书。服务端先弄一套目录:# 放自签发的服务端CA根证书server-secrets/ca# 放自签发的服务端的证书server-secrets/cert# 放服务端的keystore和truststoreserver-secrets/jks生成自签名CA证书新建文件:server-secrets/ca/server-root-ca-csr.json内容如下:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “server-root-ca”}运行下面命令生成Server ROOT CA证书:cfssl gencert –initca=true ./server-root-ca-csr.json | cfssljson –bare server-root-ca会得到下面几个文件:server-secrets/ca/├── server-root-ca-key.pem├── server-root-ca.csr└── server-root-ca.pem用下面命令验证证书:openssl x509 -in ./server-root-ca.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 0c:8a:1a:ca:da:fa:4c:17:6c:1f:42:40:4c:f1:90:f4:fd:1d:fe:58 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca Validity Not Before: Mar 27 05:14:00 2019 GMT Not After : Mar 25 05:14:00 2024 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca可以看到签发人和被签发人是同一个。生成自签发证书新建文件 server-secrets/cert/server-gencert.json,内容如下:{ “signing”: { “default”: { “usages”: [ “signing”, “key encipherment”, “server auth” ], “expiry”: “87600h” } }}可以看到我们会生成用来做server auth的证书。新建文件 server-secrets/cert/demo-csr.json,内容如下:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “server-demo”, “hosts”: [ “127.0.0.1”, “localhost” ]}看上面的hosts,你可以根据自己的需要填写域名或IP,这里因为是本地演示所以是127.0.0.1和localhost。运行下面命令生成证书cfssl gencert \ –ca ../ca/server-root-ca.pem \ –ca-key ../ca/server-root-ca-key.pem \ –config ./server-gencert.json \ ./demo-csr.json | cfssljson –bare ./demo得到文件:server-secrets/cert/├── demo-key.pem├── demo.csr└── demo.pem验证结果:openssl x509 -in ./demo.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 1d:d0:51:97:6c:ce:ea:29:2a:f4:3b:3c:48:a3:69:b0:ef:f3:26:7b Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca Validity Not Before: Mar 27 05:17:00 2019 GMT Not After : Mar 24 05:17:00 2029 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-demo可以看到签发者是server-root-ca,Subject是server-demo。将证书导入keystore到 server-secrets/jks,执行下面命令生成pkcs12格式的keystore(JDK识别这个格式)openssl pkcs12 -export \ -in ../cert/demo.pem \ -inkey ../cert/demo-key.pem \ -out server-demo.keystore \ -name server-demo \ -CAfile ../ca/server-root-ca.pem \ -caname root -chain过程中会让你输入密码,你就输入:server-demo-ks。得到文件:server-secrets/jks/└── server-demo.keystore用JDK提供的keytool看看里面的内容:keytool -list -keystore server-demo.keystoreserver-demo, 2019-3-27, PrivateKeyEntry,证书指纹 (SHA1): B2:E5:46:63:BB:00:E7:82:48:A4:2F:EC:01:41:CE:B4:4B:CE:68:7A让你输入密码的时候就输入:server-demo-ks。客户端先弄一套目录:# 放自签发的客户端CA根证书client-secrets/ca# 放自签发的客户端的证书client-secrets/cert# 放客户端的keystore和truststoreclient-secrets/jks生成自签名CA证书新建文件 client-secrets/ca/client-root-ca-csr.json:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “client-root-ca”}运行下面命令生成Client ROOT CA证书:cfssl gencert –initca=true ./client-root-ca-csr.json | cfssljson –bare client-root-ca会得到下面几个文件:client-secrets/ca/├── client-root-ca-key.pem├── client-root-ca.csr└── client-root-ca.pem用下面命令验证证书:openssl x509 -in ./client-root-ca.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 7e:fc:f3:53:07:1a:17:ae:24:34:d5:1d:00:02:d6:e4:24:09:92:12 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca Validity Not Before: Mar 27 05:20:00 2019 GMT Not After : Mar 25 05:20:00 2024 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca可以看到签发人和被签发人是同一个。生成自签发证书新建文件 client-secrets/cert/client-gencert.json,内容如下:{ “signing”: { “default”: { “usages”: [ “signing”, “key encipherment”, “client auth” ], “expiry”: “87600h” } }}可以看到我们会生成用来做client auth的证书。新建文件 client-secrets/cert/demo-csr.json,内容如下:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “client-demo”}这里没有hosts,这是因为我们不需要用这个证书来做服务端认证。运行下面命令生成证书cfssl gencert \ –ca ../ca/client-root-ca.pem \ –ca-key ../ca/client-root-ca-key.pem \ –config ./client-gencert.json \ ./demo-csr.json | cfssljson –bare ./demo得到文件:client-secrets/cert/├── demo-key.pem├── demo.csr└── demo.pem验证结果:openssl x509 -in ./demo.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 6e:50:e2:2c:02:bb:ef:fd:03:d9:2c:0a:8f:ba:90:65:fb:c4:b5:75 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca Validity Not Before: Mar 27 05:21:00 2019 GMT Not After : Mar 24 05:21:00 2029 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-demo可以看到签发者是client-root-ca,Subject是client-demo。将证书导入keystore到 client-secrets/jks,执行下面命令生成pkcs12格式的keystore(JDK识别这个格式)openssl pkcs12 -export \ -in ../cert/demo.pem \ -inkey ../cert/demo-key.pem \ -out client-demo.keystore \ -name client-demo \ -CAfile ../ca/client-root-ca.pem \ -caname root -chain过程中会让你输入密码,你就输入:client-demo-ks。得到文件:client-secrets/jks/└── client-demo.keystore用JDK提供的keytool看看里面的内容:keytool -list -keystore client-demo.keystoreclient-demo, 2019-3-27, PrivateKeyEntry,证书指纹 (SHA1): 83:AE:0E:5E:0C:CE:86:C9:D1:84:D7:6F:87:F3:76:1F:B4:3E:46:31让你输入密码的时候就输入:client-demo-ks。两端互信好了,到此为止server和client的证书都已经生成了,接下来只需要将各自的root-ca添加到彼此都truststore中。把server-root-ca导入到client的truststore中cd client-secrets/jkskeytool -importcert \ -alias server-root-ca \ -storetype pkcs12 \ -keystore client.truststore \ -storepass client-ts \ -file ../../server-secrets/ca/server-root-ca.pem -noprompt注意上面的-storepass参数,这个是trustore的密码:client-ts。得到文件:client-secrets/jks/└── client.truststore用JDK提供的keytool看看里面的内容:keytool -list -keystore client.truststoreserver-root-ca, 2019-3-27, trustedCertEntry,证书指纹 (SHA1): 75:E3:78:97:85:B2:29:38:25:3C:FD:EC:68:97:9B:78:A0:5F:BB:9D让你输入密码的时候就输入:client-ts。把client-root-ca导入到server的truststore中cd server-secrets/jkskeytool -importcert \ -alias client-root-ca \ -storetype pkcs12 \ -keystore server.truststore \ -storepass server-ts \ -file ../../client-secrets/ca/client-root-ca.pem -noprompt注意上面的-storepass参数,这个是trustore的密码:server-ts。得到文件:server-secrets/jks/└── server.truststore用JDK提供的keytool看看里面的内容:keytool -list -keystore server.truststoreclient-root-ca, 2019-3-27, trustedCertEntry,证书指纹 (SHA1): 1E:95:2C:12:AA:7E:6D:E7:74:F1:83:C2:B8:73:6F:EE:57:FB:CA:46让你输入密码的时候就输入:server-ts。配置Tomcat好了,我们现在client和server都有了自己证书放在了自己的keystore中,而且把彼此的root-ca证书放到了自己的truststore里。现在我们弄一个tomcat作为server,然后为他配置SSL。修改tomcat/conf/server.xml,添加如下Connector:<Connector port=“8443” protocol=“org.apache.coyote.http11.Http11NioProtocol” maxThreads=“150” SSLEnabled=“true”> <SSLHostConfig certificateVerification=“required” truststoreFile="/path/to/server-secrets/jks/server.truststore" truststorePassword=“server-ts” truststoreType=“PKCS12”> <Certificate certificateKeyAlias=“server-demo” certificateKeystoreFile="/path/to/server-secrets/demo-jks/server-demo.keystore" certificateKeystoreType=“PKCS12” certificateKeystorePassword=“server-demo-ks” type=“RSA” /> </SSLHostConfig></Connector>可以看到我们开启了客户端认证certificateVerification=“required”,也开启了服务端认证<Certificate>。记得修改上面的keystore和truststore的路径。修改tomcat/conf/web.xml,添加如下元素:<security-constraint> <web-resource-collection> <web-resource-name>Automatic Forward to HTTPS/SSL</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint></security-constraint>这个作用是当访问8080端口时,都跳转到8443端口,强制走HTTPS。启动tomcat:tomcat/bin/catalina.sh run用curl测试好了,我们现在用curl来测试访问一下:curl https://localhost:8443/curl: (60) SSL certificate problem: self signed certificate in certificate chain…看到curl说服务端用的是一个自签发的证书,不可信,也就是说服务端认证失败。添加–insecure试试:curl –insecure https://localhost:8443/curl: (35) error:1401E412:SSL routines:CONNECT_CR_FINISHED:sslv3 alert bad certificate这里就说明客户端认证失败。所以如果要正确访问得像下面这样,指定server-root-ca证书,以及客户端自己签发的证书及private key:curl –cacert server-secrets/ca/server-root-ca.pem \ –key client-secrets/cert/demo-key.pem \ –cert client-secrets/cert/demo.pem \ https://localhost:8443/<!DOCTYPE html><html lang=“en”>…Httpclient测试我们现在用Httpclient来访问看看。pom.xml中添加依赖:<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.7</version></dependency>Java代码,记得把文件路径改掉:import org.apache.http.HttpEntity;import org.apache.http.HttpException;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;import javax.net.ssl.SSLContext;import java.io.File;import java.io.IOException;public class Client { public static void main(String[] args) throws Exception { SSLContext sslcontext = SSLContexts.custom() .loadTrustMaterial( new File("/path/to/client-secrets/demo-jks/client.truststore"), “client-ts”.toCharArray() ) .loadKeyMaterial( new File("/path/to/client-secrets/demo-jks/client-demo.keystore"), “client-demo-ks”.toCharArray(), “client-demo-ks”.toCharArray()) .build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); CloseableHttpClient httpclient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); HttpGet httpGet = new HttpGet(“https://localhost:8443”); CloseableHttpResponse response = httpclient.execute(httpGet); try { System.out.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); System.out.println(EntityUtils.toString(entity)); } finally { response.close(); } }}安全性考虑所有private key都很重要!如果它被泄漏了,就要回收它所对应都证书。如果CA的private key泄漏了,那么用它签发的所有证书都要被回收。keystore和truststore的密码设置的要复杂一些。关于反向代理因为服务端认证所需要的证书直接配置在Tomcat上的,因此在做反向代理的时候不能使用SSL Termination模式,而是得使用SSL Passthrough模式。其他语言、SDK、工具上面讲的方法不是只适用于Tomcat和Httpclient的,TLS的服务端认证与客户端认证应该在绝大部分的语言、SDK、类库都有支持,请自行参阅文档实践。文中的keystore和truststore是Java特有的,不过不必迷惑,因为它们仅仅起到一个存放证书和private key的保险箱,有些语言或工具则是直接使用证书和private key,比如前面提到的curl。参考资料cfsslSSL/TLS Configuration HOW-TOSSL SupportCONFIGURING TOMCAT SSL CLIENT/SERVER AUTHENTICATION,这篇文章有点古老了,server.xml的配置方式已经不一样了,仅供参考。ClientCustomSSL.javaJSSE Reference Guide一些基础概念:Basics of Digital Certificates and Certificate Authority,基础概念,挺重要Create Your Own Certificate and CA,这篇文章挺重要的,主要讲了如何使用keytool和openssl来生成证书的过程Introducing TLS with Client AuthenticationThe magic of TLS, X509 and mutual authentication explained其他运用客户端认证的软件的相关文档,很有启发:Etcd - Play etcd TLS部分Etcd - Example 2: Client-to-server authentication with HTTPS client certificatesCoreos - Generate self-signed certificates ...

March 28, 2019 · 4 min · jiezi

why https ?

Foreword不知道有没有同学和我一样,在网上看https的资料总是觉得好像讲的不详细或者经不起推敲,甚至在书本中,也看的云里雾里,稍微到了关键的地方,就被跳过不介绍了。自己好像懂了,诶,好像又没懂。反正我当初是憋了好一段时间 (〒︿〒)因此,为了避免新手别像本王一样走弯,本王放弃了看动漫的时间,下定决心写一篇关于https的文章。原文why https ?github上看排版更好。Whathttps在MDN上的定义:HTTPS (安全的HTTP)是 HTTP 协议的加密版本。它通常使用 SSL 或者 TLS 来加密客户端和服务器之前所有的通信 。这安全的链接允许客户端与服务器安全地交换敏感的数据,例如网上银行或者在线商城等涉及金钱的操作。SSL和TLS的区别:大体上说白了,没什么区别。就是TLS是IETF的标准化,SSL不是,而且会被历史给能慢慢淘汰。值得一提的是SSL 3.0开始,便引入了前向安全性,为了不一开始就让各位困扰,前向安全会在后面介绍。Why那为什么要是用https呢?自然因为安全啦。那http怎么就不安全了呢?接下来就让我们一起来看看吧:小灰是客户端,小灰的同事小红是服务端,有一天小灰试图给小红发送请求。但是,由于传输信息是明文,这个信息有可能被某个中间人恶意截获甚至篡改。这种行为叫做中间人攻击。如何进行加密呢?小灰和小红可以事先约定一种对称加密方式,并且约定一个随机生成的密钥。后续的通信中,信息发送方都使用密钥对信息加密,而信息接收方通过同样的密钥对信息解密。这样做是不是就绝对安全了呢?并不是。虽然我们在后续的通信中对明文进行了加密,但是第一次约定加密方式和密钥的通信仍然是明文,如果第一次通信就已经被拦截了,那么密钥就会泄露给中间人,中间人仍然可以解密后续所有的通信内容。这可怎么办呢?别担心,我们可以使用非对称加密,为密钥的传输做一层额外的保护。非对称加密的一组秘钥对中,包含一个公钥和一个私钥。明文既可以用公钥加密,用私钥解密;也可以用私钥加密,用公钥解密。在小灰和小红建立通信的时候,小红首先把自己的公钥Key1发给小灰:收到小红的公钥以后,小灰自己生成一个用于对称加密的密钥Key2,并且用刚才接收的公钥Key1对Key2进行加密,发送给小红:小红利用自己非对称加密的私钥,解开了公钥Key1的加密,获得了Key2的内容。从此以后,两人就可以利用Key2进行对称加密的通信了。在通信过程中,即使中间人在一开始就截获了公钥Key1,由于不知道私钥是什么,也无从解密。那这样做是不是就绝对安全了呢?同样不是。中间人虽然不知道小红的私钥是什么,但是在截获了小红的公钥Key1之后,却可以偷天换日,自己另外生成一对公钥私钥,把自己的公钥Key3发送给小灰。小灰不知道公钥被偷偷换过,以为Key3就是小红的公钥。于是按照先前的流程,用Key3加密了自己生成的对称加密密钥Key2,发送给小红。这一次通信再次被中间人截获,中间人先用自己的私钥解开了Key3的加密,获得Key2,然后再用当初小红发来的Key1重新加密,再发给小红。那怎么办呢?难道再把公钥进行一次加密吗?这样只会陷入鸡生蛋蛋生鸡,永无止境的困局。这时候,我们有必要引入第三方,一个权威的证书颁发机构(CA)来解决。接下来,也是开始正真的进入https的详解了。How证书的生成权威的证书颁发机构(CA)是做什么的?简单的说,就是发安全证书的,而且受全世界认可,相信它绝不造假,安全可靠。用户通过申请,填写相关资料,然后花点钱,就能获得CA下发的安全证书。我们介绍下具体的流程:生成密钥和证书签名请求此部分使用 openssl 命令行程序(大部分 Linux、BSD 和 Mac OS X 系统均附带此程序)来生成私钥/公钥和 CSR(证书签名请求 )。生成一个公钥/私钥对用于生成 RSA 密钥对的命令为:openssl genrsa -out www.example.com.key 2048生成CSR(证书签名请求)命令:openssl req -new -sha256 -key www.example.com.key -out www.example.com.csr将 CSR 提交给证书颁发机构对于不同的证书颁发机构 (CA),需要使用不同的方法将 CSR 发送给他们。 这些方法可能包括在其网站上使用表单、以电子邮件或其他方式发送 CSR。 一些 CA(或其经销商)甚至可能将其中部分或全部流程自动化(在某些情况下,包括密钥对和 CSR 的生成)。将 CSR 发送给 CA 并按照他们的说明接收最终证书或证书链。关于收费:对于为您的公钥进行证实的服务,不同 CA 的收费将有所不同。还可以选择将密钥映射到多个 DNS 名称,包括多个独立名称(例如 example.com、www.example.com、example.net 和 www.example.net 的全部)或“通配符”名称(例如 *.example.com)。例如,某个 CA 目前提供以下价格:标准:16 美元/年,适用于 example.com 和 www.example.com。通配符:150 美元/年,适用于 example.com 和 *.example.com。对称加密的密钥生成证书包含如下信息:对于已经双方都有私钥以后的事情,想必同学们都已经经过之前的训练非常清楚了。所以我们只需要重点介绍服务端和客户端进行对称加密的时候的密钥是怎么生成就可以了。我们来看看整个用https信息交互的流程:第一种方式:第二种方式:图中生成对称密钥的流程已经很清楚了。另外提一下,我们需要知道,目前有两对密钥:一对是服务端生成的公私钥另一对是CA自己的公私钥服务端的私钥只在服务端存着;服务端的公钥在证书里面;CA的私钥只在CA机构那边存着(可想而知,要是CA的私钥被泄露了,那基本这个CA机构也就破产了);CA的公钥和证书一起预置了在各个操作系统里。为了流程图更清晰,图中忽略了客户端用CA的公钥解密证书中服务端的公钥和签名的过程。回过头来,有个问题是,为什么有两种方式?这就得提到之前说过的前向安全性了。它们主要的区别就是生成对称密钥的算法,图1是RSA,图2则是DH。什么是RSA?C随机选取一个master key(即对称加密的密钥) ,用S 的公钥加密,S解密,得到明文的master key,剩下过程和DH算法类似!什么是DH?S为server端,C为client端:S 筛选出自己的素数对 S1、S2;C 筛选出自己的素数对 C1、C2;S与C交换各自的S2、C2;S拥有了S1、C2,DH可以算出一个master key;C拥有了C1、S2,DH可以算出一个master key;两个master key 完全一样。这就是神奇的DH算法!任何第三方都无法根据截获的S2、C2算出master key。Summary最终,我们通过http中遇到的种种问题,到一步步的想办法解决,再到后来的走投无路,最终引入了https。然后又学习了https加密的整个过程,以及https早期的前向安全问题的解决方案。想必,同学们已经对https有了更深入的了解了。参考资料HTTPS可以防止中间人篡改内容吗?在服务器上启用 HTTPSTLS/SSL 高级进阶漫画:什么是 HTTPS 协议? ...

March 27, 2019 · 1 min · jiezi

HTTP精简教程二:简单的HTTP协议

HTTP协议HTTP协议和TCP/IP协议族内的其他众多协议相同,用于客户端和服务器之间的通信。请求访问资源的一端为客户端,响应资源的一端为服务器。请求必须从客户端发出,而服务器回复响应,因此建立通信是从客户端开始的。请求报文POST /index.htm HTTP/1.1Host: hackr.jpConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 16 name=ueno&age=25报文说明方法POSTURI/index.htm协议版本HTTP/1.1请求首部字段Host: hackr.jpConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 16内容实体name=ueno&age=25响应报文HTTP/1.1 200 OKDate: Tue, 10 Jul 2012 06:50:15 GMTContent-Length: 363Content-Type: text/html <html>…报文说明协议版本HTTP/1.1 200 OK状态码200状态码的原因短语OK响应首部字段Date: Tue, 10 Jul 2012 06:50:15 GMTContent-Length: 363Content-Type: text/html主体<html>…HTTP是不保存状态的协议为了更快的处理大量的事物,确保协议的伸缩性,因此把HTTP协议设为无状态协议;为此,引入Cookie技术保存用户的登陆状态。HTTP请求方法GET:获取资源GET方法用来请求访问已被URI识别的资源。POST:传输实体主体虽然GET方法和POST方法都可以用来传输实体,但一般不用GET方法。GET与POST的区别方法GETPOST本质索取数据提交数据安全性低高执行效率高低机制将参数拼接在url上,明文传输将表单内各个字段与其内容放置在HTML HEADER内一起传送到action属性所指的URL地址大小取决于浏览器和系统理论上没有限制,取决于浏览器和系统地址栏输入支持不支持浏览器历史记录保留参数参数不保留编码方式url编码多种编码方式PUT:传输文件PUT方法用来传输文件,类似FTP协议文件上传,请求的报文中包含文件内容,然后保存在URI指定位置。但是HTTP/1.1的PUT方法不带验证机制,任何人都能上传文件,存在安全性问题,慎用。HEAD:获取报文首部类似GET方法,区别在于只返回报文首部,不返回报文主体。DELETE:删除文件与PUT方法相反,用来删除文件,DELETE方法按请求URI删除指定资源。但是HTTP/1.1的DELETE方法同样不带验证机制,存在安全性问题,慎用。区别OPTIONS:询问支持方法返回服务器支持的方法TRACE:追踪路径CONNECT:要求用隧道协议连接代理持久连接旨在建立1次TCP连接后进行多次请求和响应的交互,在HTTP/1.1中默认都是持久连接

March 19, 2019 · 1 min · jiezi

HTTP/2的优势

HTTP2 协议的目标是保持HTTP/1.x向后的语义兼容的情况下,降低网络延迟,提高传输效率。相比于HTTP/1.x,它具备以下提高网络传输性能的新特性:多路复用允许通过一个单一的HTTP/2连接来发起多重请求。这个特性使得我们需要针对HTTP/1.x做的线头阻塞优化(css sprite, inline image)变得多余。也就是说在HTTP/2协议中,我们可以不再需要将多个请求合并为一个单一的请求,来减少多次建立连接带来的延迟。首部压缩首部压缩移除了一些啰嗦的首部,减少传输的数据服务端推送对于一个请求,可以有多个响应。其中的一个场景是,当客户端请求一个html文件的时候,服务端除了响应html文件之外,还可以向客户端推送这个html中可能使用到的css,js,image文件。避免不必要的round trip。服务端推送的一个问题就是,服务端有时可能重复推送客服端缓存的内容,造成多余的传输数据。其中的一个解决办法是,客户端增加一个Cache Digest 来告诉服务端哪些内容是缓存的。加密传输HTTP/2协议的内容是经过非对称加密的图解HTTPS 协议加密HTTP/1.x的keep-alivekeep-alive 允许设置空闲连接超时时长和最大连接数。一个包含keep-alive的响应头如下:HTTP/1.1 200 OKConnection: Keep-AliveContent-Encoding: gzipContent-Type: text/html; charset=utf-8Date: Thu, 11 Aug 2016 15:23:13 GMTKeep-Alive: timeout=5, max=1000Last-Modified: Mon, 25 Jul 2016 04:32:39 GMTServer: Apache(body)如上,表示该连接最大空闲时间为5ms,并且该连接所能允许的最大请求数为1000。超过1000个请求之后,自动断开连接。这个有点像HTTP/2中的多路复用。虽然他们都是复用一个连接来完成多次请求,但是其实他们是有区别的。在HTTP/1.x中在一个连接中发送多个请求必须是有序的,也就是说必须是请求1完成了才能发送请求2。假设请求1的响应需要等待比较长的操作(IO操作,数据库拆查询),那么在等待的这段时间中,服务器到客户端的链路中是没有数据传输的,我们希望的在请求1等待响应的这段时间中,能够传输一些请求2的内容。这样,整体的传输时间就会减少。在HTTP/2中,数据都被拆分成了帧,在客户端或者服务端中,通过帧信息来重新组合一个请求的完整数据。这就解决了上述的问题。参考:HTTP/2.0 相比1.0有哪些重大改进?HTTP/2 对现在的网页访问,有什么大的优化呢?体现在什么地方?keep-alive

March 11, 2019 · 1 min · jiezi

搞搞, 超星尔雅;

前奏目前正在读书的兄弟们, 一定很熟悉超星尔雅, 没错就是那个,看视屏不能快进的超星尔雅;不爱学习的我, 怎么能被这个耽误时间, 因此今天, 我们来,试试能不能跳过, 视频。正文尝试一一开始我们先试试, 能不能从video入手, 结果可想而知。 调动currentTime 视频会自动跳转到开始。尝试二不能调动进度条,那肯定是某个函数的功能,此方法不通。 但我们这样想,视频放完肯定要,发送数据给,超星的服务器,ok, 打开fiddler开始抓包。我们在想, 那发送放完的 数据肯定,是在视频最后, 所以第一个视频,在放到最后的时候。 我发现了这个可疑的接口, /multimedia/log/a/ ,就搞它, 打开form 可以看到playingTime, 这大概就是播放时间了吧,内心有些小激动,再看看下面server返回的JSON { isPassed=False } 当然,这大概就是判断视频是否确定了接口 ok 打开postman, 来模拟个包。把刚才fiddler 的链接复制上去。 postman 会自动解析?XX=XX& 把playTime 设置成 当时视频的时长=<video/>.duration先把cookie 全部带上, (因为不确定,cookie的功能)发送包, 但结果发现, server返回了405,这时我们把POST方法换成get/head 结果什么都没有返回返回网页, 发现任务点变成了已完成, 但视频还没放完。 刷新一下,还是一样。就这样^_^

February 24, 2019 · 1 min · jiezi

使用acme.sh撸一个免费且自动更新的HTTPS证书

前言一直想撸一下https,最近刚好有点空,就实现了一下。之前看过一篇教你快速撸一个免费HTTPS证书的文章,通过Certbot来管理Let’s Encrypt的证书,使用前需要安装一堆库,觉得不太友好。所谓条条大路通罗马,肯定还有其他方法可以做这个事情。经过一番研究,发现了 acme.sh 这个库,这个是用Shell脚本编写的,不需要安装其他东西,比较纯净,觉得比较适合自己,记录一下过程。准备工作一个已解析好的域名(可以用http来访问)。开启服务器的443端口防火墙。步骤一、安装acme.shcurl https://get.acme.sh | sh这个命令后会将acme.sh安装到~/.acme.sh/目录下重新载入~/.bashrcsource ~/.bashrc 二、生成证书acme.sh –issue -d www.your-domin.com –webroot /srv/your-domin.com/这个命令的意思是用http方式将www.your-domin.com生成一个证书,/srv/your-domin.com/是你的网站根目录。(这个过程中acme.sh 会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证. 最后又自动删除验证文件.)三、安装或copy证书到nginx目录默认生成的证书都放在安装目录下: ~/.acme.sh/,这个目录一般来说不能让nginx或Apache直接使用。所以我们需要将证书放到一个指定的目录,习惯是放在/etc/nginx/ssl/目录下。acme提供了–installcert来安装证书,只需指定目标位置, 然后证书文件会被copy到相应的位置。先确保存在/etc/nginx/ssl/目录mkdir /etc/nginx/sslcopy证书并指定nginx reload命令acme.sh –installcert -d www.your-domin.com \ –key-file /etc/nginx/ssl/www.your-domin.com.key \ –fullchain-file /etc/nginx/ssl/fullchain.cer \ –reloadcmd “service nginx force-reload"service nginx force-reload是为了在让acme自动更新时候能够重启nginx使得证书生效。执行完命令可以在/etc/nginx/ssl/看到多了www.your-domin.com.key和www.your-domin.com.cer的文件。四、生成 dhparam.pem 文件openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048这一步不是必须,但最好加上,后面配置好后会通过ssllabs.com 来验证一下,如果这一步ssl_dhparam 未配置,将导致 ssllabs.com 的评分降到 B。A+是最好。五、配置nginx证书已安装完毕,接下来就是让nginx来使用这个证书了。由于我这个服务器有几个站点,而目前只是一个站点配置了证书,因此只修改当前站点的conf即可server { listen 80; server_name www.your-domin.com; listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; ssl_certificate /etc/nginx/ssl/www.your-domin.com.cer; ssl_certificate_key /etc/nginx/ssl/www.your-domin.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/ssl/dhparam.pem; …}ssl_prefer_server_ciphers on; 这个配置能提高证书的评分。ssl_dhparam /etc/nginx/ssl/dhparam.pem; 能提高证书评分,这个文件是在第四步时生成的,若没有做则不需要写这句。nginx -t验证一下nginx配置是否正确,然后systemctl restart nginx重启一下nginx,就可以用https://www.your-domin.com测…。六、证书更新Let’s Encrypt 的证书有效期是 90 天的,需要定期重新申请,不过acme在安装的时候就已经设置了自动更新,所以这一步不用关心,很省心。这里了解一下acme.sh的自动更新:安装acme时会自动为你创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书.查看任务# crontab -l47 0 * * * “/root/.acme.sh”/acme.sh –cron –home “/root/.acme.sh” > /dev/null手动renew一下证书可以通过这个命令acme.sh –cron -f七、设置软件自动更新目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.所以为了省心省力,最好还是设置一下软件的自动更新,执行下面的命令就可以了。acme.sh –upgrade –auto-upgrade其他在这个网站可以验证一下你的证书级别,根据我上面的配置可以评级为A。https://www.ssllabs.com/sslte…参考文章acme.sh说明使用 acme.sh 给 Nginx 安装 Let’ s Encrypt 提供的免费 SSL 证书让你的网站免费开启Https访问,绿色健康小清新 ...

February 22, 2019 · 1 min · jiezi

https的那些事儿

什么是HTTPSHTTPS = HTTP + TLSTLS是一种安全传输协议,保证HTTPS请求与响应的数据安全性HTTPS请求响应的大致流程第一步:TLS握手,协商加密密钥client请求server,say helloserver发送证书、签名算法、加密算法等信息client验证证书合法性client与server协商数据传输的对称密钥第二步:应用数据传输,用协商通过的密钥加密应用数据,发送加密数据证书合法性校验证书合法性校验用到数字签名技术。合法的证书由CA机构签发,证书中都会带上Signature,Signature是证书的摘要(HASH)用CA的私钥加密生成的。证书校验流程:client用同样的算法生成证书摘要Aclient用CA的公钥解密Signature获得摘要Bclient比较A和B是否相同,相同则证书合法。如果证书被修改过,A和B必然不会相同。多级证书的校验:CA机构也是分级的,顶的CA机构的证书是根证书。一般网站的证书不可能是根证书签发的,这样就会一级一级往上校验证书的合法性。参考文章https://security.stackexchang…https://segmentfault.com/a/11...https://imququ.com/post/optim...https://www.cnblogs.com/snowa...http://www.runoob.com/w3cnote...https://www.jianshu.com/p/94d…

February 21, 2019 · 1 min · jiezi

你的微博也被盗赞?试试HSTS强制HTTPS加密

微博账户被盗赞或被动加关注的问题,可能很多用户都遇到过,每天都会发现自己的账户莫名其妙关注或点赞了几十个营销号、广告号、明星号的微博,挨个取消被盗的关注和赞,竟然成了日常最主要的微博操作,很多用户对此感到不厌其烦。原因分析从技术上看,能够给微博账号加关注或盗赞的途径通常有:1、微博账户被盗,能够被别人直接登录;2、使用第三方客户端等,可以通过微博开放平台OAuth拿到access token,然后权限被滥用;3、在浏览器上使用web版微博登录时,cookies被泄露了。对此,微博安全中心也曾给过一些安全建议,比如:建议用户更换密码、升级客户端、设置登录保护、清除第三方应用权限等等,但是不少用户按照建议完成这些操作后,被盗赞的问题仍然存在。在对不同客户端、web端的访问情况进行分析后我们发现,虽然微博已经启用HTTPS加密 很多开放平台的接口也使用HTTPS加密,但你的浏览器书签、别人发给你的链接、旧的外链、其他应用生成的链接都可能还是 HTTP 的。当部分请求由HTTP连接301跳转到HTTPS时,这个 HTTP 请求仍然会带上浏览器在 http://weibo.com 域下的所有 cookie。这么一来,当用户登录后在某个特定场景访问到HTTP的微博链接时,仍然可能遭遇cookie劫持,清除授权或修改密码也没有用。解决方法通过给 cookie 设置 secure 或者在服务器端设置 HSTS(HTTP Strict Transport Security) 也能解决这个问题,但是微博服务器端的设置是用户无法控制的,作为用户还有没有什么办法解决这个问题呢?沃通CA(www.wosign.com)建议:比较简单的做法就是,用户在Chrome浏览器手动设置HSTS预载入列表(preload list),将微博域名加入预载入列表,强制HTTPS加密访问。HSTS代表的是HTTPS严格传输安全协议,它是一个网络安全政策机制,能够强迫浏览器只通过安全的HTTPS连接(永远不能通过HTTP)与网站交互,这能够帮助防止协议降级攻击和cookie劫持。但是对于HSTS生效前的首次HTTP请求,依然无法避免被劫持,浏览器厂商们为了解决这个问题,提出了HSTS Preload List(预载入)方案:内置一份可以定期更新的列表,对于列表中的域名,即使用户之前没有访问过,也会使用HTTPS协议。Chrome运营了一个HSTS 预载入列表,大多数主流浏览器Firefox, Opera, Safari, IE 11 and Edge也都有基于Chrome列表的预载入列表。在Chrome浏览器设置HSTS预载入列表的方法是:在 Chrome 里打开 chrome://net-internals/#hstsAdd domain中增加微博主域名Query domain中能查询到就可以了在HSTS预载入列表中加入微博主域名后,Chrome再遇到HTTP的微博连接,会直接在浏览器内部就跳转到 HTTPS,确保请求从一开始就加密,保证通讯安全,防止cookie劫持、SSL Strip中间人攻击,您可以通过Chrome开发者工具对此进行验证。关注沃通CA获取全球信任SSL证书。

February 21, 2019 · 1 min · jiezi

谷歌Chrome开展实验,解决HTTPS混合内容错误

HTTPS证书申请谷歌Chrome团队将在本周开展一项实验,试图解决HTTPS 混合内容(mixed content)错误。HTTPS混合内容错误一直是网站所有者推进HTTPS加密的一大阻碍,Chrome团队对这一问题的解决将更有利于推动HTTPS加密普及。HTTPS混合内容错误是指,初始的HTML(网页)通过安全的HTTPS连接加载,但也页面中其他资源(如图像、视频、样式表、脚本)却通过不安全的HTTP连接加载的时候,就会出现混合内容错误(也就是不安全因素)。因为HTTP和HTTPS内容都被加载显示在同一个页面上,而初始请求是基于HTTPS加密的,现代浏览器会对这类内容显示警告,指示用户此页面含有不安全资源。在过去几年中,混合内容(mixed content)一直是浏览器制造商和其他推动HTTPS迁移的组织面临的一个大问题。浏览器混合内容错误有时被认为是阻止用户访问网站,这让许多网站运营者不敢迁移到HTTPS,许多人担心他们支持HTTPS没有带来任何实际好处却失去流量收入。解决Web浏览器中出现的混合内容错误,可能是说服网站运营者转向HTTPS的最后一个主要障碍。本周,Google工程师在Chrome中推出了一项实验,他们将浏览器配置为自动将任何混合内容升级为完整的HTTPS。Chrome会通过秘密地将资源的URL(例如图像,视频,样式表,脚本)从HTTP版本更改为HTTPS来实现此目的。如果HTTPS链接上存在相同的资源,则一切都正常加载。如果这个HTTPS资源不存在,Chrome会记录该错误并执行为此实验配置的众多方案中的一种。一般认为,网站所有者升级他们的网站使用HTTPS时,他们可能忘记更改网站源代码,一些内容即便可以通过HTTPS加载,但却被遗留使用HTTP加载。此实验的目的是让Google工程师可以深入了解,如果Chrome默认情况下自动将所有混合内容网站更新为HTTPS,那么多少网站会连接失败,以及混合内容HTTP网址的最佳后备策略是什么。如果破损的链接和网站的百分比很小,谷歌工程师很可能会考虑在主Chrome浏览器中发布这个“自动更新到HTTPS”的功能,并朝着更安全的网络迈出新的一步。目前,谷歌打算将该实验推广到其Chrome Canary大约百分之一的用户群中(以能够启用chrome://flags/#enable-origin-trials 为标记)。混合内容错误在浏览器层级得到解决,将大大推动HTTPS加密的应用普及,网站所有者可以更加安心地升级HTTPS加密。沃通SSL证书由全球信任顶级根签发,支持Windows、安卓、iOS、JDK以及Firefox、Chrome等各类浏览器、操作系统和移动终端,具备广泛兼容性,可用于网站、APP、微信小程序等各类HTTPS应用场景。沃通CA资深技术团队免费提供一对一指导,帮助您正确部署HTTPS加密,全面解决混合内容错误、不安全加密算法等可能造成安全隐患的HTTPS部署问题。关注沃通SSL证书 www.wosign.com

February 21, 2019 · 1 min · jiezi

Flask 学习笔记(3) --- 申请和部署HTTPS证书

简介现在已经进入 HTTPS 的时代, HTTPS 证书 目前应用广泛, 发展迅速. 相较于明文传输的 HTTP, HTTPS 更加安全. HTTPS 即 Hypertext Transfer Protocol Secure, 由于其安全层使用的是 TLS/SSL, 因此 HTTPS 也可以称为 HTTP over TLS 或 HTTP over SSL. 关于 HTTPS 证书的分类, 可以参考这篇博客HTTPS 证书 需要向国际公认的证书证书认证机构 Certificate Authority (CA) 申请.接下来, 我们将使用自动化证书管理工具 acme.sh 为我们的域名申请 Let’s Encrypt 颁发的 HTTPS 证书, 然后将其部署在我们的网站上.本文假设我们的域名为 www.awesome.com开发环境在前文的基础上, 我们只需增加 acme.sh 2.8.0 这个工具. 它的中文文档在这里. 安装 acme.sh 的过程很简单, 在 Terminal 中输入如下命令 acme.sh 即可.curl https://get.acme.sh | sh生成证书我们使用 http 方式来验证我们对域名的所有权.如果只申请单域名证书(Single Domain Certificate, www.awesome.com), 那么在 Terminal 中运行如下命令即可acme.sh –issue -d www.awesome.com –standaloneacme 会在当前目录生成一个验证文件, 然后运行一个监听 80 端口的 server, 如果 Let’s Encrypt 成功地通过域名下载了这个文件, 就验证了我们对域名的所有权, 就可以签发证书了.我们也可以运行一个 file server 监听 80 端口cd ~/webapppython3 -m http.server 80然后在另一个 Terminal 里输入如下命令cd ~acme.sh –issue -d www.awesome.com –webroot ~/webapp如果要申请通配符证书(Wildcard Certificate, .awesome.com), 则需要用 dns 方式. 首先我们在 Godaddy 上申请开发者 API key & secret, 然后参考 acme.sh 的文档 readme 和 dnsapi, 执行如下命令export GD_Key=“xxxxxxxx"export GD_Secret=“yyyyy"acme.sh –issue –dns dns_gd -d “.awesome.com” -d awesome.com如果 DNS txt record 记录添加成功, acme 会先等待 120s 以待其生效, 然后验证我们对域名的所有权.下一节, 我们将讲述如何安装和部署证书安装和部署证书对于单域名证书, 根据 acme 的文档, 我们需要执行以下命令, 将证书和公钥放到 ~/ssl/ 文件夹中acme.sh –installcert -d www.awesome.com –key-file ~/ssl/server.key –fullchain-file ~/ssl/server.cer对于通配符证书, 操作也是类似的, 把域名换成 “.awesome.com” 就好了acme.sh –installcert -d “.awesome.com” –key-file /ssl/server.key –fullchain-file /sslwebsite/server.cer然后, 在之前编写的 server 中, 我们需要引入证书和公钥, 从而将明文的消息用 ssl/tls 包裹起来. 根据 Stack Overflow, 这篇文章下面的 Comments, 以及 werkzeug docs, 我们只需要在 app.run() 中加上 ssl_context=(’/ssl/server.cer’, ‘/ssl/server.key’) 参数即可# class IndexHandler(…):# …if name == ‘main’: app.add_url_rule(’/’, view_func=IndexHandler.as_view(‘index’)) context = (’./server.cer’, ‘./server.key’) app.run(port=443, host=‘0.0.0.0’, debug=True, threaded=True, ssl_context=context)至此, 我们的 HTTPS 证书已经申请和部署完成了. 但是我们的 server 目前还存在一个问题, 就是只能访问 https://www.awesome.com, 而原来的 http://www.awesome.com 已经无法访问了, 因为我们的 server 现在只能监听 443 端口而不能监听 80 端口. 下一篇文章, 我们将解决这个问题, 也就是另外写一个 server 来监听 80 端口, 并将 http 服务重定向为 https. 同时, 我们还将学习如何使用 HSTS, 使浏览器默认以更安全的 https 的方式访问我们的网站.参考链接https://imququ.com/post/letse…https://github.com/Neilpang/a...https://github.com/Neilpang/a...https://github.com/Neilpang/a...https://letsencrypt.org/https://stackoverflow.com/que...http://flask.pocoo.org/docs/1...http://flask.pocoo.org/snippe...http://werkzeug.pocoo.org/doc...http://werkzeug.pocoo.org/doc...https://jjayyyyyyy.github.io/… ...

February 15, 2019 · 2 min · jiezi

上线 HTTPS 服务 / 反向代理 LB / 隐藏业务IP

ssl 证书免费申请ssl for free 可以免费为我们提供三个月的 ssl 证书及续签服务,填写业务域名,上传验证文件到业务服务器,验证成功后便会生成相应的证书.crt和私钥.key,提供一次性下载,重新生成,销毁及续签服务。Nginx 配置 HTTPS / 负载均衡配置如下注意:在upstream中加入hash语句。server语句中不能写入weight等其他的參数,hash_method是使用的hash算法。upstream upstream_server_api { #ip_hash; 同一请求ip发往同一负载 #fair; 按后端服务器的响应时间来分配请求,响应时间短的优先分配 #–url_hash– 按訪问url的hash结果来分配请求,使每一个url定向到同一个后端服务器 #hash $request_uri; #hash_method crc32; #–url_hash– server 127.0.0.1:8081 weight=1 max_fails=3 fail_timeout=30s;#权重1 失败3此后暂停30s server 127.0.0.1:8082 weight=2 max_fails=3 fail_timeout=30s;#权重2 失败3此后暂停30s server 127.0.0.1:8083 backup;# 当其他服务器不可用或全忙时启用 server 127.0.0.1:8084 down;# 服务下线}server { listen 443 ssl default; server_name api.foo.com; index index.html index.htm index.php; root /home/wwwroot/web; … ssl on; ssl_certificate /opt/nginx_ssl/certificate.crt; ssl_certificate_key /opt/nginx_ssl/private.key; ssl_session_timeout 5m; ssl_protocols SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; … # 如果是静态请求 nginx 负责处理 否则转发给后端服务器location 处理动态请求 # 你可以根据自己的业务定义相应的转发规则 location / { try_files $uri $uri/ @loc_server_api; } # 后端服务器location则反向代理给后端服务 location @loc_server_api { proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://upstream_server_api; } location ~ ..(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ ..(js|css)?$ { expires 12h; } location ~ /. { deny all; }}如果需要重定向 http 到 https 可使用如下配置server { listen 80 default; server_name api.foo.com; #重定向http至https return 301 https://api.foo.com;}检查配置后重启服务即可nginx -tsystemctl restart nginx.service利用阿里云 SCDN 全站加速隐藏业务服务器 IP全站加速 SCDN 并不能对抗 DDOS/CC 攻击,它只是在 CDN 的基础上同时加速上行请求:选用更为畅通和高速的网络通道传输客户端向服务器端发送的请求,适合动态类数据的请求(web service)。1、创建业务域名 api.foo.com 下的 SCDN 规则,获得加速域名。2、CNAME 解析业务域名到相应的 SCDN 规则提供的加速域名。3、配置回源方式(业务域名|源站域名|自定义域名),这里我们选业务域名,我们业务服务器也应一致监听此业务域名。4、配置 HTTPS 填写申请的证书及私钥开启 HTTPS 访问,可配置是否重定向 HTTP 请求至 HTTPS。5、保存生效如此业务域名将被解析至全站加速CDN,而后 SCDN 回源请求给隐藏在后方的业务服务器,攻击者无法发现真实的业务服务器IP。 ...

January 24, 2019 · 1 min · jiezi

一篇文章带你了解http/https

走在前端的大道上本篇将自己读过的相关 http/https 方法 文章中,对自己有启发的章节片段总结在这(会对原文进行删改),会不断丰富提炼总结更新。Web 基础HTTP(HyperText Transfer Protocol,超文本传输协议)。WWW(World Wide Web)的三种技术:HTML、HTTP、URL。RFC(Request for Comments,征求修正意见书),互联网的设计文档。URLURI(Uniform Resource Indentifier,统一资源标识符)URL(Uniform Resource Locator,统一资源定位符)URN(Uniform Resource Name,统一资源名称),例如 urn:isbn:0-486-27557-4 。URI 包含 URL 和 URN,目前 WEB 只有 URL 比较流行,所以见到的基本都是 URL。HTTP超文本传输协议(HTTP)是用于传输诸如HTML的超媒体文档的应用层协议。它被设计用于Web浏览器和Web服务器之间的通信,但它也可以用于其他目的。 HTTP遵循经典的客户端-服务端模型,客户端打开一个连接以发出请求,然后等待它收到服务器端响应。 HTTP是无状态协议,意味着服务器不会在两个请求之间保留任何数据(状态)。HTTP是明文传输的,也就意味着,介于发送端、接收端中间的任意节点都可以知道你们传输的内容是什么。这些节点可能是路由器、代理等。举个最常见的例子,用户登陆。用户输入账号,密码,采用HTTP的话,只要在代理服务器上做点手脚就可以拿到你的密码了。用户登陆 –> 代理服务器(做手脚)–> 实际授权服务器在发送端对密码进行加密?没用的,虽然别人不知道你原始密码是多少 ,但能够拿到加密后的账号密码,照样能登陆。HTTP是应用层协议,位于HTTP协议之下是传输协议TCP。TCP负责传输,HTTP则定义了数据如何进行包装。1.HTTP协议的主要特点简单快速、灵活、无连接、无状态2.HTTP报文的组成部分请求报文响应报文请求行 请求头 空行 请求体状态行 响应头 空行 响应体请求报文响应报文3.HTTP方法GET —-> 获取资源POST —-> 传输资源PUT —-> 更新资源DELETE —-> 删除资源HEAD —-> 获取报文首部4.POST 和 GET 的区别GET在游览器回退是无害的,而POST会再次提交请求GET请求会被游览器主动缓存,而POST不会,除非手动设置GET请求参数会被完整的保留在游览器历史记录里,而POST中的参数不会被保留GET产生的URL地址可以被收藏,而POST不可以GET参数通过URL传递,而POST放在Request bodyGET请求只能进行URL编码,而POST支持多种编码方式GET请求在URL中传递的参数是有长度限制的,而POST没有限制GET请求会把参数直接暴露在URL上,相比POST更安全对参数的数据类型,GET只接受ASCII字符,而POST没有限制5.HTTP状态码状态信息1xx指示信息 - 表示请求已接受,继续处理2xx成功 - 表示请求已被成功接收3xx重定向 - 要完成请求必须进行进一步的操作4xx客户端错误 - 请求有语法错误或请求无法实现5xx服务器错误 - 服务器未能实现合法的请求6.什么是持久化链接7.什么是管线化HTTPS科普扫盲帖notes/HTTPHTTPSHTTPS相对于HTTP有哪些不同呢?其实就是在HTTP跟TCP中间加多了一层加密层TLS/SSL。神马是TLS/SSL?通俗的讲,TLS、SSL其实是类似的东西,SSL是个加密套件,负责对HTTP的数据进行加密。TLS是SSL的升级版。现在提到HTTPS,加密套件基本指的是TLS。传输加密的流程原先是应用层将数据直接给到TCP进行传输,现在改成应用层将数据给到TLS/SSL,将数据加密后,再给到TCP进行传输。HTTPS是如何加密数据的对安全或密码学基础有了解的同学,应该知道常见的加密手段。一般来说,加密分为对称加密、非对称加密(也叫公开密钥加密)HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性HTTPS与HTTP的一些区别HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。HTTP协议运行在TCP之上,所有传输的内容都是明文,内容可能会被窃听。HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。不验证通信方的身份,通信方的身份有可能遭遇伪装。无法证明报文的完整性,报文有可能遭篡改。使用SPDY加快你的网站速度谷歌推行一种协议(HTTP 之下SSL之上[TCP]),可以算是HTTP2的前身,SPDY可以说是综合了HTTPS和HTTP两者优点于一体的传输协议,比如压缩数据(HEADER)多路复用优先级(可以给请求设置优先级)SPDY构成图:SPDY位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTTP协议(将HTTP1.x的内容封装成一种新的frame格式),同时可以使用已有的SSL功能。HTTP2HTTP2.0可以说是SPDY的升级版(其实原本也是基于SPDY设计的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,主要是以下两点HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPSHTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATEhttp2 新特性新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。多路复用(MultiPlexing),支持单个连接多次请求,即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。目前,有大多数网站已经启用HTTP2.0,例如YouTuBe,淘宝网等网站,利用chrome控制台可以查看是否启用H2:chrome=>Network=>Name栏右键=>√Protocol本节参考文章:简单比较 http https http2、HTTPS科普扫盲帖关于跨域关于跨域,有两个误区:✕ 动态请求就会有跨域的问题✔ 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境✕ 跨域就是请求发不出去了✔ 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。同源策略具体限制些什么呢?不能向工作在不同源的的服务请求数据(client to server)但是script标签能够加载非同源的资源,不受同源策略的影响。无法获取不同源的document/cookie等BOM和DOM,可以说任何有关另外一个源的信息都无法得到 (client to client)跨域最常用的方法,应当属CORS如下图所示:只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。CORS把请求分为两种,一种是简单请求,另一种是需要触发预检请求,这两者是相对的,怎样才算“不简单”?只要属于下面的其中一种就不是简单请求:(1)使用了除GET/POST/HEAD之外的请求方式,如PUT/DELETE(2)使用了除Accept/Accept-Language/Content-Language/Last-Event-ID/Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain等几个常用的http头这个时候就认为需要先发个预检请求,预检请求使用OPTIONS方式去检查当前请求是否安全代码里面只发了一个请求,但在控制台看到了两个请求,第一个是OPTIONS,服务端返回:详见阮一峰的跨域资源共享CORS详解第二种常用的跨域的方法是JSONPJSONP是利用了script标签能够跨域,如下代码所示:function updateList (data) { console.log(data);}$body.append(‘<script src=“http://otherdomain.com/request?callback=updateList"></script>’);代码先定义一个全局函数,然后把这个函数名通过callback参数添加到script标签的src,script的src就是需要跨域的请求,然后这个请求返回可执行的JS文本:// script响应返回的js内容为updateList([{ name: ‘hello’}]);由于它是一个js,并且已经定义了upldateList函数,所以能正常执行,并且跨域的数据通过传参得到。这就是JSONP的原理。小结跨域分为两种,一种是跨域请求,另一种访问跨域的页面,跨域请求可以通过CORS/JSONP等方法进行访问,跨域的页面主要通过postMesssage的方式。由于跨域请求不但能发出去还能带上cookie,所以要规避跨站请求伪造攻击的风险,特别是涉及到钱的那种请求。本节参考文章:我知道的跨域与安全从浏览器打开到页面渲染完成,发生了什么事情(面试)主要的过程是:1.浏览器解析 -> 2.查询缓存 -> 3.dns查询 -> 4.建立链接 -> 5.服务器处理请求 -> 6.服务器发送响应 -> 7.客户端收到页面 -> 8.解析HTML -> 9.构建渲染树 -> 10.开始显示内容(白屏时间) -> 11.首屏内容加载完成(首屏时间) -> 12.用户可交互(DOMContentLoaded) -> 13.加载完成(load)跳转–>应用缓存–>dns–>tcp–>request–>response浏览器输入URL后发生了什么(简化)本节摘要:DNS域名解析;建立TCP连接;发送HTTP请求;服务器处理请求;返回响应结果;关闭TCP连接;浏览器解析HTML;浏览器布局渲染;当我们在浏览器输入网址并回车后,一切从这里开始。一、DNS域名解析我们在浏览器输入网址,其实就是要向服务器请求我们想要的页面内容,所有浏览器首先要确认的是域名所对应的服务器在哪里。将域名解析成对应的服务器IP地址这项工作,是由DNS服务器来完成的。客户端收到你输入的域名地址后,它首先去找本地的hosts文件,检查在该文件中是否有相应的域名、IP对应关系,如果有,则向其IP地址发送请求,如果没有,再去找DNS服务器。一般用户很少去编辑修改hosts文件。 DNS服务器层次结构浏览器客户端向本地DNS服务器发送一个含有域名www.cnblogs.com的DNS查询报文。本地DNS服务器把查询报文转发到根DNS服务器,根DNS服务器注意到其com后缀,于是向本地DNS服务器返回comDNS服务器的IP地址。本地DNS服务器再次向comDNS服务器发送查询请求,comDNS服务器注意到其www.cnblogs.com后缀并用负责该域名的权威DNS服务器的IP地址作为回应。最后,本地DNS服务器将含有www.cnblogs.com的IP地址的响应报文发送给客户端。从客户端到本地服务器属于递归查询,而DNS服务器之间的交互属于迭代查询。正常情况下,本地DNS服务器的缓存中已有comDNS服务器的地址,因此请求根域名服务器这一步不是必需的。二、建立TCP链接费了一顿周折终于拿到服务器IP了,下一步自然就是链接到该服务器。对于客户端与服务器的TCP链接,必然要说的就是『三次握手』。三次握手客户端发送一个带有SYN标志的数据包给服务端,服务端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息,最后客户端再回传一个带ACK标志的数据包,代表握手结束,连接成功。上图也可以这么理解:客户端:“你好,在家不,有你快递。”服务端:“在的,送来就行。”客户端:“好嘞。”TCP三次握手client—–>server:SYN(发起一个TCP连接,同步报文)server—–>client:SYN+ACK(应答报文,表示已创建连接)client—–>server:ACK(应答报文,表示收到已连接)三、发送HTTP请求与服务器建立了连接后,就可以向服务器发起请求了。这里我们先看下请求报文的结构(如下图):请求报文在浏览器中查看报文首部(以google浏览器为例):请求行包括请求方法、URI、HTTP版本。首部字段传递重要信息,包括请求首部字段、通用首部字段和实体首部字段。我们可以从报文中看到发出的请求的具体信息。具体每个首部字段的作用,这里不做过多阐述。四、服务器处理请求服务器端收到请求后的由web服务器(准确说应该是http服务器)处理请求,诸如Apache、Ngnix、IIS等。web服务器解析用户请求,知道了需要调度哪些资源文件,再通过相应的这些资源文件处理用户请求和参数,并调用数据库信息,最后将结果通过web服务器返回给浏览器客户端。服务器处理请求五、返回响应结果在HTTP里,有请求就会有响应,哪怕是错误信息。这里我们同样看下响应报文的组成结构:响应报文在响应结果中都会有个一个HTTP状态码,比如我们熟知的200、301、404、500等。通过这个状态码我们可以知道服务器端的处理是否正常,并能了解具体的错误。状态码由3位数字和原因短语组成。根据首位数字,状态码可以分为五类:状态码类别六、关闭TCP连接为了避免服务器与客户端双方的资源占用和损耗,当双方没有请求或响应传递时,任意一方都可以发起关闭请求。与创建TCP连接的3次握手类似,关闭TCP连接,需要4次握手。上图可以这么理解:客户端:“兄弟,我这边没数据要传了,咱关闭连接吧。”服务端:“收到,我看看我这边有木有数据了。”服务端:“兄弟,我这边也没数据要传你了,咱可以关闭连接了。”客户端:“好嘞。”由客户端发起的关闭连接 * client—–>server:FIN(请求关闭连接) * server—–>client:ACK(收到了连接,但不会立即关闭,等到报文都发送完再回复一个FIN) * server—–>client:FIN * client—–>server:ACK(收到关闭)由服务端发起的关闭连接* 当http设置了keepalive定时关闭,服务端会在结束数据传送后关闭TCP连接七、浏览器解析HTML准确地说,浏览器需要加载解析的不仅仅是HTML,还包括CSS、JS。以及还要加载图片、视频等其他媒体资源。浏览器通过解析HTML,生成DOM树,解析CSS,生成CSS规则树,然后通过DOM树和CSS规则树生成渲染树。渲染树与DOM树不同,渲染树中并没有head、display为none等不必显示的节点。要注意的是,浏览器的解析过程并非是串连进行的,比如在解析CSS的同时,可以继续加载解析HTML,但在解析执行JS脚本时,会停止解析后续HTML,这就会出现阻塞问题,关于JS阻塞相关问题,这里不过多阐述,后面会单独开篇讲解。八、浏览器布局渲染根据渲染树布局,计算CSS样式,即每个节点在页面中的大小和位置等几何信息。HTML默认是流式布局的,CSS和js会打破这种布局,改变DOM的外观样式以及大小和位置。这时就要提到两个重要概念:repaint和reflow。repaint:屏幕的一部分重画,不影响整体布局,比如某个CSS的背景色变了,但元素的几何尺寸和位置不变。reflow: 意味着元件的几何尺寸变了,我们需要重新验证并计算渲染树。是渲染树的一部分或全部发生了变化。这就是Reflow,或是Layout。所以我们应该尽量减少reflow和repaint,我想这也是为什么现在很少有用table布局的原因之一。最后浏览器绘制各个节点,将页面展示给用户。拓展阅读:面试必考之http状态码有哪些、CDN与DNS知识汇总、前端工程师系列,TCP复习及浓缩总结(全干货,支持面试)推荐必读:5分钟让你明白HTTP协议、分分钟让你理解HTTPS本节参考文章:”天龙八步“细说浏览器输入URL后发生了什么从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)(详细)在浏览器地址栏输入URL浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤如果资源未缓存,发起新请求如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证。检验新鲜通常有两个HTTP头进行控制Expires和Cache-Control:HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期HTTP1.1增加了Cache-Control: max-age=,值为以秒为单位的最大新鲜时间浏览器解析URL获取协议,主机,端口,path浏览器组装一个HTTP(GET)请求报文浏览器获取主机ip地址(DNS解析),过程如下:浏览器缓存本机缓存hosts文件路由器缓存ISP DNS缓存DNS递归查询(可能存在负载均衡导致每次IP不一样)打开一个socket与目标IP地址,端口建立TCP链接,三次握手如下:客户端发送一个TCP的SYN=1,Seq=X的包到服务器端口服务器发回SYN=1, ACK=X+1, Seq=Y的响应包客户端发送ACK=Y+1, Seq=ZTCP链接建立后发送HTTP请求服务器接受请求并解析,将请求转发到服务程序,如虚拟主机使用HTTP Host头部判断请求的服务程序服务器检查HTTP请求头是否包含缓存验证信息如果验证缓存新鲜,返回304等对应状态码处理程序读取完整请求并准备HTTP响应,可能需要查询数据库等操作服务器将响应报文通过TCP连接发送回浏览器浏览器接收HTTP响应,然后根据情况选择关闭TCP连接或者保留重用,关闭TCP连接的四次握手如下:主动方发送Fin=1, Ack=Z, Seq= X报文被动方发送ACK=X+1, Seq=Z报文被动方发送Fin=1, ACK=X, Seq=Y报文主动方发送ACK=Y, Seq=X报文浏览器检查响应状态吗:是否为1XX,3XX, 4XX, 5XX,这些情况处理与2XX不同如果资源可缓存,进行缓存对响应进行解码(例如gzip压缩)根据资源类型决定如何处理(假设资源为HTML文档)解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本,这些操作没有严格的先后顺序,以下分别解释构建DOM树:Tokenizing:根据HTML规范将字符流解析为标记Lexing:词法分析将标记转换为对象并定义属性和规则DOM construction:根据HTML标记关系将对象组成DOM树解析过程中遇到图片、样式表、js文件,启动下载构建CSSOM树:Tokenizing:字符流转换为标记流Node:根据标记创建节点CSSOM:节点创建CSSOM树根据DOM树和CSSOM树构建渲染树:从DOM树的根节点遍历所有可见节点,不可见节点包括:script,meta这样本身不可见的标签。被css隐藏的节点,如display: none对每一个可见节点,找到恰当的CSSOM规则并应用发布可视节点的内容和计算样式js解析如下:浏览器创建Document对象并解析HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate为loadingHTML解析器遇到没有async和defer的script时,将他们添加到文档中,然后执行行内或外部脚本。这些脚本会同步执行,并且在脚本下载和执行时解析器会暂停。这样就可以用document.write()把文本插入到输入流中。同步脚本经常简单定义函数和注册事件处理程序,他们可以遍历和操作script和他们之前的文档内容当解析器遇到设置了async属性的script时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器不会停下来等它下载。异步脚本禁止使用document.write(),它们可以访问自己script和之前的文档元素当文档完成解析,document.readState变成interactive所有defer脚本会按照在文档出现的顺序执行,延迟脚本能访问完整文档树,禁止使用document.write()浏览器在Document对象上触发DOMContentLoaded事件此时文档完全解析完成,浏览器可能还在等待如图片等内容加载,等这些内容完成载入并且所有异步脚本完成载入和执行,document.readState变为complete,window触发load事件显示页面(HTML解析过程中会逐步显示页面)OSI 七层协议 和 五层网络架构OSI 七层涵盖:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层;五层因特网协议栈其实就是:应用层(dns,http) DNS解析成IP并发送http请求传输层(tcp,udp) 建立tcp连接(三次握手)网络层(IP,ARP) IP寻址 为数据在结点之间传输创建逻辑链路数据链路层(PPP) 封装成帧 在通信实体间建立数据链路链接物理层(利用物理介质传输比特流) 物理传输(然后传输的时候通过双绞线,电磁波等各种介质) 主要定义屋里设备如何传输数据五层模型就是"会话,表示,应用层"同为一层;DNS 的大体的执行流程了解么,属于哪个层级?工作在哪个层级?DNS是应用层协议,事实上他是为其他应用层协议工作的,包括不限于HTTP和SMTP以及FTP,用于将用户提供的主机名解析为ip地址。具体过程如下:(1)浏览器缓存: 当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址(若曾经访问过该域名且没有清空缓存便存在);(2)系统缓存: 当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是否有该域名对应IP;(3)路由器缓存: 当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客户端的DNS缓存;(4)ISP(互联网服务提供商)DNS缓存: 当在用户客服端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找;(或者向网络设置中指定的local DNS进行查询,如果在PC指定了DNS的话,如果没有设置比如DNS动态获取,则向ISP DNS发起查询请求)(5)根域名服务器: 当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;(6)顶级域名服务器: 顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;(7)主域名服务器: 主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确记录;(8)保存结果至缓存: 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接。DNS 的解析的几个记录类型需要了解:A: 域名直接到 IPCNAME: 可以多个域名映射到一个主机,类似在 Github Page就用 CNAME 指向MX: 邮件交换记录,用的不多,一般搭建邮件服务器才会用到NS: 解析服务记录,可以设置权重,指定谁解析TTL: 就是生存时间(也叫缓存时间),一般的域名解析商都有默认值,也可以人为设置TXT: 一般指某个主机名或域名的说明 ...

January 13, 2019 · 1 min · jiezi

nginx docker容器配置https(ssl)

证书生成首先需要有https的证书文件,如果你已经向证书授权中心购买了证书,可以跳过这步,这里介绍如何生成自签名证书,自签名证书是指不是证书授权中心(Certificate Authority)颁发的证书,而是在个人计算机上通过相关工具自己生成的证书,一般用于测试,不可用于生产环境。为了方便管理证书(证书生成过程中会产生很多文件),我们可以单独创建一个目录用于存放证书文件,下面是通过openssl工具生成证书的过程。1. 创建目录$ cd ~$ mkdir ssl$ cd ssl2. 创建秘钥文件创建秘钥文件definesys.key,名称可以自定义,需要指定密码(随意密码即可)$ openssl genrsa -des3 -out definesys.key 1024Generating RSA private key, 1024 bit long modulus…….++++++………………++++++e is 65537 (0x10001)Enter pass phrase for definesys.key:Verifying - Enter pass phrase for definesys.key:3. 创建csr证书需要输入相关信息,比较重要的是Common Name,这个是访问nginx的地址$ openssl req -new -key definesys.key -out definesys.csrEnter pass phrase for definesys.key:You 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]:ShanghaiLocality Name (eg, city) []:ShanghaiOrganization Name (eg, company) [Internet Widgits Pty Ltd]:DefinesysOrganizational Unit Name (eg, section) []:DefinesysCommon Name (e.g. server FQDN or YOUR name) []:www.definesys.comEmail Address []:jianfeng.zheng@definesys.comPlease enter the following ’extra’ attributesto be sent with your certificate requestA challenge password []:可以不用输An optional company name []:可以不用输#此时文件$ ssl lltotal 16-rw-r–r– 1 asan staff 733 1 3 23:57 definesys.csr-rw-r–r– 1 asan staff 963 1 3 23:55 definesys.key4. 去除秘钥密码nginx使用私钥时需要去除密码,执行以下命令时需要输入秘钥的密码$ cp definesys.key definesys.key.bak$ openssl rsa -in definesys.key.bak -out definesys.keyEnter pass phrase for definesys.key.bak:writing RSA key5. 生成crt证书$ openssl x509 -req -days 3650 -in definesys.csr -signkey definesys.key -out definesys.crtSignature oksubject=/C=CN/ST=Shanghai/L=Shanghai/O=Definesys/OU=Definesys/CN=www.definesys.com/emailAddress=jianfeng.zheng@definesys.comGetting Private key#此时文件列表$ ssl lltotal 32-rw-r–r– 1 asan staff 1017 1 4 00:03 definesys.crt-rw-r–r– 1 asan staff 733 1 3 23:57 definesys.csr-rw-r–r– 1 asan staff 887 1 4 00:02 definesys.key-rw-r–r– 1 asan staff 963 1 4 00:01 definesys.key.baknginx容器配置1. 证书文件上传将definesys.crt文件和definesys.key文件拷贝到服务器上,假设你服务器上nginx的配置文件在/etc/nginx/目录下,可以在该目录下创建一个文件夹,这里命名certs,将文件拷贝至该文件夹下。2. 配置文件修改修改配置文件nginx.confserver { listen 443 ssl; server_name www.definesys.com; ssl_certificate /etc/nginx/certs/definesys.crt; ssl_certificate_key /etc/nginx/certs/definesys.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /usr/share/nginx/html; index index.html index.htm; }}如果server配置不在nginx.conf文件上,可以在conf.d文件夹下找.conf后缀的文件,一般有个default.conf文件。3. 启动容器docker run -d –restart=unless-stopped -p 443:443 -v /etc/nginx/:/etc/nginx -v /var/run/docker.sock:/tmp/docker.sock:ro -v /u01/application:/usr/share/nginx/html nginx访问https://localhost验证配置是否正确,如果能够正常访问说明配置成功,由于是自签名证书,打开时会提示证书不安全,忽略即可。 ...

January 4, 2019 · 2 min · jiezi

SSL/TLS 握手协议概述

SSL/TLS 握手协议使客户端和服务端能够安全协商出同一份通信密钥,本文隐藏了一些细节上的内容,对这一握手过程进行了简要说明,如有错误还请指出SSL/TLS 握手协议(0) Client 与 Server 之前建立 (TCP) 连接(1) Client 向 Server 发送 “client hello” 消息,里面包含了安全相关的信息,例如 SSL/TLS 版本号,Client 支持的加密套件 (CipherSuite)。“client hello” 消息还包含了一个随机数client random,用于通信密钥的计算。SSL/TLS 协议还允许 “client hello” 消息包含 Client 所支持的压缩算法 (可选项)(2) Server 回复一条 “server hello” 消息,里面包含了加密套件 (Server 从 “client hello” 消息的 CipherSuites 列表中选择其中一个),session id 和 另一个随机数server random。Server 还会在消息中附带自己的数字证书。(可选) 如果 Server 需要 Client 的数字证书进行客户端认证,会向 Client 发送 “client certificate request” 请求消息,里面包含了 Server 所支持的证书类型和认可的证书颁发机构 CA(3) Client 收到 “server hello”,验证 Server 端的数字证书,并得到证书中 Server 端的公钥,读者可自行查阅更多数字证书的知识(4) Client 向 Server 发送第三个随机数pre-master secret。与之前不同,这次的随机数使用了 Server 的公钥加密 (非对称加密)。现在双方同时拥有这三个随机数client random,server random,premaster secret,可以用来计算生成共同的通信密钥 master secret 用于加密后面传输的业务数据。(5 - 可选) 如果收到 Server 端发来的 “client certificate request” 请求消息,Client 会向 Server 发送一个使用 Client 自己的私钥加密过的随机数 (暂时记作 secret-A),附带 Client 的数字证书。或者发送一个 “no digital certificate alert” 无证书警告,这种情况下基本可以认为 SSL/TLS 握手失败。(6 - 可选) Server 验证 Client 发送过来的数字证书,并得到证书中公钥对 Client 进行身份认证 (通过公钥解密上面那个 secret-A)。(7) Client 向 Server 发送 “finished” 消息,使用第 4 步中计算出来的密钥进行加密传输 (对称加密),这表示 Client 端握手阶段已经完成。(8) Server 也向 Client 发送 “finished” 消息,使用第 4 步中计算出来的密钥进行加密传输 (对称加密),这表示 Server 端握手阶段完成。(9) SSL/TLS 握手阶段完成,接下来双方通信的消息都会使用协商出来的密钥进行加密 (对称加密)Java 代码演示服务端 (全局 SSL 配置)public static void main(String[] args) throws IOException { System.setProperty(“javax.net.debug”, “SSL,handshake”); System.setProperty(“javax.net.ssl.keyStore”, “./keystore/TEST.p12”); System.setProperty(“javax.net.ssl.keyStorePassword”, “TEST”); SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(8001); // serverSocket.setNeedClientAuth(true); 需求客户端认证,可选 while (true) { try { SSLSocket socket = (SSLSocket) serverSocket.accept(); InputStream in = socket.getInputStream(); String message = IOUtils.toString(in); System.out.println(message); in.close(); socket.close(); } catch (Exception e) { e.printStackTrace(); } }}客户端public static void main(String[] args) throws UnknownHostException, IOException { System.setProperty(“javax.net.debug”, “SSL,handshake”); System.setProperty(“javax.net.ssl.trustStore”, “./keystore/TEST.p12”); System.setProperty(“javax.net.ssl.trustStorePassword”, “TEST”); SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) factory.createSocket(“localhost”, 8001); socket.startHandshake(); OutputStream out = socket.getOutputStream(); out.write(“hello”.getBytes()); out.close(); socket.close();}因测试需要,Server 的数字证书是自签名的,而非权威的 CA 所颁发,于是客户端使用了全局的 TrustStore 配置,引入 Server 的数字证书,否则会有以下错误Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) … 14 more 现在我们分别启动 Server 和 Client,并分析 SSL debug 日志Client Hello*** ClientHello, TLSv1.2RandomCookie: GMT: 1545722559 bytes = { 221, 47, 184, 101, 75, 18, 171, 225, 219, 236, 80, 229, 222, 114, 155, 14, 110, 144, 168, 163, 85, 252, 110, 180, 127, 37, 247, 50 }Session ID: {}Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]Compression Methods: { 0 }Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}Extension ec_point_formats, formats: [uncompressed]Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA首先是 Client 发起 SSL 握手,发送 “client hello” 消息ClientHello, TLSv1.2 得知 Client 支持的版本号RandomCookie,客户端生成的随机数 (client random),使用 4 个字节的当前时间加上 28 个随机字节Cipher Suites 列表,表示 Client 所支持的加密套件Server HelloServer 收到 “client hello”,即来自 Client 的握手请求,回复 “server hello” ServerHello, TLSv1.2RandomCookie: GMT: 1545722559 bytes = { 230, 234, 216, 95, 222, 185, 10, 245, 211, 122, 11, 47, 116, 109, 51, 164, 52, 92, 165, 72, 58, 222, 7, 19, 230, 32, 247, 99 }Session ID: {92, 34, 219, 191, 186, 218, 195, 78, 237, 222, 208, 62, 165, 14, 115, 106, 29, 243, 81, 152, 79, 45, 199, 0, 141, 231, 199, 100, 242, 152, 101, 13}Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256Compression Method: 0Extension renegotiation_info, renegotiated_connection: <empty>Cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 Certificate chainchain [0] = [[ Version: V3 Subject: CN=fwks, OU=ACL, O=ACL, L=ZHA, ST=ASIA, C=CN, EMAILADDRESS=ACL@GMAIL.COM Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11…………ServerHello, TLSv1.2,Server 使用的版本号RandomCookie,Server 生成的随机数 (server random),4 个字节的当前时间加上 28 个随机字节Session ID,凭借 session id,会话双方可以缓存并使用 SSL/TLS 握手阶段生成的密钥,而不需要再频繁地进行 SSL/TLS 握手Cipher suite,Server 从 “client hello” 的加密套件列表中选择的其中一个Certificate chain,是从 CA 到 Server 的数字证书链列表。因为这里是测试用的自签名证书,所以证书链中只有 Server 自己的数字证书Client 收到 “server hello” 后对 Server 的证书进行验证,成功后打出如下日志 (测试需要,Server 的自签名证书已经配置在 Client 的 TurstStore/TrustManager 中)Found trusted certificate:[[ Version: V3 Subject: CN=fwks, OU=ACL, O=ACL, L=ZHA, ST=ASIA, C=CN, EMAILADDRESS=ACL@GMAIL.COM Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11…………“server hello” 中还有一段消息 ServerKeyExchange,告诉 Client 使用的密钥交换算法是什么 (例中使用 ECDH 算法),即如何使用 client random, server random, premaster-secret 生成通信密钥 (不了解 ECDH,这里可能会有误)。*** ECDH ServerKeyExchangeSignature Algorithm SHA512withRSAServer key: Sun EC public key, 256 bits public x coord: 80178198866764561576110018839724135146035097258288090685496480316896017800231 public y coord: 21879990761153492368331320937448674839810402545614808541518903129245252068750 parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)ClientKeyExchangeClient 使用 Server 的公钥加密第三个随机数 pre-master secret,并发送给 Server。只有 Server 能使用自己的私钥解出这个 pre-master secret*** ECDHClientKeyExchangeECDH Public value: { 4, 159, 152, 225, 34, 111, 12, 18, 196, 101, 247, 201, 137, 231, 252, 89, 48, 157, 66, 201, 181, 25, 159, 10, 12, 202, 18, 190, 64, 58, 12, 220, 204, 49, 251, 95, 11, 40, 251, 46, 204, 69, 48, 238, 166, 116, 134, 140, 172, 186, 106, 85, 34, 105, 169, 185, 87, 101, 80, 133, 214, 130, 56, 132, 64 }main, WRITE: TLSv1.2 Handshake, length = 70现在通信双方都掌握了足够的信息去生成通信密钥 (master secret)SESSION KEYGEN:PreMaster Secret:0000: 03 01 84 54 F5 D6 EB F5 A8 08 BA FA 7A 22 61 2D …T……..z"a-0010: 75 DC 40 E8 98 F9 0E B2 87 80 B8 1A 8F 68 25 B8 u.@……….h%.0020: 51 D0 54 45 61 8A 50 C9 BB 0E 39 53 45 78 BE 79 Q.TEa.P…9SEx.yCONNECTION KEYGEN:Client Nonce:0000: 40 FC 30 AE 2D 63 84 BB C5 4B 27 FD 58 21 CA 90 @.0.-c…K’.X!..0010: 05 F6 A7 7B 37 BB 72 E1 FC 1D 1B 6A F5 1C C8 9F ….7.r….j….Server Nonce:0000: 40 FC 31 10 79 AB 17 66 FA 8B 3F AA FD 5E 48 23 @.1.y..f..?..^H#0010: FA 90 31 D8 3C B9 A3 2C 8C F5 E9 81 9B A2 63 6C ..1.<..,……clClient Nonce,就是第一个随机数 client randomServer Nonce,就是第二个随机数 server randomPreMaster Secret,第三个随机数生成的通信密钥如下。除了 Master Secret 的其他几个,笔者也不是特别了解Master Secret:0000: 2C 31 A6 EC A7 75 D0 DC E9 3E 23 1D B4 B7 50 87 ,1…u…>#…P.0010: 48 41 18 7D 29 D4 DB 8A 7D A5 F3 D5 15 08 A4 50 HA..)……….P0020: 5A 4A 50 7D 08 C3 E5 A5 CB ED 4C 40 80 C3 B8 B2 ZJP…….L@….Client MAC write Secret:0000: 1C C1 5F 82 CB CD AB 6B 77 C7 7B D8 66 48 6F A4 ..….kw…fHo.0010: C2 30 59 4D 91 1A 36 82 A4 C2 EF 9B 42 B5 98 7F .0YM..6…..B…Server MAC write Secret:0000: 7D D6 D2 3C 6F 61 AE 15 1F 62 46 4E A5 68 59 66 …<oa…bFN.hYf0010: 72 50 81 0D 12 07 41 B4 8E 83 1F 5D EF 85 D0 12 rP….A….]….Client write key:0000: B0 50 53 C9 FF 10 4E 71 0B 5F 29 63 9C 47 82 77 .PS…Nq.)c.G.wServer write key:0000: 65 67 22 93 A2 45 74 18 D0 F7 B9 F2 78 19 61 07 eg"..Et…..x.a.Finish 消息现在通信双方都计算同一份密钥 Master Secret,可以用于加密并发送 finish 消息了。但在此之前 Client 还会发送了一条 “Change Cipher Spec”,用于告诉对方接下来的通信使用新的密钥加密消息。SSL 日志也会打出下面这一条:main, WRITE: TLSv1.2 Change Cipher Spec, length = 1接下来才是使用新密钥加密发送 finish 消息*** Finishedverify_data: { 5, 73, 52, 104, 95, 23, 44, 252, 228, 173, 15, 129 }main, WRITE: TLSv1.2 Handshake, length = 80Server 收到来自 Client 的 “Change Cipher Spec” 和 “finish” 消息后,也会向 Client 发送 “Change Cipher Spec” 和 “finish” 消息main, READ: TLSv1.2 Change Cipher Spec, length = 1main, READ: TLSv1.2 Handshake, length = 80 Finishedverify_data: { 5, 73, 52, 104, 95, 23, 44, 252, 228, 173, 15, 129 }main, WRITE: TLSv1.2 Change Cipher Spec, length = 1 Finishedverify_data: { 169, 120, 73, 97, 72, 13, 37, 157, 77, 249, 0, 7 }***main, WRITE: TLSv1.2 Handshake, length = 80至此,SSL/TLS 握手阶段完成,通信双方使用新协商的密钥加/解密业务数据main, READ: TLSv1.2 Application Data, length = 64hello关于 HTTPS到这是否豁然开朗了?HTTPS 就是 HTTP over SSL/TLS,同样先进行 SSL/TLS 握手协商通信密钥,再使用通信密钥加密 HTTP 请求/响应报文。如果你在浏览器输入 https://localhost:8001/ 访问上面的 SSL Server,浏览器会给出如下警告浏览器在验证 Server 证书的时候已经失败了,原因是:证书不可信,因为它是自签名的 (The certificate is not trusted because it is self-signed)证书的内容和域名 “localhost” 不匹配 (The certificate is not valid for the name localhost)附录A:加密套件 CipherSuite加密算法套件是一组密码算法的集合,SSL/TLS 通信过程会使用到这一组算法,他们包括密钥交换算法 (key exchange algorithm),主要有 RSA, DH, ECDH, ECDHE认证算法,规定服务端认证和客户端认证 (可选) 使用的算法,主要有 RSA, DSA, ECDSA 这一类非对称加密算法数据加密算法,规定在实际的数据传输中使用的对称加密算法,有 AES, DES, 3DES 这一类对称加密算法消息验证算法 (MAC algorithm),规定数据完整性验证算法 (验证数据在传输中是否受到噪声干扰和其它非人为的破坏),SHA, MD5 这一类散列算法可作为 MAC分割线上方的算法在 SSL/TLS 握手阶段使用,下方两类算法在实际数据传输时使用到回顾之前测试中使用到的加密套件Cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLS: 协议名字ECDHE: 密钥交换算法RSA: 认证算法 (RSA 非对称加密算法)WITH: 分割线AES_128_CBC: 数据加密算法 (AES 对称加密算法)SHA256: MAC 算法 (SHA 散列算法/哈希算法) ...

December 26, 2018 · 6 min · jiezi

http 与 https

http 协议http 是一个基于 TCP/IP 通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)http 协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系,对 http 服务器来说,它并不知道这两个请求来自同一个客户端。 为了解决这个问题, Web 程序引入了 Cookie 机制来维护状态.统一资源标识符 (URI)HTTP 使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接http://<host>:<port>/<path>?<query>#<frag>https://<host>:<port>/<path>?<query>#<frag>默认 HTTP 的端口号为 80,HTTPS 的端口号为 443。HTTP 报文结构(请求报文和响应报文)request line 请求行request header 请求头空行body 内容: 请求数据请求行GET /index.js HTTP/1.1请求方法:GET 获取POST 对资源的建立或修改、HEAD :类似 get,只不过响应只有报头,用于节省字节PUT : 替换对应的资源DELETE 删除OPTIONS 嗅探请求预检,复杂请求中跨域的时候用到请求头host 域名User-Agent : 它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。Referer 告诉服务器我是从哪个页面链接过来的,服务器基于此可以获得一些信息用于处理Accept-Encoding 浏览器发给服务器,声明浏览器支持的编码类型 eg: gzip(一般对纯文本内容可压缩到原大小的 40%)cookie 保存一些信息If-Modified-Since 从何时开始是否有修改If-None-Match 检查 MD5 之类的 hash 值Cache-Control: no-cache响应头Content-Type 响应的 HTTP 内容类型Cache-Control max-age=3600Expires 过期时间Access-Control-Allow-Origin 设置允许的来源,验证请求的时候会带的 OriginAccess-Control-Allow-Headers 设置允许跨域携带的 headersAccess-Control-Allow-Methods 设置允许跨域方法ETag 被请求变量的实体值,与 Web 资源关联的记号last-modified 标记此文件在服务器端最后被修改的时间status 状态码Set-Cookie 设置客户端的 cookie状态码1xx 消息2xx 请求成功200 成功206 (Partial Content)断点续传和多线程下载3xx 重定向301 请求的资源永久从不同的 URI 响应请求302 请求的资源临时从不同的 URI 响应请求304 如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码4xx 客户端错误400 Bad Request (语义有误或者请求参数出错)401 Unauthorized 需要权限验证403 Forbidden 服务器收到请求,但是拒绝提供服务404 not found 请求失败,请求所希望得到的资源未被在服务器上发现5xx 服务器错误500 Internal Server Error 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理503 Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求504 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器或者辅助服务器(例如 DNS)收到响应。httpsHTTPS = HTTP + SSL加密方式对称加密,比较有代表性的就是 AES 加密算法;双方密钥相同,加解密速度快非对称加密,经常使用到的 RSA 加密算法就是非对称加密的;公钥和私钥http 风险被窃听被篡改被冒充基本运行原理客户端和服务端建立 SSL 握手 客户端通过 CA 证书来确认服务端的身份;互相传递三个随机数,之后通过这随机数来生成一个密钥;互相确认密钥,然后握手结束;数据通讯开始,都使用同一个对话密钥来加解密;基本运行原理(详细)首先,客户端 A 访问服务器 B ,客户端 A 会生成一个随机数 1,把随机数 1 、自己支持的 SSL 版本号以及加密算法等这些信息告诉服务器 B 。服务器 B 知道这些信息后,确认一下双方的加密算法,生成一个随机数 2 以及一个公钥返回给客户端 A客户端 A 生成一个随机数 3 ,然后用公钥加密随机数 3 并传输给服务端 B 。服务端 B 接收到后利用私钥进行解密,得到随机数 3。最后,客户端 A 和服务端 B 都有随机数 1、随机数 2、随机数 3,然后双方都利用这三个随机数生成一个对话密钥。之后传输内容就是利用对话密钥来进行加解密了。这时就是利用了对称加密。SSL 的握手部分结束,客户端 A 和服务器 B 开始使用相同的对话密钥进行数据通讯。为啥需要 CA 证书因为在第一步的时候,我们并不清楚服务器 B 是不是真的是服务器 B。所以需要一个我们信得过的机构来告诉我们。基本运行原理(带 CA 证书)首先,客户端 A 访问服务器 B ,客户端 A 会生成一个随机数 1,把随机数 1 、自己支持的 SSL 版本号以及加密算法等这些信息告诉服务器 B 。服务器 B 知道这些信息后,确认一下双方的加密算法,然后也生成一个随机数 B ,并将随机数 B 和 CA 颁发给自己的证书一同返回给客户端 A 。客户端 A 得到 CA 证书后,会去校验该 CA 证书的有效性。校验通过后,客户端生成一个随机数 3 ,然后用证书中的公钥加密随机数 3 并传输给服务端 B 。服务端 B 加密后的随机数 3,利用私钥进行解密,得到随机数 3。最后,客户端 A 和服务端 B 都有随机数 1、随机数 2、随机数 3,然后双方都利用这三个随机数生成一个对话密钥。之后传输内容就是利用对话密钥来进行加解密了。这时就是利用了对称加密,一般用的都是 AES 算法。SSL 的握手部分结束,客户端 A 和服务器 B 开始使用相同的对话密钥进行数据通讯。浏览器验证证书的合法性证书链证书链由多个证书一层一层组成的,除了最底层的网站证书的公钥是给用户加密报文外,其他层证书中的公钥均用于解密底层的证书指纹签名。最高层的根证书是自签名的,也就是自己颁发给自己,所以它的公钥不仅用来解密下层的签名,也用来给自己的签名解密。 ...

December 23, 2018 · 2 min · jiezi

fiddler抓包小节

最近早微信上看到一个有趣的H5,想看看代码怎么写的,但是微信上H5只能在手机上或PC微信端看,这样我们怎么看代码呢是吧?所以想起微信开发者工具0.7的版本之下才有的移动调试,嗯 这个很简单,让我试试,一步一步来…如图:结果悲剧了,只能代理HTTP,不能代理HTTPS如果你想看的页面是HTTP上面这个还是非常有用的。emmm,想到了fiddler抓包,可以抓包HTTPS,于是去官网下载了一个fiddler,下面就直接晒步骤了。1、首先下载fiddler,安装(一直next就好)2、打开fiddler设置 Tool -> Option3、选到HTTPS选项卡,设置允许截获解密HTTPS链接,且下载安装在PC端证书(都允许就好),方便以后PC端抓包HTTPS。4、在选到Connections选项卡,设置代理端口号这些并勾选允许远程电脑代理链接。5、最后fiddler最重要的一步,重启fiddler,要重启fiddler哪些设置才生效。接下来就是手机端的设置(有一个前提抓包都是在同一局域网下面才能抓包代理)1、第一步就是设置手机端口号 选中同一局域网下,并点进去设置2、第二步,打开safari浏览器输入刚刚填写的局域网和端口号 例如我的是192.168.1.132:8888(此时fiddler应是打开状态)会出现下图圈住的红色块(红色块上面是我fiddler代理成功后才出现的,未代理成功不会出现),然后点击下载代理证书fiddlerRoot certificate,并安装允许3、此时打开想要看的HTTPS网站会出现 443 失败错误,那是因为还缺少最后一步,就是手机的 通用 -> 关于本机 -> 证书信任设置 找到你的刚刚下载的根证书(然后开启信任)最后你就可以快乐的在fiddler上面看你访问的所有请求了,最后展示一个在手机上请求segmentfault的时候fiddler抓包显示最后祝大家抓包愉快~~~

December 21, 2018 · 1 min · jiezi

centos nginx下配置免费https

准备记录下部署免费https的过程 ,使用Let’s Encrypt的免费证书下载自动安装脚本wget https://dl.eff.org/certbot-autochmod a+x certbot-auto安装执行脚本./certbot-auto –nginx这里会下载一些东西,让后让你选择你需要加https的域名,这个域名是在nginx.conf中配置的server中读取到的。注意选择的域名只能是备案过的那个域名。因为这个脚本会到DNS服务器去查这个域名对应的ip服务器。对不上也是不会给颁发证书的。执行成功后,会让你选择是否把http的请求重定向到https。直接选择2就行到这里已经配置成功了,访问下网站就可以看效果了。点击那个锁还可以看到关于证书的详细信息总结其实这脚本就是相当于一键安装包,帮你申请https证书,然后下载到服务器存放,然后在把证书配置到nginx.conf里边。打开nginx.conf就能看到新增的配置信息。 listen 443 ssl http2; # managed by Certbot ssl_certificate /etc/letsencrypt/live/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # Redirect non-https traffic to https if ($scheme != “https”) { return 301 https://$host$request_uri; #该状态代码301告诉浏览器(和搜索引擎)这是永久重定向。这使浏览器记住重定向,以便下次访问时,浏览器将在内部进行重定向 }# managed by Certbot}附由于Let’s Encrypt这个证书90天后就过期了,可以使用cron做一个定时任务,因为我这个证书是18号申请的,所以每个月的19号就执行一次,执行crontab -e后会进入个文件输入0 0 19 * * ./path/to/certbot-auto renewcrontab -e的五个参数分别代表,分钟、小时、天、月、周。参考https://certbot.eff.org/lets-encrypt/centos6-nginxhttps://bjornjohansen.no/redirect-to-https-with-nginxhttp://nginx.org/en/docs/http/ngx_http_core_module.html

December 19, 2018 · 1 min · jiezi

https证书互信解决方案—创建私有CA并申请证书

前言https相较于http而言有很大的安全性,当我们一个服务开启https并与之通信时,往往需要证书的认证,如果是浏览器访问服务,只要在浏览器内设置信任证书即可,而如果是程序内访问服务(如java程序),则需要导入该服务的证书所信任的证书。实际情况中,内部系统的互相通信使用https,往往不可能向公有CA申请证书(申请证书需要很高的费用),故我们需要创建一个私有CA来申请证书实现https通信。名词介绍CA和证书认证详见我的一篇博文:https简单解读实现步骤环境介绍64位 centos 7.X操作系统装有openssl命令构建私有CACA要给别人签发证书,首先自己得有一个作为根证书,我们得在一切工作之前修改好CA的配置文件、序列号、索引等等。输入以下命令更改配置文件:vi /etc/pki/tls/openssl.cnf配置文件更改以下部分:[ CA_default ] dir = /etc/pki/CA # Where everything is keptcerts = $dir/certs # Where the issued certs are keptcrl_dir = $dir/crl # Where the issued crl are keptdatabase = $dir/index.txt # database index file.#unique_subject = no # Set to ’no’ to allow creation of # several ctificates with same subject.new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificateserial = $dir/serial # The current serial numbercrlnumber = $dir/crlnumber # the current crl number # must be commented out to leave a V1 CRLcrl = $dir/crl.pem # The current CRLprivate_key = $dir/private/cakey.pem # The private keyRANDFILE = $dir/private/.rand # private random number file…default_days = 3650 # how long to certify for…# For the CA policy[ policy_match ]countryName = matchstateOrProvinceName = optionallocalityName = optionalorganizationName = optionalorganizationalUnitName = optionalcommonName = suppliedemailAddress = optional在/etc/pki/CA目录创建两个文件index.txt和serial:cd /etc/pki/CA && touch index.txt serial && echo 01 > serial仍在当前目录下生成一个CA私钥cakey.pem和自签证书cacert.pem:openssl genrsa -out private/cakey.pem 2048openssl req -new -x509 -key private/cakey.pem -out cacert.pem生成公钥的时候会提示输入一些信息,例子如下:Country Name (2 letter code) []:CN #国家名State or Province Name (full name) []:hangzhou #省份名Locality Name (eg, city) []:hangzhou #地名Organization Name (eg, company) []:company #公司名Organizational Unit Name (eg, section) []:unit #部门名Common Name (eg, your websites domain name) []:localhost #服务域名Email Address []: #电子邮件后面一些信息可按回车略过这里比较重要的是Comman Name填写的是服务的域名地址,即如果该证书用于某个服务则填该服务的域名地址(如用于百度服务器,则填写www.baidu.com)本方案的CA证书不用于某个服务,故可填localhost私有CA签署证书为一个服务生成私钥server.key和一个证书请求文件server.csr:openssl genrsa -out server.key 2048openssl req -new -key server.key -out server.csr生成证书请求文件时,仍会提示输入一些信息,例子如下:Country Name (2 letter code) []:CN #国家名State or Province Name (full name) []:hangzhou #省份名Locality Name (eg, city) []:hangzhou #地名Organization Name (eg, company) []:company #公司名Organizational Unit Name (eg, section) []:unit #部门名Common Name (eg, your websites domain name) []:XXX.XXX.XXX #服务域名Email Address []: #电子邮件这里的Common Name就应该填你实际服务所用的域名了下面将该证书请求文件server.csr由你构建的私有CA签署,生成一个server.crt证书:openssl x509 -req -in server.csr -CA /etc/pki/CA/cacert.pem -CAkey /etc/pki/CA/private/cakey.pem -CAcreateserial -out server.crt到此为止,server.crt证书可用于服务提供https访问,客户端若想访问该服务,导入CA根证书cacert.pem即可。 ...

December 17, 2018 · 2 min · jiezi

从 node服务从部署,到https配置与nginx转发

从 node服务从部署,到https配置与nginx转发最近在搞小程序,小程序的服务必须使用https协议,之前没学过这些,于是写下这篇博客,记录自己遇到的问题本篇博客解决这些问题,服务器的登陆配置、项目的部署、https证书的申请、nginx部署https与转发本地服务通过私钥登陆服务器腾讯云重装系统登陆设置选择使用ssh密钥设置选择ssh密钥,如果没有则创建ssh密钥点击开始安装下载生成好的私钥到本地使用终端进行配置// 赋予私钥文件仅本人可读权限chmod 400 <下载的与云服务器关联的私钥的绝对路径>// 运行以下远程登录命令ssh -i <下载的与云服务器关联的私钥的绝对路径> <username>@<hostname or ip address>给服务器装nvm管理node版本// 下载nvmwget https://github.com/cnpm/nvm/archive/v0.23.0.tar.gz// 解压nvmtar -xf v0.23.0.tar.gz// 进入目录cd nvm-0.23.0/// 安装nvm./install.sh// 安装后执行source ~/.bash_profile使用nvm安装nodenvm install 10.14.2给服务器安装git由于我的代码托管在github上,给服务器安装git方便管理代码在linux安装git克隆项目到服务器git clone https://github.com/lfhwnqe/wechat_server.git进入项目根目录安装依赖cd wechat_servernpm install启动项目进行连接npm start现在项目在本7001端口启动此时访问服务器公网ip:7001就可以访问到服务器上启动的服务把域名映射到服务器进入域名管理界面(我用的是阿里的)点击解析设置点击修改在记录值处修改为服务器的公网ip保存设置,然后访问你的域名有服务监听80端口的话就可以得到响应了申请https证书先申请一个免费https证书在服务器运行一下命令,通过openssl生成csr和私钥openssl req -new -newkey rsa:2048 -sha256 -nodes -out linuoblog.cn.csr -keyout linuoblog.cn.key -subj “/C=CN/ST=ShenZhen/L=ShenZhen/O=NUO Inc./OU=Web Security/CN=linuoblog.cn” 下面是上述命令相关字段含义:C:Country ,单位所在国家,为两位数的国家缩写,如: CN 就是中国ST 字段: State/Province ,单位所在州或省L 字段: Locality ,单位所在城市 / 或县区O 字段: Organization ,此网站的单位名称;OU 字段: Organization Unit,下属部门名称;也常常用于显示其他证书相关信息,如证书类型,证书产品名称或身份验证类型或验证内容等;CN 字段: Common Name ,你的网站域名;如果你是使用https://freessl.cn获取证书,在使用openssl命令生成 csr 文件后,在页面选择csr生成,并粘贴生成的csr内容到页面,然后通过该网站的验证方式,验证所有者,即可获得ca证书https://freessl.cn获得的ca证书是 .pem后缀的证书文件,证书文获取成功后,就可以在 Nginx 配置文件里配置 HTTPS 了。配置nginx,域名启用https,通过nginx把https请求转发到本地node服务要开启 HTTPS 服务,在配置文件信息块(server block),必须使用监听命令 listen 的 ssl 参数和定义服务器证书文件和私钥文件,同时通过设置location模块把发送到网页的请求转发到服务器上的node服务,如下所示:worker_processes auto;http { #配置共享会话缓存大小,视站点访问情况设定 ssl_session_cache shared:SSL:10m; #配置会话超时时间 ssl_session_timeout 10m; server { listen 443 ssl; server_name linuoblog.cn; #设置长连接 keepalive_timeout 70; #HSTS策略 add_header Strict-Transport-Security “max-age=31536000; includeSubDomains; preload” always; #证书文件 ssl_certificate full_chain.pem; # 证书的路径 #私钥文件 ssl_certificate_key linuoblog.cn.key; # 私钥的路径 location / { # 这里是把链接代理到本机的7001端口 proxy_pass http://127.0.0.1:7001; } }} events { worker_connections 1024; ## Default: 1024 }配置完成后启动nginxnginx这个时候,访问自己的域名就能看到https服务了。同时也通过nginx把网页端的请求转发到了服务器本地的server上 ...

December 14, 2018 · 1 min · jiezi

Linux升级wget/curl用于下载https文件的过程

因为需要提升服务器的性能以及支持mysql更新版本的某些特性,因此决定升级mysql版本从5.1.30到8.0,目标确定下来就开始干。Mysql安装方式选择在Linux上安装应用,一般有三种方式,优劣对比分别为:因此我们选择二进制安装,安装简单、方便,支持多个Mysql版本同时存在。在Linux上安装二进制版本的应用,统一为三步:// 通过配置自动生成文件./configure// 编译文件make// 检查自测单元,看编译是否通过,可以省略该步,不影响安装make check// 安装make install卸载通过二进制安装的程序:// 方式一: 在编译目录里执行卸载make uninstall// 方式二:找到安装目录,然后删除,如nettle程序$find / -name nettle/usr/include/nettlerm -rf /usr/include/nettlewget不支持https我们可以在mysql官网下载最新版本的mysql8.0.13二进制文件,注意官网提供的下载链接是https协议的,当我们在服务器执行下载命令:// 使用wget或者curl来下载文件wget https://dev.mysql.com/downloads/file/?id=480751curl -O https://dev.mysql.com/downloads/file/?id=480751会报错:// wget 加上–no-check-certificate 依然不可以$wget https://dev.mysql.com/downloads/file/?id=480751--2018-12-12 16:57:54– https://dev.mysql.com/downloads/file/?id=480751Resolving dev.mysql.com (dev.mysql.com)… 137.254.60.11Connecting to dev.mysql.com (dev.mysql.com)|137.254.60.11|:443… connected.GnuTLS: A TLS fatal alert has been received.GnuTLS: received alert [40]: Handshake failedUnable to establish SSL connection.// curl 加上–insecure依然不可以$curl https://dev.mysql.com/downloads/file/?id=480751curl: (35) SSL connect error根据网上查询到的答案,原因均为版本过低,当前的版本不支持https协议的下载:So the error actually happens with www.coursera.org and the reason is missing support for SNI. You need to upgrade your version of wget.当前的版本:$wget –versionGNU Wget 1.16.3 built on linux-gnu.+digest +https +ipv6 +iri +large-file +nls +ntlm +opie -psl +ssl/gnutls Wgetrc: /usr/local/etc/wgetrc (system)Locale: /usr/local/share/locale Compile: gcc -DHAVE_CONFIG_H -DSYSTEM_WGETRC="/usr/local/etc/wgetrc" -DLOCALEDIR="/usr/local/share/locale" -I. -I../lib -I../lib -DHAVE_LIBGNUTLS -DNDEBUG Link: gcc -DHAVE_LIBGNUTLS -DNDEBUG -lpcre -lnettle -lgnutls -lz -lidn -lrt ftp-opie.o gnutls.o http-ntlm.o ../lib/libgnu.a Copyright (C) 2014 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later<http://www.gnu.org/licenses/gpl.html>.This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Originally written by Hrvoje Niksic <hniksic@xemacs.org>.Please send bug reports and questions to <bug-wget@gnu.org>.——————$curl.7.19.7 –versioncurl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.1.0 zlib/1.2.3 libidn/1.18 libssh2/1.2.2Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz wget升级既然是版本过低,升级即可,直接安装新版本的wget,然后卸载掉原有的wget文件即可。下载完成1.20版本之后// 获得文件wget-1.20.tar.gzwget http://mirror.sergal.org/gnu/wget/wget-1.20.tar.gz// 解压缩tar -xzvf wget-1.20.tar.gz// 进入解压后的文件夹cd wget-1.20// 开始配置./configure// 然而报错了:…checking for GNUTLS… noconfigure: error: Package requirements (gnutls) were not met:No package ‘gnutls’ foundConsider adjusting the PKG_CONFIG_PATH environment variable if youinstalled software in a non-standard prefix.Alternatively, you may set the environment variables GNUTLS_CFLAGSand GNUTLS_LIBS to avoid the need to call pkg-config.See the pkg-config man page for more details.报错信息显示我们没有安装gnutls依赖,需要继续进行安装,更为详细的报错信息,可以查看config.log:// 查看详细报错信息vim config.log…PKG_CONFIG=’/usr/local/bin/pkg-config’…configure:44443: checking for GNUTLSconfigure:44450: $PKG_CONFIG –exists –print-errors “gnutls"Package gnutls was not found in the pkg-config search path.Perhaps you should add the directory containing gnutls.pc'to the PKG_CONFIG_PATH environment variableNo package 'gnutls' foundconfigure:44453: $? = 1configure:44467: $PKG_CONFIG --exists --print-errors "gnutls"Package gnutls was not found in the pkg-config search path.Perhaps you should add the directory containing gnutls.pc’to the PKG_CONFIG_PATH environment variableNo package ‘gnutls’ foundconfigure:44470: $? = 1configure:44484: result: noNo package ‘gnutls’ foundconfigure:44500: error: Package requirements (gnutls) were not met:No package ‘gnutls’ foundConsider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GNUTLS_CFLAGS and GNUTLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.这里可以看出配置脚本实际是执行了:$ /usr/local/bin/pkg-config –exists –print-errors “gnutls"Package gnutls was not found in the pkg-config search path.Perhaps you should add the directory containing gnutls.pc'to the PKG_CONFIG_PATH environment variableNo package 'gnutls' found安装gnutls库gnutls全称 GNU Transport Layer Security Library,即基于GNU版权协议的传输层安全协议,是wget支持https中的ssl协议的基础库。我们可以在官方提供的镜像库里快速下载并安装:// 下载gnutls二进制文件wget http://www.ring.gr.jp/pub/net/gnupg/gnutls/v3.6/gnutls-3.6.4.tar.xz// 解压xz文件xz -d gnutls-3.6.4.tar.xztar -xvf gnutls-3.6.4.tarcd gnutls-3.6.4./configure// 报错:...checking for NETTLE... noconfigure: error: *** *** Libnettle 3.4 was not found.// 如果觉得可能不安全,可以下载md5签名文件验证文件,但是这个文件验证后发现签名过期了,所以没办法验证了wget http://www.ring.gr.jp/pub/net...gpg --verify gnutls-3.6.4.tar.xz.sig gnutls-3.6.4.targpg --recv-key F1679A65gpg --verify --verbose gnutls-3.6.4.tar.xz.sig gnutls-3.6.4.tar查看详细报错信息:$ vim config.log...configure:10032: checking for NETTLEconfigure:10039: $PKG_CONFIG --exists --print-errors "nettle &gt;= 3.4"Package nettle was not found in the pkg-config search path.Perhaps you should add the directory containing nettle.pc’to the PKG_CONFIG_PATH environment variableNo package ’nettle’ foundconfigure:10042: $? = 1configure:10056: $PKG_CONFIG –exists –print-errors “nettle >= 3.4"Package nettle was not found in the pkg-config search path.Perhaps you should add the directory containing nettle.pc'to the PKG_CONFIG_PATH environment variableNo package 'nettle' foundconfigure:10059: $? = 1configure:10073: result: noNo package 'nettle' foundconfigure:10090: error: *** *** Libnettle 3.4 was not found.结果显示我们需要3.4版本以上的Libnettle库,继续安装。安装Libnettle库Nettle库是用于跨平台的底层密码库,包含加密和解密的不同算法。我们下载并安装nettle库:wget ftp://ftp.gnu.org/gnu/nettle/nettle-3.4.1.tar.gztar -xzvf nettle-3.4.1.tar.gzcd nettle-3.4.1./configure// 安装成功...configure: summary of build options: Version: nettle 3.4.1 Host type: x86_64-unknown-linux-gnu ABI: 64 Assembly files: x86_64 Install prefix: /usr/local Library directory: ${exec_prefix}/lib64 Compiler: gcc Static libraries: yes Shared libraries: yes Public key crypto: no Using mini-gmp: no Documentation: yesmakemake install根据官方文档,我们安装完成后应该会有两个文件lib{hogweed,nettle}.so,然而我们只能发现其中一个:make install &amp;&amp;chmod -v 755 /usr/lib/lib{hogweed,nettle}.so &amp;&amp;install -v -m755 -d /usr/share/doc/nettle-3.4.1 &amp;&amp;install -v -m644 nettle.html /usr/share/doc/nettle-3.4.1$ ll | grep '\.so'-rwxr-xr-x 1 root root 3675341 Dec 12 19:15 libnettle.so$ ll | grep weed-rw-rw-r-- 1 work work 529 Dec 10 15:30 hogweed.pc-rw-r--r-- 1 work work 590 Nov 19 2017 hogweed.pc.in-rw-rw-r-- 1 work work 298 Dec 10 15:30 libhogweed.map-rw-r--r-- 1 work work 338 Nov 19 2017 libhogweed.map.in少了一个libhogweed.so文件,稍后我们编译gnutls时会发现这个导致的问题。继续编译gnutls既然nettle安装完成了,我们可以继续安装gnutls:./configure...configure: error: *** *** Libnettle 3.4 was not found.依然报错缺失库,但我们明明已经安装了,为什么找不到呢?我们用包管理工具查找一下:$ pkg-config --modversion nettlePackage nettle was not found in the pkg-config search path.Perhaps you should add the directory containing nettle.pc’to the PKG_CONFIG_PATH environment variableNo package ’nettle’ found我们找下这个nettle.pc刚才安装到哪里去了:$ locate nettle.pc/home/work/lib/nettle-3.4.1/nettle.pc/home/work/lib/nettle-3.4.1/nettle.pc.in/usr/lib64/pkgconfig/nettle.pc/usr/local/lib64/pkgconfig/nettle.pc而我们pkg-config默认的管理包检索路径为/usr/lib/pkgconfig,所以无法正常找到,参考pkgconfig文档,有两种方案:// 方案一:链接该文件到默认目录中ln -s /usr/local/lib64/pkgconfig/nettle.pc /usr/lib/pkgconfig/nettle.pc // 方案二:全局变量中更改包的检索路径(只在本次终端窗口生效,退出后恢复,所以只能临时使用一下)$ echo $PKG_CONFIG_PATH$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib64/pkgconfig/$ echo $PKG_CONFIG_PATH:/usr/local/lib64/pkgconfig/// 任一方案执行后结果$ pkg-config –modversion nettle3.4.1此时,我们继续安装:$ ./configure…checking for NETTLE… yeschecking for HOGWEED… noconfigure: error: *** *** Libhogweed (nettle’s companion library) was not found. Note that you must compile nettle with gmp support.可以看到,我们的nettle库已经安装成功,但是hogweed却检查没有找到,提示中也写明了libhogweed需要字gmp库已经安装完成的情况下重新编译nettle才可以被安装。有人提出过相关的问题,我们也可以从官网文档上更详细的知道这个Nettle对于libhogweed的依赖:5 LinkingNettle actually consists of two libraries, libnettle and libhogweed. The libhogweed library contains those functions of Nettle that uses bignum operations, and depends on the GMP library. With this division, linking works the same for both static and dynamic libraries.If an application uses only the symmetric crypto algorithms of Nettle (i.e., block ciphers, hash functions, and the like), it’s sufficient to link with -lnettle. If an application also uses public-key algorithms, the recommended linker flags are -lhogweed -lnettle -lgmp. If the involved libraries are installed as dynamic libraries, it may be sufficient to link with just -lhogweed, and the loader will resolve the dependencies automatically.总而言之,就是没有libhogweed.so这个文件不行,而它只能由nettle进行安装。根据nettle库官方资料显示,libhogweed.so应该在nettle安装时被自动生成,然而我们在上面的安装过程中并没有生成。那是不是因为我没有安装gmp导致的呢?安装gmp库我们下载gmp库并安装,可以在编译Nettle的config.log中查看有一条warning,指明了版本需求:$ vim config.log…configure:6583: result: noconfigure:6594: WARNING: GNU MP not found, or too old. GMP-6.0 or later is needed, see https://gmplib.org/. Support for public key algorithms will be unavailable.所以我们需要下载6.0版本后的:// 这里我只找到了官网的https版本,没办法,只好本地下载,然后rz到服务器,因为是二进制文件,要带上-be参数rz -be// 然后正常编译$ ./configure & make & make install…Libraries have been installed in: /usr/local/libIf you ever happen to want to link against installed librariesin a given directory, LIBDIR, you must either use libtool, andspecify the full pathname of the library, or use the ‘-LLIBDIR’flag during linking and do at least one of the following: - add LIBDIR to the ‘LD_LIBRARY_PATH’ environment variable during execution - add LIBDIR to the ‘LD_RUN_PATH’ environment variable during linking - use the ‘-Wl,-rpath -Wl,LIBDIR’ linker flag - have your system administrator add LIBDIR to ‘/etc/ld.so.conf’这里提醒我们需要将动态库链接到缓存中,我们采用第四种方案,可以参考ldconfig命令:$ vim /etc/ld.so.conf// 添上安装的.so文件路径/usr/local/lib:wq$ ldconfig$ ldconfig -v | grep gmp libgmp.so.10 -> libgmp.so.10.3.2 libgmpxx.so.4 -> libgmpxx.so.4.1.0 libgmp.so.3 -> libgmp.so.3.5.0看到libgmp.so.10就是我们安装的最新版本,现在OK了。然后重新编译安装nettle,会生成libhogweed.so文件:$ ll | grep weed-rw-r–r– 1 root root 541 Dec 12 22:12 hogweed.pc-rw-r–r– 1 work work 590 Nov 19 2017 hogweed.pc.in-rw-r–r– 1 root root 6154192 Dec 12 22:13 libhogweed.a-rw-r–r– 1 root root 298 Dec 12 22:12 libhogweed.map-rw-r–r– 1 work work 338 Nov 19 2017 libhogweed.map.in-rwxr-xr-x 1 root root 5519996 Dec 12 22:13 libhogweed.so-rw-r–r– 1 root root 8 Dec 12 22:13 libhogweed.stamp请注意如果安装完成后,如果出现多个版本的gmp库,请删除老版本的。具体删除哪一项请自行斟酌,我删除了所有的,然后在编译的过程中,会报错:can’t find libgmp.so.3,说明libgmp.so.3这个是基础库,请不要动!等我删除了老版本的,重新编译nettle就OK。如果你安装成功了新版本,依然编译不成功,请参考这个。恐怖的依赖地狱用二进制来安装的时候,总是会出现各种各样的问题,缺少各种依赖的包,解决方法就是缺什么就去安什么,但是会非常恐怖。为了解决nettle安装的问题,除了上面的gmp,我还安装了最新版本的各种库:libunistring: https://www.gnu.org/software/...p11-kit:https://github.com/p11-glue/p…libffi:https://sourceware.org/libffi/pkg-config: https://pkg-config.freedeskto...libtasn1: https://ftp.gnu.org/gnu/libta…同时,由于gnutls编译不通过的问题,又升级了pkg-config,它依赖于Libtasn1。继续安装gnutls库(失败、暂时放弃更新)./configure// 此时没有错误信息了,但是还有很多WARNING信息*** autogen not found. Will not link against libopts.*** You will not be able to create source packages with ‘make dist’ because gtk-doc >= 1.14 is not found.*** LIBIDN2 was not found. You will not be able to use IDN2008 support*** libunbound was not found. Libdane will not be built.*** trousers was not found. TPM support will be disabled.*** `guile-snarf’ from Guile not found. Guile bindings not built.*** The DNSSEC root key file in /etc/unbound/root.key was not found.*** This file is needed for the verification of DNSSEC responses.*** Use the command: unbound-anchor -a “/etc/unbound/root.key”*** to generate or update it.// 继续编译,又报错了make…tlsproxy/buffer.c:40: error: redefinition of typedef ‘buffer_t’tlsproxy/buffer.h:31: note: previous declaration of ‘buffer_t’ was here暂时放弃更新wget,过几天继续尝试,解决各种问题太费时间了如果想要减少warning信息,可以更新autogen等库:autogen: https://ftp.gnu.org/gnu/autog...guile: http://alpha.gnu.org/gnu/guile/gcc: http://ftp.tsukuba.wide.ad.jp...mpc: https://ftp.gnu.org/gnu/mpc/安装autogen过程中需要依赖guile,然而安装guile时又报错:guile configure: error: Cannot find a type to use in place of socklen_t放弃更新autogen。尝试curl更新,层层依赖,放弃$ curl https://dev.mysql.com/downloads/file/?id=480751curl: (35) SSL connect error根据报错原因和网上资料是由于版本过老,需要更新curl版本。从官方地址下载curl后安装,再次用新版本的curl请求:$ curl https://dev.mysql.com/downloads/file/?id=480751curl: (35) error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure还是报错,根据上面的资料,如果依然不能解决问题,需要更新NSS,NSS和OpenSSl类似,都属于底层密码学,由Mozilla维护,MDN文档提供安装说明,它跟前面的二进制文件略有不同,不提供configure自动配置,详细的查看它的文档。安装NSS库比较麻烦,还需要再安装GYP库,想起来又是层层嵌套的依赖关系,放弃更新。解决方案:本地下载,rz上传在耗费两天的时间后,我及时的终止了无畏的尝试,转而使用本地下载mysql8.0文件,然后rz -be上传到服务器,搞定。结论:Linux上层层依赖的二进制文件安装简直是地狱版的体验,在给我们带来高自由度的同时也有无尽的烦恼,然而yum安装版本又过低,不能满足需求。虽然最终还是没有成功更新wget或者curl,但是在整个过程中,也学习到了很多的新东西,在这篇文章总结一下过程,希望也能帮助一些人在某一步骤遇到的问题。解决问题整体思路和过程参考资料mysql8.0官网下载地址:https://dev.mysql.com/downloa…Mysql三种安装方式详解:https://www.jianshu.com/p/a04…[StackOverFlow] wget ssl alert handshake failure:https://stackoverflow.com/que…卸载二进制程序:http://www.blogjava.net/zhyiw…wget下载地址:http://mirror.sergal.org/gnu/…gnutls下载地址:http://www.ring.gr.jp/pub/net…利用.sig文件验证数据的完整性:https://blog.csdn.net/xiazhiy…下载安装nettle http://www.linuxfromscratch.o...nettle官方文档:http://www.lysator.liu.se/~ni…gmp下载地址:https://gmplib.org/ldconfig命令:http://man.linuxde.net/ldconfigSecureCRT rz 上传文件失败问题:https://blog.csdn.net/heavend…初识NSS,一文了解全貌:https://cloud.tencent.com/dev…MDN文档 NSS:https://developer.mozilla.org…curl: (35) SSL connect error:https://stackoverflow.com/que…简述configure、pkg-config、pkg_config_path三者的关系:http://www.mike.org.cn/articl…How to compile GnuTLS: https://stackoverflow.com/que… ...

December 13, 2018 · 6 min · jiezi