目录
1. 客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;
2. 服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;
3. 客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;
4. 服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。
1.ssl协议(https)工作流程
总流程图
SSL建立过程总共有13个包,第一次建立至少需要9个包。
1. 客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;
SSL握手第一阶段:
SSLclient通过Client Hello消息将它支持的SSL版本号、加密算法、密钥交换算法、MAC算法等信息发送给SSLserver
客户端密码套件格式:每个套件都以“SSL”开头,紧跟着的是密钥交换算法。用“With”这个词把密钥交换算法、加密算法、散列算法分开
例如:SSL_DHE_RSA_WITH_DES_CBC_SHA,DHE_RSA(带有RSA数字签名的暂时Diffie-HellMan)定义为密钥交换算法;DES_CBC定义为加密算法;SHA定义为散列算法。
2. 服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;
服务器启动SSL握手的第二阶段,是本阶段唯一的发送方,客户机是唯一的接收方。
证书:服务器将证书和根CA整个链发给客户端。使客户端能用服务器证书中的服务器公钥认证服务器。
服务器密钥交换: 由密钥交换算法决定的。
证书请求: 服务端可能会要求客户自身验证。
服务器握手完成:第二阶段结束,第三阶段开始。
Certificate消息(可选):
第一次建立必须要有证书。
一般情况下,除了会话恢复时不需要发送该消息,在SSL握手的全流程中,都需要包含该消息。
消息包含一个X.509证书,证书中包含公钥,发给客户端用来验证签名或在密钥交换的时候给消息加密。
这一步是服务器端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥。
Server Key Exchange(可选):
根据之前在ClientHello消息中包含的CipherSuite消息,决定了密钥交换方式。
因此在Server Key Exchange消息中便会包含完成密钥交换所需的一系列参数。
这里使用的是Diffi-Hellman算法,所以需要发送服务器使用的DH参数,RSA算法不需要。
在Diffie-Hellman中,客户端无法自行计算预主密钥;双方都有助于计算它,因此客户端需要从服务器获取Diffie-Hellman公钥。
Certificate Request(可选):
可以是单向的身份验证,也可以是双向的身份验证
服务器用来验证客户端,服务器发送Certificate Request消息,要求客户端发它自己的证书过来进行验证。
该消息中包含服务器支持的证书类型(RSA,DSA,ECDSA)和服务器端所信任的所有证书发行机构的CA列表。
客户端会用这些信息来筛选证书。
Server Hello Done
该消息表示服务器已经将所有信息发送完毕,接下来等待客户端的消息。
3. 客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;
客户端启动SSL握手的第三阶段,客户端使本阶段唯一的发送方,服务器端是唯一接收方
证书(可选):为了对服务器证明自身,客户端要发送一个证书消息,这是可选的。
客户机密钥交换(Pre-master-secret): 这里客户端要将预备主密钥发送给服务器,使用服务器端的公钥进行加密。
证书验证(可选):对预备主密钥和随机数进行签名,证明拥有证书的密钥
Certificate(可选):
如果在第二阶段服务器端要求发送客户端证书,客户端便会在该阶段将自己的证书发送过去。服务器端在之前发送的Certificate Request消息中包含了服务器端所支持的证书类型和CA列表,因此客户端会在自己的证书中选择满足这两个条件的第一个证书发送过去。若客户端没有证书,则发送一个no_certificate警告。
Client Key Exchange
根据之前从服务器端收到的随机数,按照不同的密钥交换算法(RSA,Diffie-Hellman)产生的一个48字节的key,算出一个pre-master(是整个握手阶段第三个随机数),发送给服务器,服务器端收到pre-master算出main master。而客户端当然也能自己通过pre-master算出main master。如此以来双方就算出了对称密钥。 如果是RSA算法,会生成一个48字节的随机数,然后用server的公钥加密后再放入报文中。 如果是DH算法,发送的就是客户端的DH参数,之后服务器和客户端根据DH算法,各自计算出相同的pre-master secret.
本消息在给服务器发送的过程中,使用了服务器的公钥加密。服务器用自己的私钥解密后才能得到pre-master key.(向服务器证明自己的确持有客户端证书私钥。)
Certificate Verify(可选):
只有在客户端发送了自己证书到服务器端,这个消息才需要发送。其中包含一个签名,对从第一条消息以来的所有握手消息的HMAC值(用master_secret)进行签名。
4. 服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。
客户端启动SSL握手的第四个阶段,使服务器结束。该阶段分为四步,前两个消息来自客户机,后2个消息来自服务器。
建立起一个安全的连接,客户端发送一个Change Cipher Spec消息,并且把协商得到的CipherSuite拷贝到当前连接的状态之中。
客户端用新的算法、密钥参数发送一个Finished消息, 这条消息可以检查密钥交换和认证过程是否已经成功。其中包括一个校验值,对客户端整个握手过程的消息进行校验。服务器同样发送Change Cipher Spec消息和Finished消息。
握手过程完成,客户端和服务器可以交换应用层数据进行通信。
ChangeCipherSpec:
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送(ChangeCipherSpec是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了)。
Clinet Finished:
客户端握手结束通知, 表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验(使用HMAC算法计算收到和发送的所有握手消息的摘要,然后通过RFC5246中定义的一个伪函数PRF计算出结果,加密后发送。此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。)
Server Finished:
服务端握手结束通知。
1.使用私钥解密加密的Pre-master数据,基于之前(Client Hello 和 Server Hello)交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key=Fuc(random_C, random_S, Pre-Master);
2.计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性;
3.发送一个 ChangeCipherSpec(告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了)
4.服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。 根据之前的握手信息,如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的Session Secret对数据进行加密传输了。
2.配置不同端的虚拟主机访问apache服务器
// 创建两个根目录,并定义网页内容
[root@localhost ~]# mkdir -p /www/ip/{8080,1000}
[root@localhost ~]# echo "this is 8080" > /www/ip/8080/index.html
[root@localhost ~]# echo "this is 1000" > /www/ip/1000/index.html
// 定义基于不同端口来访问网站的配置文件并重启服务
[root@localhost ~]# cd /etc/httpd/conf.d
[root@localhost conf.d]# ls
autoindex.conf myhosts.conf README ssl.conf userdir.conf welcome.conf
[root@localhost conf.d]# vim myhosts.conf
<Directory /www>
AllowOverride none
Require all granted
</Directory>
Listen 8080
<VirtualHost 192.168.75.128:8080>
DocumentRoot "/www/ip/8080"
ServerName 192.168.75.128
</VirtualHost>
Listen 1000
<VirtualHost 192.168.75.128:1000>
DocumentRoot "/www/ip/1000"
ServerName 192.168.75.128
</VirtualHost>
[root@localhost conf.d]# systemctl restart httpd
测试
3.配置用户控制和虚拟目录访问apache服务器
//创建密码文件
[root@localhost ~]# htpasswd -c /usr/local/etc/passwords test
New password:
Re-type new password:
Adding password for user test
//创建需要保护的目录,在首页输入内容
[root@localhost ~]# mkdir -p /usr/local/mysecret
[root@localhost ~]# echo "Test User Secret" >> /usr/local/mysecret/index.html
//定义基于加密文件的配置并重启https服务
[root@localhost ~]# vim /etc/httpd/conf.d/myhosts.conf
<Directory "/usr/local/mysecret"> #配置目录权限
AuthType Basic #选择被用于认证用户的方法
AuthName "Hello Secret" #双引号内是提示信息
AuthBasicProvider file
AuthUserFile "/usr/local/passwords" #指定创建的密码文件路径
Require user test #指定可以访问该服务器的用户
</Directory>
Listen 80
<VirtualHost 192.168.75.100:80>
alias "/mysecret" "/usr/local/mysecret"
ServerName 192.168.75.100
</VirtualHost>
[root@localhost ~]# systemctl restart httpd
测试:
在浏览器输入:192.168.75.100/mysecret/
4.配置使用ssl完成https访问apache服务器
//安装ssl
[root@localhost ~]# yum install mod_ssl -y
Repository extras is listed more than once in the configuration
Last metadata expiration check: 18:19:00 ago on Mon 06 Dec 2021 10:31:03 AM EST.
Package mod_ssl-1:2.4.37-43.module_el8.5.0+1022+b541f3b1.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
//创建https目录
[root@localhost ~]# mkdir -p /www/https/
//在首页写入内容
[root@localhost ~]# cd /www
[root@localhost www]# ls
cgi https ip
[root@localhost www]# cd https/
[root@localhost https]# ls
index.html
[root@localhost https]# echo "This is nt first https page" > index.html
//定义基于443端口加密访问的配置并重启https服务
[root@localhost https]# vim /etc/httpd/conf.d/myhosts.conf
<Directory /www/https>
AllowOverride none
Require all granted
</Directory>
#Listen 443 https
<VirtualHost 192.168.75.128:443>
DocumentRoot "/www/https"
ServerName 192.168.75.128
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>
[root@localhost https]# systemctl restart httpd
测试:
在浏览器输入:https://192.168.75.128:443
高级—继续访问
5.配置访问apache的cgi程序
cgi:Common Gateway Interface——公共网关接口,是Web 服务器运行时外部程序的规范,几乎所有服务器都支持CGI。
1.创建一个cgi的目录: /www/cgi
//创建一个cgi的目录: /www/cgi
[root@localhost ~]# mkdir -p /www/cgi
//在这个目录下创建一个cgi程序
[root@localhost cgi]# vim test.cgi
#!/bin/bash
printf "Context-type:text/html\n\n"
printf "Hello World For Cgi"
//配置目录权限(让这个目录具有可执行cgi权限的权限,设定cgi的后缀名)
[root@localhost cgi]# cd /etc/httpd/conf.d
[root@localhost conf.d]# vim myhosts.conf
<Directory "/www/cgi">
AllowOverride none
Options +ExecCGI
AddHandler cgi-script .cgi .py .pl
Require all granted
</Directory>
Listen 8001
<VirtualHost 192.168.75.200:8001>
ScriptAlias "/cgi" "/www/cgi"
ServerName 192.168.75.200
</VirtualHost>
[root@localhost conf.d]# systemctl restart httpd
测试:
发生了内部错误,查了错误日志也没改好,有没有大佬知道怎么改