【带着问题去学】
Ⅰ、http和https有什么关系?
http是不安全,https是安全的
Ⅱ、https的工作流程?
超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS。
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道。HTTPS并不是一个新协议,而是HTTP+SSL(TLS)。原本HTTP先和TCP(假定传输层是TCP协议)直接通信,而加了SSL后,就变成HTTP先和SSL通信,再由SSL和TCP通信,相当于SSL被嵌在了HTTP和TCP之间[应用层和传输层中间加了个ssl]。
SSL协议【重中之重】
SSL 是“Secure Sockets Layer”的缩写,中文叫做“安全套接字层”。它是在上世纪90年代中期,由网景公司设计的。到了1999年,SSL 应用广泛,已经成为互联网上的事实标准。IETF 就把SSL 标准化。标准化之后SSL被改为TLS(Transport Layer Security传输层安全协议)。
SSL协议分为两层:
SSL记录协议 (SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能。
SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
SSL协议提供的服务:
1)认证用户和服务器,确保数据发送到正确的客户机和服务器[http就无法确认服务器身份]
2)加密数据以防止数据中途被窃取
3)维护数据的完整性,确保数据在传输过程中不被改变。
HASH是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。Hash算法特别的地方在于它是一种单向算法,用户可以通过hash算法对目标信息生成一段特定长度的唯一hash值,却不能通过这个hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。
常见的HASH算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1。
共享密钥加密(对称密钥加密):加密和解密使用相同密钥。
对称加密算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES。
公开密钥加密(非对称密钥加密):公开密钥加密使用一对非对称的密钥。一把叫做私有密钥,一把叫做公开密钥。私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。使用此加密方式,发送密文的一方使用公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听盗走。
常见的非对称加密算法:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)。
但由于公开密钥比共享密钥要慢,所以我们就需要综合一下他们两者的优缺点,使他们共同使用,而这也是HTTPS采用的加密方式。在交换密钥阶段使用公开密钥加密方式,之后建立通信交换报文阶段则使用共享密钥加密方式。
如何证明公开密钥本身是货真价实的公开密钥?如,正准备和某台服务器建立公开密钥加密方式下的通信时,如何证明收到的公开密钥就是原本预想的那台服务器发行的公开密钥。或许在公开密钥传输过程中,真正的公开密钥已经被攻击者替换掉了。这个时候就需要第三方公证单位来帮忙啦。
CA就是一个公认的公证单位,你可以自行产生一把密钥且制作出必要的证书数据并向CA单位注册,那么当客户端的浏览器在浏览时,该浏览器会主动向CA单位确认该证书是否为合法注册过,如果是,那么该次连接才会建立,如果不是,浏览器会发出警告信息,告知用户应避免建立连接。所以说,如此一来WWW服务器不但有公证单位的证书,用户在建立连接时也比较有保障。
当你在浏览器的地址栏上输入https开头的网址后,浏览器和服务器之间会在接下来的几百毫秒内进行大量的通信:
上图重带红色*号的是可以省略的
clientHello:
1.ssl/tls的协议版本
2.cipher suite加密套件
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
TLS: 使用的协议
ECDHE_ECDSA: 非对称加密算法
AES_256: 对称加密算法
GCM_SHA384: 完整性校验(hash算法)
3.client_random
ServerHello:
随机数:Random: 7de9b470d34f2a3bdec634ac9f4fc53233f97d1368a017e9783dfbaf6fd45e1b
确定加密套件:Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
TLS版本: Version: TLS 1.2 (0x0303)
certificate:
当你第一次去请求一个网站的时候,服务器会将自己的证书发送客户端,客户端去下载证书(客户端相当于获取到了证书)
当第一次去请求的时候,certificate必须有。第二次请求就不需要了
Server Key Exchange:
服务器将密钥交换的参数发送给客户端
certificate Request(可选的):
确定如果服务器需要验证客户端的身份,那么可以要求客户端将自己的CA证书发送给服务器
serverHelloDone:
代表告知客户端: 服务器数据发送完毕
certificate(可选):
客户端向服务器发送自己的证书, 在我们上一阶段如果有certificate Request,才会有这个数据包。只有服务器要求了才会发
client key exchange:
客户端和服务器进行密钥交换,实质就是使用前面协商加密套件和选择好的密钥交换算法开始进行密钥交换
刚才提到两个随机数:client_random, server_random;现在出现第三个随机数:pre_master, 客户端将pre_master发送给服务器客户端和服务器都掌握三个随机数: (client_random, server_random, pre_master)-》根据三个随机数以及加密算法计算出的会话密钥SessionKey
这是算密码的流程【反正我是看不懂0.o】
反正最后算出来个Master Secret会话密钥
Certificate Verify:
验证证书
Change cipher Spec & Encrypted Handshake message:
客户端向服务器发送Change cipher Spec: 编码改变通知: 其实告诉服务器我们现在握手完成了
客户端向服务器发送Encrypted Handshake message: 对之前我们的握手的所有信息进行hash,拿到一个hash值, 发送给服务器
服务器对应的也发送这个两个消息: change cipher spec, encrypted Handshake message
服务器接收到客户端的 hash值之后,进行校验(整个流程中发送消息的完整性), 校验通过了之后,发送 change cipher spec, encrypted Handshake message
客户端收到服务器发的change cipher spec, encrypted Handshake message, 认为建立的安全的连接,可以进行传输数据了
Application Data:
传输的数据是被加密过的,被master_key加密的
客户端浏览器向服务器端发送如下信息:
(1)客户端支持的SSL /TLS协议的版本号。
(2)Cipher Suite(密钥算法套件)。
eg.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xc02c)
TLS:使用的协议
ECDHE_ECDSA:非对称算法
AES_256:对称加密算法
GCM_SHA384:完整性校验(hash算法)
(3)客户端产生的随机数client_random,稍后用于生成"会话密钥"。
【配置时间】
未安装前
mod_ssl是一种以openssl 的工具箱为基础专门为apache webserver 提供密码保护的软件。
[root@localhost ~]# yum install mod_ssl -y
【装了之后就有ssl的配置文件了】
[root@localhost ~]# cd /etc/pki/tls/certs/
[root@localhost certs]# make jiami.crt
csr: 证书的请求文件
pem/crt: 证书,包含公钥
key: 私钥
#/etc/httpd/conf.d/ssl.conf 文件
[root@localhost ~]# vim /etc/httpd/conf.d/myssl.conf
建立一个虚拟主机:为ssl来建立一个虚拟主机验证https
Ⅰ、相当于一个站点:那你访问这个站点的时候,是不是得默认进入一个目录(/www/httpd)
mkdir -p /www/https
ehco "this page is for https" > /www/https/index.html
Ⅱ、设置目录的访问权限
在/etc/httpd/conf.d/新建一个配置文件:myssl.d
Ⅲ、设置虚拟主机:主要是通过启用ssl来进行访问
[root@localhost ~]# systemctl restart httpd
通过浏览器访问或者curl --insecure https://IP地址
【出现这个没有错嗷,这是因为我们的证书不权威】
1.4.3 基于虚拟目录和用户控制的web网站
访问网站的时候使用用户名和密码这个用户名和密码时怎么来的?
这个用户不是我们Linux上的用户,是我们专门为apache设置的用户
htpasswd: 就是来设置用户密码的
1、创建用户,并设置密码,将密码存储在文件中
[root@localhost httpd]# mkdir /etc/httpd/passwd_dir
[root@localhost httpd]# htpasswd -c /etc/httpd/passwd_dir/user.txt http_user【-c 表示创建,后面那个http_user是我们自己设的用户名】
New password: 【123456防自己忘0.o】
Re-type new password:
Adding password for user http_user
# 创建我们要访问网站的目录
mkdir -p /www/secret/
echo "This page is for secret" > /www/secret/index.html
2、对虚拟主机做额外的设置,就是设置基础认证
针对它的目录权限来设置
AuthType Basic 基本认证类型(账号)
AuthName “Please login:” 提示信息,双引号必须有,可以更换为其它提示信息: 域
AuthUserFile /etc/httpd/password_dir/user.txt 用户认证文件的用户
AuthBasicProvider file: 提供密码的方式是文件(默认配置,可以不用配置)
require user http_user: 允许http_user这个用户访问
【配置要打全,之前忘了require user 了……】
【这里是用的100ip然后用另外一个端口来实现,记得监听】
3、验证:访问192.168.174.100:9092输入账户http_user与对应密码
使用alias来将我们的路径映射到Linux上目录
Alias /webpath /full/filesystem/path
http://192.168.233.100/webpath -> 实际上访问的是/full/filesystem/path
http://192.168.233.100 -> 默认进入的就是DocumentRoot目录
没配置alias之前
http://192.168.233.100/webpath 访问的是DocumentRoot/webpath
Alias /webpath /www/mappath/
操作:
【懒得配置了,记得监听端口,给目录权限,然后配下面这个玩意就行了,最后记得重启服务,应该不会出问题,这个和上面太类似了】
# 配置虚拟主机
Alias /webpath "/www/mappath"
# 创建目录/www/mappath
mkdir -p /www/mappath
# 设置访问页面
echo "This page is for alias" > /www/mappath/index.html
访问:192.168.174.100:9093/webpath
别名模块铁三角:
Redirect: 重定向: 将访问的路径重定向到另一个url上
Alias: 映射访问路径到Linux文件系统具体路径
ScriptAlias: 将我们的访问路径映射到Linux文件系统的具体路径(指向的是可执行的文件的目录)
1.4.4 搭建动态网站
动态网站并不是指具有动画功能的网站,而是指网站内容可根据不同情况动态变更的网站,一般情况下动态网站通过数据库进行架构。 动态网站除了要设计网页外,还要通过数据库和编程序来使网站具有更多自动的和高级的功能。
动态网页:使用网页脚本语言,比如php、JSP等,通过脚本将网站内容动态存储到数据库,用户访问网站是通过读取数据库来动态生成网页的方法。
CGI是Web服务器和一个独立的进程之间的协议,它会把HTTP请求`Request`的`Header`头设置成进程的环境变量,HTTP请求的`Body`正文设置成进程的标准输入,进程的标准输出设置为HTTP响应`Response`,包含`Header`头和`Body`正文。
CGI: Common Gateway Interface
定义web服务器与外部内容生成程序(通常称为CGI程序或CGI脚本)交互的方式。这是一种简单的方法,可以使用您最熟悉的编程
浏览器发送http请求到服务器(请求一个CGI程序)
服务器接收到请求之后,知道你请求是一个CGI程序: 服务器启动CGI进程(会把我们请求的请求头作为进程的环境变量,请求体作为进程的标准输入)
CGI进程就可以拿到请求的数据, CGI进程去执行CGI程序-》程序会有标准输出,这个标准输出会作为我们服务器返回给浏览器的内容(即响应的内容)
如何去写一个CGI程序:去写一个shell脚本
CGI接口标准包括标准输入、环境变量、标准输出三部分:
标准输入:CGI程序像其他可执行程序一样,可通过标准输入(stdin)从服务器获取到输入信息,比如Form中的数据,
这就是所谓的向CGI程序传递数据的POST方法。这意味着在操作系统命令行状态可执行的CGI程序,对CGI程序进行调试。
POST方法是常用的方法。
环境变量:操作系统提供了许多环境变量,他们定义了程序的执行环境,应用程序可以存取他们,Web服务器和CGI接口又定义了自己的一些环境变量,用来向CGI程序传递一些重要的参数。CGI的GET方法还通过环境变量QUERY-STRING向CGI传递FORM表单数据。
标准输出: CGI程序通过标准输出(stdout)将输出信息传送给Web服务器。传送给Web服务器的信息可以用各种格式。
普通程序和CGI程序的两点不同:
首先:CGI程序的所有输出之前必须有MIME类型头。这是HTTP头部告诉客户端接收内容的类型。
其次: 你的输出需要在html中或其他浏览器可以展示的形式
设置目录权限的两种方式
ScriptAlias /path "/www/cgi-bin" -> 让我们去访问/path实际上访问的是/www/cgi-bin, 且/www/cgi-bin这个目录下的所有的文件都是可执行的文件
第一种方式
AllowOverride None
Require all granted
ScriptAlias /bin "/www/cgi。bin"
脚本:test.sh, 脚本放置的路径: /www/cgi-bin2/
#!/bin/bash
要有个空行,所以才有的第二个\n
helloworld是响应体的内容
【重启服务后还是不得行,因为目录没有可执行权限x】
成功
第二种方式:
AllowOverride None
Options +ExecCGI
Require all granted
Alias /bin2 "/www/cgi.bin2"
AddHandler cgi-script .sh .cgi .py
脚本:test.sh, 脚本放置的路径: /www/cgi.bin2/
#!/bin/bash
cgi.bin2的test.sh是从cgi.bin里拷过去的不用改