HTTPS 协议

HTTPS 协议

推荐Blog:
了解 HTTPS
图解 HTTPS

HTTPS 协议是什么?

首先提醒读者,其实这个世界压根不存在 HTTPS 协议,只有 HTTP 协议,加上 S 的后缀只是告诉大家 HTTP 使用的是六层结构(将表示层和会话层归属到应用层),有了新的逻辑层 SSL/TLS 的安全保护,但 HTTPS 协议的说法传泛甚广,所以以下皆称 HTTPS 协议

HTTPS (Hyper Text Transfer Protocol over SecureSocket Layer)是基于 HTTP 衍生出的可进行加密传输、身份认证的网络协议 。是以安全为目标的 HTTP 通道,HTTPS 在 HTTP 的基础下加入 SSL/TSL 层,用来对传输的内容做加密, HTTPS 的默认端口为 443,HTTPS 存在不同于 HTTP 的默认端口及一个 加密传输 / 身份验证 层(在 HTTP与 TCP 之间)。

HTTPS 协议的组成:
①.HTTP 协议 + SSL(Secure Sockets Layer)层
其中 SSL层 是一个新的逻辑层概念,不属于任意一个层,但处于应用层与传输层之间,SSL 层包含了两个协议:
SSL 记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。
SSL 握手协议(SSL Handshake Protocol):它建立在 SSL 记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

②.HTTP 协议 + TLS(Transport Layer Security)协议
其中 TLS 是安全传输层协议,是基于 SSL 层衍生的;摒弃了 SSL 层,TLS 归属于传输层,顾名思义实现了传输层的安全保护措施

为什么需要 HTTPS 协议?

HTTP是明文传输的,那么在客户端、服务端之间传输的内容,是可以被中间的任意一个节点获取的;例如用户登陆,输入账号、密码,如果采用 HTTP 协议,在中间的代理服务器上,稍微做点手脚就可以拿到你的密码 ;同时,用户请求的服务端页面,也可以被代理服务器任意更改替换(使用 ngx_http_sub_module 模块),服务端原始的页面会被篡改,例如被迫打上“澳门皇家赌场”的广告。

客户端----> 代理服务器(做手脚)----> 服务端

模拟网站原始页面被篡改,首先配置服务端原始页面:

# 服务端 nginx 配置
[root@web01 ~]# vi /etc/nginx/conf.d/www.wqh.com.conf 
    server {
            listen 80;
            server_name www.wqh.com;
            root /website;
            index index.html;
            charset utf-8;
    }

# 站点目录的索引文件
[root@web01 ~]# vim  /website/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>my website</title>
</head>
<body>
<article>
  <header>
    <h1>一个个人网站</h1>
    <p>创建时间:<time pubdate="pubdate">2020/2/22</time></p>
  </header>
  <p>
    <b>标题:</b>我只写正经内容
  </p>
  <footer>
    <p><small>我不打广告</small></p>
  </footer>
</article>
</body>
</html>

中间安插一个代理服务器:

# 代理服务器 nginx 配置
[root@lb01 ~]# vi /etc/nginx/conf.d/test.conf
upstream sb {
        server 10.0.0.9:80;
}
server {
        listen 80;
        server_name www.wqh.com;

        location / {
                proxy_pass http://sb;
                proxy_set_header Host $http_host;
                sub_filter '<h1>一个个人网站' '<h1>一起贪玩蓝月吗';
                sub_filter '</b>我只写正经内容' '</b>开局就神装,一刀99999';
                sub_filter '<small>我不打广告' ' <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591197424430&di=22f4883b00be870cb56c796067d45962&imgtype=0&src=http%3A%2F%2Fwww.ijiandao.com%2Fwp-content%2Fuploads%2F2019%2F06%2F74dbd2451110be34e86e4c96874b9e05.jpg">';
        }
}

如何使用 HTTPS 协议?

需要配置 SSL/TLS 证书,才可以使用 HTTPS 协议,证书类型如下,证书的选择包括 单域名证书、多域名证书、通配符证书,通配符选择的证书只支持匹配二级域名 。

对比 域名型 DV 企业型 OV 增强型 EV
地址栏 小锁标记+https 小锁标记+https 小锁标记+企业名称+https
一般用途 个人站点和应用; 简单的https加密需求 电子商务站点和应用; 中小型企业站点 大型金融平台; 大型企业和政府机构站点
审核内容 域名所有权验证 全面的企业身份验证; 域名所有权验证 最高等级的企业身份验证; 域名所有权验证
颁发时长 10分钟-24小时 3-5个工作日 5-7个工作日
单次申请年限 1年 1-2年 1-2年
赔付保障金 —— 125-175万美金 150-175万美金
不同类型的域名:

使用 SSL 证书需要使用 ngx_http_ssl_module 模块(官方文档),正常的 SSL 证书(被浏览器承认)都需要申请,但也可以模拟生成一个证书(不被浏览器承认):

## ngx_http_ssl_module 语法
# 启动 ssl 功能
Syntax:  ssl on | off;  <----  ssl on; 或 listen 443 ssl;  
Default: ssl off;
Context: http,server
# 指定证书文件
Syntax:  ssl_certificate file;
Default: -
Context: http,server
# 指定私钥文件
Syntax:  ssl_certificate_key file;
Default: -
Context: http,server


## 模拟生成一个 SSL 证书
# 生成私钥
[root@lb01 ~]# mkdir /app/nginx/conf/ssl_key
[root@lb01 ~]# cd /app/nginx/conf/ssl_key/
[root@lb01 ssl_key]#  openssl genrsa -idea -out /app/nginx/conf/ssl_key/$(date +%Y%m%d)_wqh.com.key 2048
Generating RSA private key, 2048 bit long modulus
................................+++
.............................................................................................+++
e is 65537 (0x10001)
Enter pass phrase for /app/nginx/conf/ssl_key/20200603_wqh.com.key:
Verifying - Enter pass phrase for /app/nginx/conf/ssl_key/20200603_wqh.com.key:
# 生成证书
[root@lb01 ssl_key]#  openssl req -days 36500 -x509 -sha256 -nodes -newkey rsa:2048 -keyout /app/nginx/conf/ssl_key/20200603_wqh.com.key -out /app/nginx/conf/ssl_key/20200603_wqh.com.crt
Generating a 2048 bit RSA private key
....+++
................................................+++
writing new private key to '/app/nginx/conf/ssl_key/20200603_wqh.com.key'
-----
You are about to be asked to enter information that will be incorporated
into 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 blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Heilongjiang
Locality Name (eg, city) [Default City]:qiqihaer
Organization Name (eg, company) [Default Company Ltd]:none
Organizational Unit Name (eg, section) []:none
Common Name (eg, your name or your server's hostname) []:wqh.com
Email Address []:123@123.com

单台服务器配置 HTTPS:

[root@lb01 ~]# vi /app/nginx/conf/conf.d/test.conf
server {
        listen 80;
        server_name www.wqh.com;
        return 302 https://$host/$request_uri;
}

server {
        listen 443 ssl;
        server_name www.wqh.com;
        ssl_certificate /app/nginx/conf/ssl_key/20200603_wqh.com.crt;
        ssl_certificate_key /app/nginx/conf/ssl_key/20200603_wqh.com.key;
	    root /website;
	    index index.html;
}
[root@lb01 ~]# vim  /website/index.html
<H1>THIS IS HTTPS</H1>

企业案例:分布式集群架构实现 HTTPS

部署负载均衡代理服务器,添加 SSL 安全证书;部署应用服务器,数据库服务器,NFS共享存储服务器以及备份服务器;具体环境需求如下:

服务器 IP(WAN) 服务
lb01 10.0.0.5 nginx + SSL证书
web01 10.0.0.7 nginx + php-fpm
web02 10.0.0.8 nginx + php-fpm
web03 10.0.0.9 nginx + php-fpm
db01 10.0.0.51 mariadb
nfs 10.0.0.31 nfs-server,sereync
backup 10.0.0.41 rsync

部署数据库服务器

# 安装 mariadb,创建数据库 wordpress、wecenter
[root@db01 ~]# yum -y install mariadb-server
[root@db01 ~]# systemctl start mariadb && systemctl enable mariadb
[root@lb01 ~]# mysqladmin -uroot password 123
[root@lb01 ~]# mysql -p123
>create database wordpress;
>grant all on wordpress.* to wp_user@'%' identified by '123456';
>create database wecenter;
>grant all on wecenter.* to wc_user@'%' identified by '123456';

部署应用服务器

# 每个应用服务器都装过 Nginx,进行以下操作
# 编辑 nginx 配置文件
[root@web01 ~]# cat /etc/nginx/conf.d/blog.wqh.com.conf 
server {
	listen 80;
	server_name blog.wqh.com;
	root /website/wordpress/;
	index index.php;
	location ~ \.php$ {
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include fastcgi_params;
	}
}
[root@web01 ~]# cat /etc/nginx/conf.d/wecenter.wqh.com.conf 
server {
	listen 80;
	server_name wecenter.wqh.com;
	root /website/wecenter/;
	index index.php;
	location ~ \.php$ {
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include fastcgi_params;
	}
}
[root@web01 ~]# cat /etc/nginx/conf.d/phpmyadmin.com.conf 
server {
	listen 80;
	server_name phpmyadmin.wqh.com;
	root /website/phpmyadmin;
	index index.php;
	location ~ \.php$ {
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include fastcgi_params;
	}
}
# 添加参数到 fastcgi_params 文件,开启 HTTPS(让 php-fpm 将所有 HTTP链接 转为 HTTPS链接)
[root@web01 ~]# echo  "fastcgi_param HTTPS on;" >>  /etc/nginx/fastcgi_params

# 解压 phpmyadmin、 wecenter、wordpress 到指定站点目录,指定属主属组(nginx,php-fpm 的执行用户)
# 打开浏览器安装,phpmyadmin 需要手动创建数据库配置文件
[root@web01 ~]# vi /website/phpmyadmin/config.inc.php
$cfg['Servers'][$i]['host'] = '172.16.1.51';


# 安装好后,将web01服务器的 nginx配置文件 传给web02、web03服务器
[root@web01 ~]# rsync -avz /etc/nginx/  10.0.0.8:/etc/
[root@web01 ~]# rsync -avz /etc/nginx/  10.0.0.9:/etc/

部署NFS服务器

# 安装 nfs-utils rpcbind,启动服务,客户端也需要安装才可以指定挂载 nfs 文件系统类型 
[root@nfs ~]# yum -y install nfs-utils
[root@nfs ~]# systemctl start nfs-server && systemctl enable nfs-server
[root@web01 ~]# yum -y install nfs-utils
[root@web02 ~]# yum -y install nfs-utils
[root@web03 ~]# yum -y install nfs-utils

# 指定共享存储目录、网段、授权,/website_data 存储站点目录下所有的内容,/phpmyadmin_session 存储 phpmyadmin 维持会话的 session 文件
[root@nfs ~]# cat /etc/exports
/website_data 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)
/phpmyadmin_session 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)

# 创建匿名用户,创建共享存储目录,指定目录授权
[root@nfs ~]# mkdir /website_data /phpmyadmin_session
[root@nfs ~]# useradd www -u 666 -r -s /sbin/nologin -M
[root@nfs ~]# chown www.www /website_data && chown www.www /phpmyadmin_session

# 先将 Web01 站点目录的内容同步到 nfs 服务器的 /website_data 
[root@web01 ~]# rsync -avz /website/ 10.0.0.31:/website_data

# 再将 Web01 Web02 Web03 的站点目录挂载到 nfs 服务器上,若 Web02 Web03 没有站点目录则创建,并统一属主
[root@web01 ~]# mount -t nfs 172.16.1.31:/website_data /website
[root@web02 ~]# mount -t nfs 172.16.1.31:/website_data /website
[root@web03 ~]# mount -t nfs 172.16.1.31:/website_data /website

# 再将 phpmyadmin 维持会话的 /var/lib/php/session 目录,挂载到 nfs 服务器上
[root@web01 ~]# mount -t nfs 172.16.1.31:/phpmyadmin_session /var/lib/php/session/
[root@web02 ~]# mount -t nfs 172.16.1.31:/phpmyadmin_session /var/lib/php/session/
[root@web03 ~]# mount -t nfs 172.16.1.31:/phpmyadmin_session /var/lib/php/session/


##############  NFS服务端 同时也是 Rsyncd 客户端,需要部署 Sersync服务 实时备份 ###################
# 下载 Sersync 软件包
[root@nfs ~]# wget https://files.cnblogs.com/files/zzzwqh/sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@nfs ~]# tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz -C /usr/local/

# 编辑 confxml.xml 配置文件
[root@nfs ~]# vi /usr/local/sersync/confxml.xml
        <!-- Rsync客户端监控目录 -->
	<localpath watch="/website_data">
            <!-- Rsync服务端IP 和 Rsync服务端模块  -->
	    <remote ip="172.16.1.41" name="website_data"/>
	    <!--<remote ip="192.168.8.39" name="tongbu"/>-->
	    <!--<remote ip="192.168.8.40" name="tongbu"/>-->
	</localpath>
	<rsync>
            <!-- 指定rsync命令选项   -->
	    <commonParams params="-az"/>
            <!-- 是否开启认证模式(认证用户),指定Rrync服务端认证用户,指定密码文件路径 -->
	    <auth start="true" users="rsync_backup" passwordfile="/etc/rsync.password"/>
	    <userDefinedPort start="false" port="874"/><!-- port=874 -->
	    <timeout start="false" time="100"/><!-- timeout=100 -->
	    <ssh start="false"/>
	</rsync>
# 创建 confxml_session.xml 配置文件(需要同时监听两个目录,所以需要两个配置文件)
[root@nfs ~]# vi /usr/local/sersync/confxml_session.xml
        <!-- Rsync客户端监控目录 -->
	<localpath watch="/phpmyadmin_session">
            <!-- Rsync服务端IP 和 Rsync服务端模块  -->
	    <remote ip="172.16.1.41" name="session_data"/>
	    <!--<remote ip="192.168.8.39" name="tongbu"/>-->
	    <!--<remote ip="192.168.8.40" name="tongbu"/>-->
	</localpath>
	<rsync>
            <!-- 指定rsync命令选项   -->
	    <commonParams params="-az"/>
            <!-- 是否开启认证模式(认证用户),指定Rrync服务端认证用户,指定密码文件路径 -->
	    <auth start="true" users="rsync_backup" passwordfile="/etc/rsync.password"/>
	    <userDefinedPort start="false" port="874"/><!-- port=874 -->
	    <timeout start="false" time="100"/><!-- timeout=100 -->
	    <ssh start="false"/>
	</rsync>

# 创建密码认证文件
[root@nfs ~]# echo 123 > /etc/rsync.password
[root@nfs ~]# chmod 600 /etc/rsync.password


# 启动 Sersync服务 
[root@nfs ~]# /usr/local/sersync/sersync2 -rdo /usr/local/sersync/confxml.xml
[root@nfs ~]# /usr/local/sersync/sersync2 -rdo /usr/local/sersync/confxml_session.xml 

部署备份服务器

# 安装 rsync,启动服务
[root@backup ~]# yum -y install rsync
[root@backup ~]# systemctl start rsyncd && systemctl enable rsyncd

# 1.编辑 /etc/rsyncd.conf 配置文件
[root@backup ~]# cat /etc/rsyncd.conf 
uid = rsync
gid = rsync
port = 873
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[website_data]
comment = website's data
path = /website_bak
[session_data]
comment = phpmyadmin session's data
path = /session_bak


# 2.创建好 rsync 用户,创建 /website_bak目录、/session_bak目录,指定属主
[root@backup ]# useradd rsync -s /sbin/nologin -M
[root@backup ]# mkdir /backup
[root@backup ]# chown rsync.rsync /backup

# 3.编辑密码文件,服务端密码文件需要写成 `auth users:password`,客户端只需要写入 `passord`
[root@backup ]# cat /etc/rsync.passwd 
rsync_backup:123
[root@backup ]# chmod 600 /etc/rsync.passwd

# 4.重启服务
[root@backup ]# systemctl restart rsyncd

部署代理服务器

## 模拟生成一个 SSL 证书
# 生成私钥
[root@lb01 ~]# mkdir /app/nginx/conf/ssl_key
[root@lb01 ~]# cd /app/nginx/conf/ssl_key/
[root@lb01 ssl_key]#  openssl genrsa -idea -out /app/nginx/conf/ssl_key/$(date +%Y%m%d)_wqh.com.key 2048
Generating RSA private key, 2048 bit long modulus
................................+++
.............................................................................................+++
e is 65537 (0x10001)
Enter pass phrase for /app/nginx/conf/ssl_key/20200603_wqh.com.key:
Verifying - Enter pass phrase for /app/nginx/conf/ssl_key/20200603_wqh.com.key:
# 生成证书
[root@lb01 ssl_key]#  openssl req -days 36500 -x509 -sha256 -nodes -newkey rsa:2048 -keyout /app/nginx/conf/ssl_key/20200603_wqh.com.key -out /app/nginx/conf/ssl_key/20200603_wqh.com.crt
Generating a 2048 bit RSA private key
....+++
................................................+++
writing new private key to '/app/nginx/conf/ssl_key/20200603_wqh.com.key'
-----
You are about to be asked to enter information that will be incorporated
into 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 blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Heilongjiang
Locality Name (eg, city) [Default City]:qiqihaer
Organization Name (eg, company) [Default Company Ltd]:none
Organizational Unit Name (eg, section) []:none
Common Name (eg, your name or your server's hostname) []:wqh.com
Email Address []:123@123.com

# 编辑 nginx 配置文件
[root@lb01 ~]# cat /app/nginx/conf/conf.d/lb.conf 
upstream wqh {
	server 172.16.1.7;
	server 172.16.1.8;
	server 172.16.1.9;
}
server {
	listen 80;
	server_name blog.wqh.com wecenter.wqh.com phpmyadmin.wqh.com;
	return 302 https://$host/$request_uri;
}
server {
	listen 443 ssl;
	server_name blog.wqh.com wecenter.wqh.com phpmyadmin.wqh.com;
	ssl_certificate /app/nginx/conf/ssl_key/20200603_wqh.com.crt;
	ssl_certificate_key /app/nginx/conf/ssl_key/20200603_wqh.com.key;
	location / {
		proxy_pass http://wqh;
		proxy_set_header HOST $host;
	}
}

番外:SSL 优化参数

server {
    listen 443 ssl;
    server_name blog.wqh.com;
    root /var/website/wordpress;
    index index.php index.html index.htm;
    ssl_certificate   ssl/123456_blog.wqh.com.pem;
    ssl_certificate_key  ssl/123456_blog.wqh.com.key;
    
    ssl_session_cache shared:SSL:10m; # 在建立完 ssl 握手后如果断开连接,在 session_timeout 时间内再次连接,是不需要再次获取公钥建立握手的,可以服用之前的连接
    ssl_session_timeout 1440m;  # ssl 连接断开后的超时时间
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  # 配置加密套接协议
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;  # 使用 TLS 版本协议
    ssl_prefer_server_ciphers on;  # nginx决定使用哪些协议与浏览器通信
}
posted @ 2020-06-03 22:36  拨云见日z  阅读(638)  评论(0编辑  收藏  举报