Blog

bash-日常命令总结

lsof  -i:443

/usr/share/nginx/html
/etc/nginx/conf.d
/var/log/nginx/error.log
 
vim  /etc/nginx/conf.d/www.huaijiujia.com.conf

systemctl restart nginx 


[root@superguy ~]# hostnamectl  set-hostname amazon.com
[root@superguy ~]# 
## 非 ss 流量端口 转发
--failover www.amazon.com:443

vim /etc/php-fpm.d/www.conf
systemctl restart php-fpm


 chmod 777 /dev/shm/php-fcgi.sock
  ls -al  /dev/shm/php-fcgi.sock


 top
 journalctl -xe


vim /etc/systemd/system/obfs-server.service
systemctl daemon-reload
systemctl restart obfs-server

 

密码和证书-https(ssl/tls)之协议概述和运行机制

一、相关加密算法

1)对称加密算法:就是加密和解密使用同一个密钥的加密算法。因为加密方和解密方使用的密钥相同,所以称为称为对称加密,也称为单钥加密方法。

优点是:加密和解密运算速度快,所以对称加密算法通常在消息发送方需要加密大量数据时使用;
缺点是:安全性差,如果一方的密钥遭泄露,那么整个通信就会被破解。另外加密之前双方需要同步密钥;
常用对称加密算法有:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等;

2)非对称加密算法:而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。

公钥和私钥是一对:公钥用来加密,私钥解密,而且公钥是公开的,私钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。

优点是:安全性更好,私钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。
缺点是:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
常用的非对称加密算法有:RSA、Elgamal、Rabin、D-H、ECC等;

3)HASH算法:也称为消息摘要算法。将任意长度的二进制值映射为较短的固定长度的二进制值,该二进制值称为哈希值。

常用于检验数据的完整性,检验数据没有被篡改过。常见的又 MD5(MD系列),SHA-1(SHA系列)

二、HTTP概述

首先,HTTP 是一个网络协议,是专门用来帮你传输 Web 内容滴。关于这个协议,就算你不了解,至少也听说过吧?比如访问百度主页,浏览器地址栏会出现如下的网址
http://www.baidu.com/
俺加了粗体的部分就是指 HTTP 协议。大部分网站都是通过 HTTP 协议来传输 Web 页面、以及 Web 页面上包含的各种东东(图片、CSS 样式、JS 脚本)。

 2.1. HTTP 的版本和历史
如今咱们用的 HTTP 协议,版本号是 1.1(也就是 HTTP 1.1)。这个 1.1 版本是1995年底开始起草的(技术文档是 RFC2068),并在1999年正式发布(技术文档是 RFC2616)。
在 1.1 之前,还有曾经出现过两个版本“0.9 和 1.0”,其中的 HTTP 0.9 【没有】被广泛使用,而 HTTP 1.0 被广泛使用过。
另外,2015年 IETF 发布了 HTTP 2.0 (技术文档是 RFC7540

 2.2. HTTP 和 TCP 之间的关系
简单地说,TCP 协议是 HTTP 协议的基石——HTTP 协议需要依靠 TCP 协议来传输数据。
在网络分层模型中,TCP 被称为“传输层协议”,而 HTTP 被称为“应用层协议”。有很多常见的应用层协议是以 TCP 为基础的,比如“FTP、SMTP、POP、IMAP”等。
TCP 被称为“面向连接”的传输层协议。关于它的具体细节,俺就不展开了(否则篇幅又失控了)。你只需知道:传输层主要有两个协议,分别是 TCP 和 UDP。TCP 比 UDP 更可靠。你可以把 TCP 协议想象成某个水管,发送端这头进水,接收端那头就出水。并且 TCP 协议能够确保,先发送的数据先到达(与之相反,UDP 不保证这点)。

 2.3. HTTP 协议如何使用 TCP 连接?
HTTP 对 TCP 连接的使用,分为两种方式:俗称“短连接”和“长连接”(“长连接”又称“持久连接”,洋文叫做“Keep-Alive”或“Persistent Connection”)
假设有一个网页,里面包含好多图片,还包含好多【外部的】CSS 文件和 JS 文件。在“短连接”的模式下,浏览器会先发起一个 TCP 连接,拿到该网页的 HTML 源代码(拿到 HTML 之后,这个 TCP 连接就关闭了)。然后,浏览器开始分析这个网页的源码,知道这个页面包含很多外部资源(图片、CSS、JS)。然后针对【每一个】外部资源,再分别发起一个个 TCP 连接,把这些文件获取到本地(同样的,每抓取一个外部资源后,相应的 TCP 就断开)
相反,如果是“长连接”的方式,浏览器也会先发起一个 TCP 连接去抓取页面。但是抓取页面之后,该 TCP 连接并不会立即关闭,而是暂时先保持着(所谓的“Keep-Alive”)。然后浏览器分析 HTML 源码之后,发现有很多外部资源,就用刚才那个 TCP 连接去抓取此页面的外部资源。

在 HTTP 1.0 版本,【默认】使用的是“短连接”(那时候是 Web 诞生初期,网页相对简单,“短连接”的问题不大);
到了1995年底开始制定 HTTP 1.1 草案的时候,网页已经开始变得复杂(网页内的图片、脚本越来越多了)。这时候再用短连接的方式,效率太低下了(因为建立 TCP 连接是有“时间成本”和“CPU 成本”滴)。所以,在 HTTP 1.1 中,【默认】采用的是“Keep-Alive”的方式。
关于“Keep-Alive”的更多介绍,可以参见维基百科词条(在“这里”)

三、SSL/TLS概述

SSL 是洋文“Secure Sockets Layer”的缩写,中文叫做“安全套接层”。它是在上世纪90年代中期,由网景公司设计的。(顺便插一句,网景公司不光发明了 SSL,还发明了很多 Web 的基础设施——比如“CSS 样式表”和“JS 脚本”)
为啥要发明 SSL 这个协议捏?因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点——比如传输内容会被偷窥(嗅探)和篡改。发明 SSL 协议,就是为了解决这些问题。
到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。
很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布。
1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞。
1996年,SSL 3.0版问世,得到大规模应用。
1999年,互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版TLS 1.0版。
2006年和2008年,TLS进行了两次升级,分别为TLS 1.1版和TLS 1.2版。最新的变动是2011年TLS 1.2的修订版。

目前,应用最广泛的是TLS 1.0,接下来是SSL 3.0。但是,主流浏览器都已经实现了TLS 1.2的支持。
TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。

四、CA证书概述

数字证书 里面存放了公钥,(采用数字证书是为了防止别人篡改非对称加密算法的公钥,保证公钥的可信)具体可参见密码和证书-https(ssl/tls)之证书的概述及获取和网站部署

五、https概述

HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过SSL / TLS进行加密,所以传输的数据都是加密后的数据。

不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险。

(1) 窃听风险(eavesdropping):第三方可以获知通信内容。
(2) 篡改风险(tampering):第三方可以修改通信内容。
(3) 冒充风险(pretending):第三方可以冒充他人身份参与通信。

SSL/TLS协议是为了解决这三大风险而设计的,希望达到:

(1) 所有信息都是加密传播,第三方无法窃听。
(2) 具有校验机制,一旦被篡改,通信双方会立刻发现。
(3) 配备身份证书,防止身份被冒充。

互联网是开放环境,通信双方都是未知身份,这为协议的设计带来了很大的难度。而且,协议还必须能够经受所有匪夷所思的攻击,这使得SSL/TLS协议变得异常复杂。


★HTTPS 协议的需求是啥?

花了好多口水,终于把背景知识说完了。下面正式进入正题。先来说说当初设计 HTTPS 是为了满足哪些需求?
很多介绍 HTTPS 的文章一上来就给你讲实现细节。个人觉得:这是不好的做法。早在2009年开博的时候,发过一篇《学习技术的三部曲:WHAT、HOW、WHY》,其中谈到“WHY 型问题”的重要性。一上来就给你讲协议细节,你充其量只能知道 WHAT 和 HOW,无法理解 WHY。俺在前一个章节讲了“背景知识”,在这个章节讲了“需求”,这就有助于你理解:当初为什么要设计成这样?——这就是 WHY 型的问题。

◇兼容性

因为是先有 HTTP 再有 HTTPS。所以,HTTPS 的设计者肯定要考虑到对原有 HTTP 的兼容性。
这里所说的兼容性包括很多方面。比如已有的 Web 应用要尽可能无缝地迁移到 HTTPS;比如对浏览器厂商而言,改动要尽可能小;……
基于“兼容性”方面的考虑,很容易得出如下几个结论:
1. HTTPS 还是要基于 TCP 来传输
(如果改为 UDP 作传输层,无论是 Web 服务端还是浏览器客户端,都要大改,动静太大了)
2. 单独使用一个新的协议,把 HTTP 协议包裹起来
(所谓的“HTTP over SSL”,实际上是在原有的 HTTP 数据外面加了一层 SSL 的封装。HTTP 协议原有的 GET、POST 之类的机制,基本上原封不动)

打个比方:如果原来的 HTTP 是塑料水管,容易被戳破;那么如今新设计的 HTTPS 就像是在原有的塑料水管之外,再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了之后,不容易被戳破。

◇可扩展性

前面说了,HTTPS 相当于是“HTTP over SSL”。
如果 SSL 这个协议在“可扩展性”方面的设计足够牛逼,那么它除了能跟 HTTP 搭配,还能够跟其它的应用层协议搭配。岂不美哉?
现在看来,当初设计 SSL 的人确实比较牛。如今的 SSL/TLS 可以跟很多常用的应用层协议(比如:FTP、SMTP、POP、Telnet)搭配,来强化这些应用层协议的安全性。

接着刚才打的比方:如果把 SSL/TLS 视作一根用来加固的金属管,它不仅可以用来加固输水的管道,还可以用来加固输煤气的管道。

◇保密性(防泄密)

HTTPS 需要做到足够好的保密性。
说到保密性,首先要能够对抗嗅探(行话叫 Sniffer)。所谓的“嗅探”,通俗而言就是监视你的网络传输流量。如果你使用明文的 HTTP 上网,那么监视者通过嗅探,就知道你在访问哪些网站的哪些页面。
嗅探是最低级的攻击手法。除了嗅探,HTTPS 还需要能对抗其它一些稍微高级的攻击手法——比如“重放攻击”(后面讲协议原理的时候,会再聊)。

◇完整性(防篡改)

除了“保密性”,还有一个同样重要的目标是“确保完整性”。关于“完整性”这个概念,在之前的博文《扫盲文件完整性校验——关于散列值和数字签名》中大致提过。健忘的同学再去温习一下。
在发明 HTTPS 之前,由于 HTTP 是明文的,不但容易被嗅探,还容易被篡改。
举个例子:
比如咱们天朝的网络运营商(ISP)都比较流氓,经常有网友抱怨说访问某网站(本来是没有广告的),竟然会跳出很多中国电信的广告。为啥会这样捏?因为你的网络流量需要经过 ISP 的线路才能到达公网。如果你使用的是明文的 HTTP,ISP 很容易就可以在你访问的页面中植入广告。
所以,当初设计 HTTPS 的时候,还有一个需求是“确保 HTTP 协议的内容不被篡改”。

◇真实性(防假冒)

在谈到 HTTPS 的需求时,“真实性”经常被忽略。其实“真实性”的重要程度不亚于前面的“保密性”和“完整性”。
举个例子:
你因为使用网银,需要访问该网银的 Web 站点。那么,你如何确保你访问的网站确实是你想访问的网站?(这话有点绕口令)
有些天真的同学会说:通过看网址里面的域名,来确保。为啥说这样的同学是“天真的”?因为 DNS 系统本身是不可靠的(尤其是在设计 SSL 的那个年代,连 DNSSEC 都还没发明)。由于 DNS 的不可靠(存在“域名欺骗”和“域名劫持”),你看到的网址里面的域名【未必】是真实滴!
(不了解“域名欺骗”和“域名劫持”的同学,可以参见俺之前写的《扫盲 DNS 原理,兼谈“域名劫持”和“域名欺骗/域名污染”》)
所以,HTTPS 协议必须有某种机制来确保“真实性”的需求(至于如何确保,后面会细聊)。

◇性能

再来说最后一个需求——性能。
引入 HTTPS 之后,【不能】导致性能变得太差。否则的话,谁还愿意用?
为了确保性能,SSL 的设计者至少要考虑如下几点:
1. 如何选择加密算法(“对称”or“非对称”)?
2. 如何兼顾 HTTP 采用的“短连接”TCP 方式?
(SSL 是在1995年之前开始设计的,那时候的 HTTP 版本还是 1.0,默认使用的是“短连接”的 TCP 方式——默认不启用 Keep-Alive)

◇小结

以上就是设计 SSL 协议时,必须兼顾的各种需求。后面聊协议的实现时,俺会拿 SSL 协议的特点跟前面的需求作对照。看看这些需求是如何一一满足滴。

★设计 HTTPS 协议的主要难点

设计 HTTPS 这个协议,有好几个难点。俺个人认为最大的难点在于“密钥交换”。
在传统的密码学场景中,假如张三要跟李四建立一个加密通讯的渠道,双方事先要约定好使用哪种加密算法?同时也要约定好使用的密钥是啥?在这个场景中,加密算法的【类型】让旁人知道,没太大关系。但是密钥【千万不能】让旁人知道。一旦旁人知道了密钥,自然就可以破解通讯的密文,得到明文。
好,现在回到 HTTPS 的场景。
当你访问某个公网的网站,你的浏览器和网站的服务器之间,如果要建立加密通讯,必然要商量好双方使用啥算法,啥密钥。——在网络通讯术语中,这个过程称之为“握手/handshake”。在握手阶段,因为加密方式还没有协商好,所以握手阶段的通讯必定是【明文】滴!既然是明文,自然有可能被第三方偷窥到。然后,还要考虑到双方之间隔着一个互联网,什么样的偷窥都可能发生。
因此,在握手的过程中,如何做到安全地交换密钥信息,而不让周围的第三方看到。这就是设计 HTTPS 最大的难点。

★结尾

本文费这么多口水,来介绍 HTTPS 的“需求”和“难点”,为啥捏?因为只有当你了解这些,后面介绍 SSL/TLS 的实现原理时,你才能理解——当初为啥要把协议设计成这个样子。

五、https基本运行过程

1)利用对称加密算法来加密网页内容,那么如何保证对称加密算法的秘钥的安全呢?

2)使用非对称加密算法来获得对称加密算法的秘钥,从而保证了对称加密算法的秘钥的安全,也就保证了对称加密算法的安全。

这里这样安排使用的原理是,利用了对称加密算法和非对称加密算法优点,而避免了它们的缺点。利用了对称加密算法速度快,而非对称加密算法安全的优点;同时巧妙的避免了对称加密算法的不安全性,以及需要同步密钥的缺点,也避免了非对称加密算法的速度慢的缺点。实在是巧妙了。

这里有两个问题:

(1)如何保证非对称加密算法公钥不被篡改?

解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。

(2)公钥加密计算量太大,如何减少耗用的时间?

解决方法:每一次对话(session),客户端和服务器端都生成一个”对话密钥”(session key),用它来加密信息。由于”对话密钥”是对称加密算法,所以运算速度非常快,而服务器公钥只用于加密”对话密钥”本身,这样就减少了加密运算的消耗时间。(也就是网页内容的加密使用的是对称加密算法)

因此,SSL/TLS协议的基本过程是这样的:
(1) 客户端向服务器端索要并验证非对称加密算法的公钥。
(2) 双方协商生成对称加密算法的”对话密钥”。
(3) 双方采用对称加密算法和它的”对话密钥”进行加密通信。
上面过程的前两步,又称为”握手阶段”(handshake)。

大白话说明一下:

第一步,爱丽丝给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。

第二步,鲍勃确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。

第三步,爱丽丝确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给鲍勃。

第四步,鲍勃使用自己的私钥,获取爱丽丝发来的随机数(即Premaster secret)。

第五步,爱丽丝和鲍勃根据约定的加密方法,使用前面的三个随机数,生成”对话密钥”(session key),用来加密接下来的整个对话过程。

六、https握手阶段详解

“握手阶段”涉及四次通信:

1) 客户端发出请求(ClientHello)

首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。在这一步,客户端主要向服务器提供以下信息:

(1)浏览器支持的SSL/TLS协议版本,比如TLS 1.0版。

(2)一个浏览器客户端生成的随机数,稍后用于生成对称加密算法的"对话密钥"。

(3)浏览器支持的各种加密方法,对称的,非对称的,HASH算法。比如RSA非对称加密算法,DES对称加密算法,SHA-1 hash算法。

(4)浏览器支持的压缩方法。

这里需要注意的是,客户端发送的信息之中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应该向客户端提供哪一个网站的数字证书。
这就是为什么通常一台服务器只能有一张数字证书的原因。
对于虚拟主机的用户来说,这当然很不方便。2006年,TLS协议加入了一个Server Name Indication扩展[ 即 SNI 扩展],允许客户端向服务器提供它所请求的域名。

2) 服务器回应(SeverHello)

服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。服务器的回应包含以下内容:

(1)确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。

(2)一个服务器生成的随机数,稍后用于生成"对话密钥"。

(3)确认使用的加密方法,比如RSA公钥加密。

(4)服务器证书。

除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供”客户端证书”。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥【俗称K宝】,里面就包含了一张客户端证书。

3) 客户端回应

客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。

如果证书没有问题,客户端就会从证书中取出服务器的非对称加密算法的公钥。然后,向服务器发送下面三项信息。

(1)一个随机数。该随机数用服务器公钥加密,防止被窃听。

(2)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。

(3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。

上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称”pre-master key”。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把”会话密钥”。

至于为什么一定要用三个随机数,来生成”会话密钥”,dog250解释得很好:

“不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。

对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。

pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。”

此外,如果前一步,服务器要求客户端证书,客户端会在这一步发送证书及相关信息。

4) 服务器的最后回应

服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的对称加密算法的”会话密钥”。然后,向客户端最后发送下面信息。

(1)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。

(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用”会话密钥”加密内容。

七、session的恢复

握手阶段用来建立SSL连接。如果出于某种原因,对话中断,就需要重新握手。

这时有两种方法可以恢复原来的session:

一种叫做session ID:

session ID的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的”对话密钥”,而不必重新生成一把。

客户端给出session ID,服务器确认该编号存在,双方就不再进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通信。

另一种叫做session ticket:

session ID是目前所有浏览器都支持的方法,但是它的缺点在于session ID往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。session ticket就是为了解决这个问题而诞生的,目前只有Firefox和Chrome浏览器支持。

客户端不再发送session ID,而是发送一个服务器在上一次对话中发送过来的session ticket。这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket以后,解密后就不必重新生成对话密钥了。

八、其他补充

8.1 请考虑介绍下常用于SPDY的HTTPS falst start握手,它比标准的握手少一个“server finished”的步骤。经过debug测试,发现SPDY+HTTPS false start握手确实比标准的SSL/TLS少一次握手,最后一次服务器到客户端的握手是没有的,第一次Finished后就可以传输数据了。

8.2 第三个随机数客户端是用公钥加密的然后在发送给服务端,服务端用私钥解密获取随机数。客户端和服务端用约定加密方法使用三个随机数生成对话密钥。

8.3 整个握手阶段都不加密(也没法加密),都是明文的。因此,如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret)能不能被破解。

虽然理论上,只要服务器的公钥足够长(比如2048位),那么Premaster secret可以保证不被破解。但是为了足够安全,我们可以考虑把握手阶段的算法从默认的RSA算法,改为 Diffie-Hellman算法(简称DH算法)。

采用DH算法后,Premaster secret不需要传递,双方只要交换各自的参数,就可以算出这个随机数。

九、总结

本文如果结合 HTTPS连接的前几毫秒发生了什么 一起来理解HTTPS,将理解的更加深入。

1)HTTPS 结合使用了 非对称加密算法,对称加密算法,hash算法,分别利用他们的优势,避免他们的缺点。利用非对称加密算法获得对称加密算法的秘钥,保证他的安全性;然后实际的网页内容的加密使用的是对称加密算法,利用了对称加密算法速度快的优势,hash算法主要是防止篡改的发生,是一种校验机制,最后数字证书,保证了服务器在将非对称加密算法的公钥传给浏览器时的安全性(不会被中间人篡改),同时也标志了服务器的身份

2)HTTPS的四大金刚:

非对称加密算法(对称加密算法的秘钥) + 对称加密算法(加密内容) + 数字证书(防止篡改非对称加密算法的公钥) + HASH算法(防止篡改消息)== HTTPS

3)HTTPS的本质是什么?

HTTPS的本质就是在HTTP连接发起之前,先使用SSL/TLS协议,协调客户端和服务端,在两端各自生产一个对称加密算法的秘钥,然后使用普通的HTTP协议传输 经过对称加密算法加密的网页内容。因为对称加密算法的秘钥是安全的,所以对称加密算法加密的网页内容也是安全的。

 


参考:

http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

https://www.cnblogs.com/digdeep/p/4832885.html

http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html

https://program-think.blogspot.com/2014/11/https-ssl-tls-1.html

 

wordpress-从http迁移到https

一、获取并配置 https 证书

1、密码和证书-https(ssl/tls)之证书的概述及获取和网站部署 ,使网站能够通过https访问。

2、配置服务器,将网站从 http 跳转到 https。

### nginx 服务器 http 跳转 https 的配置如下
server {
listen     80;
server_name  www.huaijiujia.com;
return 301 https://www.huaijiujia.com$request_uri;
  }

二、编辑 wp-config.php 文件

# 添加下面这句话,使php网站 从 http 强制跳转到 https
define('FORCE_SSL_ADMIN', true);

三、其他操作

If that worked fine, now it’s time to do the last few steps to complete the transfer to HTTPS:

  • Update your sitemap — Ideally, your SEO plugin does this automatically. However, it doesn’t always work that way. With Yoast SEO you might have to switch off the plugin once for it to update the sitemap. Don’t forget to include it in your robots.txt file and update all other hardcoded links you might have there.
  • Add site to your webmaster tools — Go to every webmaster tool you are using and add the HTTPS version of your site as a new property. While you are there, upload the new sitemap. You might also consider doing a fetch and crawl and submit any disavow files that are already active for the old version of your site.
  • Update your CDN — If you are using a content delivery network (one of the ways to speed up your site), you also need to switch it to SSL. Many of them have that feature built in and your CDN should have documentation on this. Otherwise, ask their support to help you.
  • Make the switch in your analytics — If your analytics need a default URL, make sure to upgrade it with the new prefix. For Google Analytics, you find the option under Admin > Property Settings > Default URL. Also, note down when you made the switch to HTTPS to understand traffic changes.
  • Preserve social share counts — If you show social share counters on your site, you might have to make some changes in order to keep them up to date. Check this guide for details. Don’t forget to update the links to your site in your social profiles! And do the same in your email templates.

参考自:https://websitesetup.org/http-to-https-wordpress/#comment-131467

javascript练手-简单日历实现

样式表:

<style>
.cld-cur{
color:#6ac13c;
border:1px solid #6ac13c;
background:#e9f8df;
}
</style>

网页布局:

<div id=calendar></div>

JavaScript代码

//判断闰年
function runNian(_year) {
    if(_year%400 === 0 || (_year%4 === 0 && _year%100 !== 0) ) {
        return true;
    }
    else { return false; }
}
//判断某年某月的1号是星期几
function getFirstDay(_year,_month) {
    var allDay = 0, y = _year-1, i = 1;
    allDay = y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400) + 1;
    for ( ; i<_month; i++) {
        switch (i) {
            case 1: allDay += 31; break;
            case 2: 
                if(runNian(_year)) { allDay += 29; }
                else { allDay += 28; }
                break;
            case 3: allDay += 31; break;
            case 4: allDay += 30; break;
            case 5: allDay += 31; break;
            case 6: allDay += 30; break;
            case 7: allDay += 31; break;
            case 8: allDay += 31; break;
            case 9: allDay += 30; break;
            case 10: allDay += 31; break;
            case 11: allDay += 30; break;
            case 12: allDay += 31; break;
        }
    }
    return allDay%7;
}
//显示日历
function showCalendar(_year,_month,_day,firstDay) {
    var i = 0,
        monthDay = 0,
        showStr = "",
        _classname = "",
        today = new Date();
        //月份的天数
    switch(_month) {
        case 1: monthDay = 31; break;
        case 2:
            if(runNian(_year)) { monthDay = 29; }
            else { monthDay = 28; }
            break;
        case 3: monthDay = 31; break;
        case 4: monthDay = 30; break;
        case 5: monthDay = 31; break;
        case 6: monthDay = 30; break;
        case 7: monthDay = 31; break;
        case 8: monthDay = 31; break;
        case 9: monthDay = 30; break;
        case 10: monthDay = 31; break;
        case 11: monthDay = 30; break;
        case 12: monthDay = 31; break;
    }

    //输出日历表格,这部分因结构而异
    showStr = "<table class='cld-w'><thead>";
    //日历头部
    showStr += "<tr><th colspan='7'><div class='cld-hd'><span class='cld-pre'>&lt;</span><em id='showDate' value='" + _year + "-" + _month + "-" + _day + "'>" + _year + "年" + _month + "月" + _day + "日" + "</em><span class='cld-next'>&gt;</span></div></th></tr>";
    //日历星期
    showStr += "<tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr>";
    showStr += "</thead><tbody><tr>";
    //当月第一天前的空格
    for (i=1; i<=firstDay; i++) {
        showStr += "<td></td>";
    }
    //显示当前月的天数
    for (i=1; i<=monthDay; i++) {
        //当日的日期
        if(_year === today.getFullYear() && _month === today.getMonth()+1 && i === today.getDate()) {
            _classname = "cld-cur"; 
        } 
        //当日之前的日期(这个判断是因为我有工作需求,就是要求之前的日期不能点击)
        else if(_year < today.getFullYear() || (_year === today.getFullYear() && _month <= today.getMonth()) || (_year === today.getFullYear() && _month === today.getMonth()+1 && i < today.getDate()) ) {
            _classname = "cld-old";
        }
        //其他普通的日期
        else { _classname = "cld-day"; }
        //其他大于当月的月份的相同日期(为了让点击下一月的时候,相同的日期增加cld-cur类)
        if(_day === i && (_year > today.getFullYear() || _month > today.getMonth()+1)) { _classname = "cld-cur"; }
        //把日期存在对应的value       
        showStr += "<td class=" + _classname + " value='" + _year + "-" + _month + "-" + i + "'>" + i + "</td>";

        firstDay = (firstDay+1)%7;
        if(firstDay === 0 && i !== monthDay) {
            showStr += "</tr><tr>";
        } 
    }
    
    //剩余的空格
    if(firstDay!==0) {
        for (i=firstDay; i<7; i++) {
            showStr += "<td></td>";
        }
    }
        
    showStr +="</tr></tbody></table>";
    //插入calendar的页面结构里
    calendar.innerHTML = showStr;
}
//显示年月日
function showDate(_year,_month,_day) {
    var date = "", firstDay = getFirstDay(_year,_month,_day);
    if(_day !== 0) {
        date = _year + "年" + _month + "月" +_day + "日";
    }
    else { date = "No Choose."; }
    document.getElementById("showDate").innerHTML = date; //日历头部显示
    showCalendar(_year,_month,_day,firstDay);         //调用日历显示函数
}
//上一月
function preMonth(_year,_month,_day) {
    if(_month == 1) { showDate(_year - 1,12,_day); }
    else { showDate(_year,_month - 1,_day); }
}
//下一月
function nextMonth(_year,_month,_day) {
    if(_month == 12) { showDate(_year + 1,1,_day); }
    else { showDate(_year,_month + 1,_day); }
}
//初始化
var calendar = document.createElement('div');
calendar.setAttribute('id','showCld');
document.getElementById("calendar").appendChild(calendar); //增加到你的calendar里

//获取当天的年月日    
var today = new Date();
var _year = today.getFullYear(),
    _month = today.getMonth() + 1,
    _day = today.getDate();
var firstDay = getFirstDay(_year,_month);

//显示日历
showCalendar(_year,_month,_day,firstDay);


//日历点击的事件委托(可以查查js冒泡的应用)
calendar.onclick = function(e) {
    var e = e || window.event;
    var target = e.srcElement || e.target;
//把日历的头部的年月日分割成数组,这里保存在其value属性上
    dayArr = document.getElementById('showDate').getAttribute('value').split('-');
    if (target) {
        //如果是可点击的日期
        if ( target.className === "cld-day" || target.className === "cld-cur" ) {
            dateArr = target.getAttribute('value').split('-');
            //减0是把字符串转化成数值类型,以下一样            
            showDate(dateArr[0]-0,dateArr[1]-0,dateArr[2]-0);
            calendar.className = "";
        } 
        //如果是上一月的点击
        else if ( target.className === "cld-pre" ) {
            preMonth(dayArr[0]-0,dayArr[1]-0,dayArr[2]-0);
        }
        //如果是下一月的点击
        else if ( target.className === "cld-next" ) {
            nextMonth(dayArr[0]-0,dayArr[1]-0,dayArr[2]-0);
        }
    }
};

参考自:https://www.cnblogs.com/xinghh/p/3499375.html

bash-规范-特别要注意的和其他语言的不同点

一、shell脚本特别注意点

su root  可以切换成root 用户

shell编程

变量赋值时,等号两侧不能有空格!!!


注意 expr 运算符间要有空格 expr a + b

 条件判断 : [ a>b ]      []条件框 前后都要有空格
  注意:$[] 这个 是获取表达式结果   []前后 不需要空格 

(())  出现在 运算式  循环式 中


while 循环后面 别忘记 打空格
while [ 条件判断式 ] do
程序
done


===================================

9.test或[]的使用,也不一定要有if

例如

#!/bin/bash

var1=20

var2=22


[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"

home=/home

[ -d $home ] || echo "$home directory does not exist"

 

注意:

&&:前一个操作失败,后一个就不再执行

||   : 前一个操作成功,后一个就不再执行
===================================

在实际使用时,下面两种写法都是正确的。
date    "+%Y_%m_%d_%H%M%S"
date     +%Y_%m_%d_%H%M%S




 ${ } 的一些特异功能:
${变量名} 和 $变量名   效果是一样的,只是为了显示好看点。

假设我们定义了一个变量为:
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 .  及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 .  及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 .  及其右边的字符串:/dir1/dir2/dir3/my

 

mysql问题-启用ssl加密连接数据库时报错

本地网站连接本地mysql  ssl是支持的不会报错

jdbc.url=jdbc:mysql://localhost:3306/ssmcrud?useUnicode=true&characterEncoding=UTF-8&useSSL=true

本地网站连接别的主机的mysql时,出现报错:

jdbc.url=jdbc:mysql://112.112.112.112:3306/ssmcrud?useUnicode=true&characterEncoding=UTF-8&useSSL=true

The last packet successfully received from the server was 764 milliseconds ago.  The last packet sent successfully to the server was 757 milliseconds ago.] with root cause

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)

mysql  useSSL=true 问题,因为安装 mysql的时候,它会在本机 导入本机mysql的证书,所以可以使用 ssl 连接本机mysql。但是当本机网站需要连接到别的主机时,本机没有对方的ssl证书,所以就报错了。

解决办法就是:去掉 &useSSL=true

jdbc.url=jdbc:mysql://112.112.112.112:3306/ssmcrud?useUnicode=true&characterEncoding=UTF-8

Tue Nov 06 15:51:39 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

redis安装配置-在centos上

一、redis安装

1、下载获得redis-3.0.4.tar.gz后将它放入我们的Linux目录/opt
2、/opt目录下,解压命令:tar -zxvf redis-3.0.4.tar.gz
3、解压完成后出现文件夹:redis-3.0.4,进入目录:cd redis-3.0.4
4、看到源码包中的 makefile ,直接控制台输入 make 命令编译源代码。
5、
报错1:找不到 gcc ,就直接yum安装 或者 用光盘安装,输入pwd 显示当前路径。
报错2:jomalloc/jomalloc.h 没有那个文件或目录,之前缺gcc编译报错留下残余文件造成的。make distclean 清除之前 make 失败生成的文件
6、编译成功后,输入 make install 安装命令。usr 目录是 程序安装目录 /usr/local/bin /etc 是配置文件目录。

二、编辑配置文件

1、找到redis的配置文件,编辑  成 damen=yes 【vim 进入行末尾 shift + 4 】
2、查找配置文件方法  –>    /etc/redis.conf

[root@superguy ~]# rpm -qa | grep -i redis
redis-3.2.12-1.el7.x86_64
[root@superguy ~]# rpm -ql redis-3.2.12-1.el7.x86_64
/etc/logrotate.d/redis
/etc/redis-sentinel.conf
/etc/redis.conf
/etc/systemd/system/redis-sentinel.service.d
/etc/systemd/system/redis-sentinel.service.d/limit.conf
/etc/systemd/system/redis.service.d
/etc/systemd/system/redis.service.d/limit.conf
/usr/bin/redis-benchmark
/usr/bin/redis-check-aof
/usr/bin/redis-check-rdb
/usr/bin/redis-cli
/usr/bin/redis-sentinel
/usr/bin/redis-server
/usr/lib/systemd/system/redis-sentinel.service
/usr/lib/systemd/system/redis.service
/usr/libexec/redis-shutdown
/usr/share/doc/redis-3.2.12
/usr/share/doc/redis-3.2.12/00-RELEASENOTES
/usr/share/doc/redis-3.2.12/BUGS
/usr/share/doc/redis-3.2.12/CONTRIBUTING
/usr/share/doc/redis-3.2.12/MANIFESTO
/usr/share/doc/redis-3.2.12/README.md
/usr/share/licenses/redis-3.2.12
/usr/share/licenses/redis-3.2.12/COPYING
/usr/share/man/man1/redis-benchmark.1.gz
/usr/share/man/man1/redis-check-aof.1.gz
/usr/share/man/man1/redis-check-rdb.1.gz
/usr/share/man/man1/redis-cli.1.gz
/usr/share/man/man1/redis-sentinel.1.gz
/usr/share/man/man1/redis-server.1.gz
/usr/share/man/man5/redis-sentinel.conf.5.gz
/usr/share/man/man5/redis.conf.5.gz
/var/lib/redis
/var/log/redis
/var/run/redis
[root@superguy ~]# 

三、运行redis服务

redis-server /etc/redis.conf

四、使用redis客户端

[root@superguy ~]# redis-cli
127.0.0.1:6379> exit
[root@superguy ~]# 

 

http协议-html与http的区别

大白话:html协议是  保存信息的  文档协议,http协议 是 传输信息的 传输协议。

在Web服务中,信息一般是使用HTML格式以超文本和超媒体方式传送的,所使用的Internet协议是HTTP协议。

HTTP  意为超文本传输协议(全称是Hypertext Transfer Protocol)。是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示等(如文本先于图形显示)。这就是我们为什么在浏览器中看到的网址都是以“http://”开头的原因。

HTML  释为超文本标记语言(全称是Hypertext Markup Language),是用于WWW上文档的格式化语言。使用HTML语言可以创建文本文档,该文档可以从一个平台移植到另一个平台。HTML文件是带有嵌入代码(由标记表示)的ASCII文本文件,它用来表示格式化和超文本链接。HTML文件的内容通过一个页面展示出来,不同页面通过超链接关联起来。

 

tomcat安装配置-基础入门

一、centos 安装tomcat软件包

# yum 安装
yum install tomcat
# 查看安装目录
rpm -ql tomcat

#发现 /var/lib/tomcat/webapps/  这个目录下面是空的

也就是说:centos安装的tomcat,是没有欢迎界面的。一开始打开浏览器访问,找不到tomcat的欢迎页,其实是服务器默认就没有欢迎页。

二、centos 安装tomcat源码包

Installing Apache Tomcat 9

We’ll have to create a system user and group before proceeding with the installation process of Tomcat so create a user and group named tomcat to run below-given command to do so:

groupadd tomcat useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat

The options used in the above command perform the following:

-s /bin/false will disable shell access -g tomcat will assign a new user to the group tomcat -d /opt/tomcat will define the home directory for the user

Downloading and Installing Apache Tomcat

First, go to the directory /opt and download Apache Tomcat server using wgetcommand from http://tomcat.apache.org as shown below:

cd /opt/

This will change your current directory to directory /opt/

If in any case you haven’t installed wget command on your system then first of all install it using this command:

yum install wgetwget http://www-eu.apache.org/dist/tomcat/tomcat-9/v9.0.0.M15/bin/apache-tomcat-9.0.0.M15.tar.gz

Now extract using tar command as below :

tar -xzvf apache-tomcat-9.0.0.M15.tar.gz

Move all the files that are in the apache-tomcat-9.0.0.M15 directory to the tomcatdirectory to do so run following command :

mv apache-tomcat-9.0.0.M15/* tomcat/

Now change the proper ownership using the following command:

chown -hR tomcat:tomcat tomcat

Testing Tomcat

We recommend you to run a short testing on Tomcat to make sure that there is no error and it is installed successfully so follow the below-given process.

Run below given command :

cd /opt/tomcat/bin/ ./startup.sh

Currently, Tomcat is using port number 8080 so check the open port using netstat command as shown:

netstat -plntu

You can check this using a web browser with http://yourserver_IP:8080 then you’ll see the homepage of Apache Tomcat Server but we recommend you to use browser later at final testing because we will run Tomcat with a systemd service file in the final configuration.

Now run following commands :

cd /opt/tomcat/bin/./shutdown.shchown -hR tomcat:tomcat /opt/tomcat/

Creating a systemd Service File

Now you’ll need to create a systemd service file to run Apache Tomcat as a tomcat user. Creation of a systemd service file is recommended for easy starting and stopping the service.

Run following command :

nano /etc/systemd/system/tomcat.service

Add the content below into nano text editor, you can simply copy/paste this into the file:

[Unit]
Description=Apache Tomcat 8 Servlet Container
After=syslog.target network.target[Service]
User=tomcat
Group=tomcat
Type=forking
Environment=CATALINA_PID=/opt/tomcat/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
Restart=on-failure

[Install] WantedBy=multi-user.target

Save and close the file then run the following commands to start the Tomcat service and enable Tomcat service to start on boot:

systemctl daemon-reload systemctl start tomcat systemctl enable tomcat

Once again check for the open port using netstat command shown below:

netstat -plntu

Now run the command below and make sure that service is active as shown below:

systemctl status tomcat

Configure Tomcat Users

Run following command to edit tomcat-users.xml file using any text editor here we are using nano :

cd /opt/tomcat/conf/ nano tomcat-users.xml

Create a new line under line 43 and add following content, again you can simply copy-paste this into file like you’ve done before:

<role rolename="manager-gui"/>
<user username="admin" password="password" roles="manager-gui,admin-gui"/>

Save the file and exit text editor.

Now you’ll have to edit context.xml file using following commands:

cd /opt/tomcat/webapps/manager/META-INF/nano context.xml

Now you’ll have to comment out line 19 and 20 as shown below:

   <Context antiResourceLocking="false" privileged="true" >
    <!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
    </Context>

Save the file and exit nano text editor .

Now once again edit the context.xml file but this time it is in host-manager directory so run below given commands :

cd /opt/tomcat/webapps/host-manager/META-INF/nano context.xml

Comment out again line 19 and 20.

  <Context antiResourceLocking="false" privileged="true" >
    <!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
    </Context>

Save the file and exit nano text editor .

Now you’ll have to restart the tomcat and to do so run following command:

systemctl restart tomcat

Configure Firewalld

If in any case you haven’t installed firewalld on your system then install it first using yum command as shown below:

yum install firewalld

You’ll have to start firewalld and add it to start at boot time, to do so run following command:

systemctl start firewalldsystemctl enable firewalld

Now you’ll have to use firewall-cmd command to add apache tomcat port number 8080 to the firewall so simply enter below-given command:

firewall-cmd --zone=public --permanent --add-port=8080/tcp

You’ll see a result as “success”.

Now reload the firewall service using the following command:

firewall-cmd --reload

We recommend you to check for all service available and port 8080 is open and there is no error, to do so run following command:

firewall-cmd --list-portsfirewall-cmd --list-services

 


参考:

How to Install Apache Tomcat 9 on CentOS 7