1. 理论知识

1.1 什么是https

传统的 HTTP 协议以明文方式进行通信,不提供任何方式的数据加密,很容易被中间攻击者破解通信内容或者伪装成服务器与客户端通信,在安全性上存在很大问题。

HTTPS 协议是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。

关于非对称加密以及公钥私钥相关知识不在赘述,可自行了解。

PS: TLS 是传输层加密协议,前身是由网景公司1995年发布的 SSL 协议,不过在很多场合还是用 SSL 指代 TLS/SSL。

1.2 https的通信过程

下图来源:菜鸟教程

1、客户端发起 HTTPS 请求

用户访问 https 网址,连接到服务器的 443 端口,请求信息中包含了客户端支持的对称加密算法列表。

2、服务端的配置

支持 HTTPS 协议的服务器必须要有包含自己认证信息和公钥的数字证书以及自己的私钥。

3、下发证书

服务器下发自己的数字证书,这一步其实还包括从客户端支持的对称加密算法列表中选出来用于双向通信的算法,因为非对称加密是一个很耗费资源的过程,所以一般只用来协商之后用于通信的对称加密算法。

当然这一步只是明文协商了对称加密算法的名字,后面会用非对称加密来传输用于对称加密算法的秘钥,由于非对称加密的有效性,这个秘钥是不会被破解的,后续的对称加密传输也就不会被破解。

4、客户端验证证书有效性

客户端验证证书的有效性,如果证书没有问题,那么就生成一个随机值(对称加密秘钥),然后用证书中的公钥对该随机值进行加密。

5、传送用于对称通信的秘钥

用公钥加密的随机值被发送到服务端。

6、服务端解密秘钥

服务端用自己的私钥解密后,得到了客户端传过来的随机值(对称加密秘钥)。

7、双向对称加密通信

接下来就使用之前协商好的对称加密算法以及加密传输的秘钥进行通信即可。

1.3 SSL证书的签发流程

上面的 https 通信过程中,最关键的一步就是客户端如何验证服务端下发证书的有效性,因为下发证书是一个明文传输的过程,证书可能在传输过程中被拦截,被调包,被篡改,那么客户端怎么确定自己收到的就是自己想访问的网站的证书呢?

由于客户端是发起通信的一方,双方没有协商好的加密算法,服务端也不可能持有客户端的公钥信息,所以证书不能被加密发送,那么要解决这个问题就必须引入第三方可信机构(CA),客户端信任它,它就可以对服务器证书做出认证,具体来说就是使用自己的私钥对服务器证书进行签名,签名后的信息包含在证书内,这样客户端只需要持有各个 CA 的公钥,便可以对签名信息进行解密来验证证书的有效性。

上图就是 SSL 证书的签发流程:

  1. 浏览器需要记住各大CA。浏览器是怎么样记住CA的呢?在浏览器开发的时候,各个CA就把自己的根证书交给了浏览器,那么 CA 根证书中最重要的信息就是该 CA 机构的公钥了,此外还有 CA 机构的标识信息以便匹配服务器证书中声明对它签名的机构。

  2. 各大网站,如支付宝,将自己的证书交给CA。CA此时需要做的事情是,通过各种法定机构,验证网站的身份。如果CA确定该网站是真的,那么就需要用自己的私钥给网站的证书签名。网站交给 CA 的证书中除了包含自己的 URL 等标识信息外,还必须有网站自己的公钥信息,因为签完名之后证书就不能动了,而后面客户端需要服务器的公钥来加密信息。

  3. 此处就回到了之前的 https 通信过程,浏览器拿到证书后首先根据该证书的信息,如哪个 CA 对它进行了签名,结合浏览器已有的 CA 的根证书列表,对该证书进行验证,具体来说就是用对应 CA 的公钥对证书中的签名信息进行解密,再与证书信息进行比对,如果验证通过,那么就可以确定这个证书的有效性。

2. 搭建https服务

本机环境:Ubuntu 20.04,openssl 1.1.1h

明白了 https 工作过程后,我们便可以利用开源的安全传输层密码库 openssl 来自建一个实验性的 https 服务。

想一想我们需要什么?

  • 一个提供 https 服务的服务器需要有经过 CA 认证的数字证书和自己的公钥私钥(公钥放在证书里)
  • CA 认证是需要收费的,所以我们需要自建一个 CA 机构
  • 自建的 CA 机构需要有标识自己身份的根证书(包含公钥),以及用来对服务器证书进行签名的私钥
  • 一个 https 站点,收到客户端访问时下发自己的数字证书
  • 客户端需要持有 CA 的根证书,所以我们需要手动导入自建 CA 的证书

2.1 自建CA

首先创建一个 myCA 目录来存放自建 CA 的相关信息:

# 创建用户目录下的 https 目录作为实验目录,在其中创建 myCA 目录存放 CA 相关信息
# myCA/signedcerts:存放经 CA 认证的证书副本
# myCA/private:存放 CA 私钥
cd && mkdir -p https/myCA/signedcerts && mkdir https/myCA/private && cd https/myCA # 创建证书库,这两个文件存放了 CA 每一次颁发证书的记录
echo '01' > serial && touch index.txt

使用任何你熟悉的编辑器在 myCA 目录下新建一个 caconfig.cnf 文件来配置 CA 信息,其中需要注意的部分有:

  • username:修改为自己的用户名

  • default_md:默认对证书签名时的摘要算法,不要使用 sha2 以下的算法,否则服务器会启动失败(老版本可能没这个限制)

# My sample caconfig.cnf file.
#
# Default configuration to use when one is not provided on the command line.
#
[ ca ]
default_ca = local_ca
#
#
# Default location of directories and files needed to generate certificates.
#
[ local_ca ]
dir = /home/{username}/https/myCA # CA 目录
certificate = $dir/cacert.pem
database = $dir/index.txt
new_certs_dir = $dir/signedcerts
private_key = $dir/private/cakey.pem
serial = $dir/serial
#
#
# Default expiration and encryption policies for certificates.
# 认证其他服务器证书设置
default_crl_days = 365 # 默认吊销证书列表更新时间
default_days = 1825 # 默认证书有效期
default_md = sha256 # 默认对证书签名时的摘要算法
#
policy = local_ca_policy
x509_extensions = local_ca_extensions
#
#
# Default policy to use when generating server certificates. The following
# fields must be defined in the server certificate.
#
[ local_ca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = supplied
emailAddress = supplied
organizationName = supplied
organizationalUnitName = supplied
#
#
# x509 extensions to use when generating server certificates.
#
[ local_ca_extensions ]
subjectAltName = DNS:alt.tradeshowhell.com
basicConstraints = CA:false
nsCertType = server
#
#
# The default root certificate generation policy.
# 生成 CA 根证书设置
[ req ]
default_bits = 2048 # 默认生成证书请求时的秘钥长度
default_keyfile = /home/{username}/https/myCA/private/cakey.pem # 默认私钥存放位置
default_md = sha256 # 默认证书签名时使用的摘要算法
#
prompt = no
distinguished_name = root_ca_distinguished_name
x509_extensions = root_ca_extensions
#
#
# Root Certificate Authority distinguished name. Change these fields to match
# your local environment!
#
[ root_ca_distinguished_name ]
commonName = myCA # CA 机构名
stateOrProvinceName = JS # 所在省份
countryName = CN # 所在国家(仅限两字符)
emailAddress = Hui4401@qq.com # 邮箱
organizationName = USTC # 组织名
organizationalUnitName = SE # 单位名
#
[ root_ca_extensions ]
basicConstraints = CA:true

然后生成自签名的 CA 根证书和秘钥,CA 的根证书是自签名的,也就是用自己的私钥对自己的证书签名,因为它是可信机构,不需要别人认证:

# 设置 openssl 环境变量,以 CA 身份运行接下来的 openssl 命令
export OPENSSL_CONF=~/https/myCA/caconfig.cnf # 生成 rsa 秘钥对和 pem 格式的 CA 自签名根证书,有效期 1825天
# 需要输入密码,每次对服务器证书进行签名都需要这个密码,最少4位
openssl req -x509 -newkey rsa:2048 -out cacert.pem -outform PEM -days 1825

以上步骤生成了自建 CA 机构的根证书和私钥文件:

  • myCA/cacert.pem: CA 根证书
  • myCA/private/cakey.pem: CA 私钥

2.2 创建服务器证书并用CA签名

首先创建一个服务器目录来存放服务器相关信息:

# 在 myCA 同级目录下创建 server 目录存放服务器相关信息
cd .. && mkdir server && cd server

使用任何你熟悉的编辑器在 server 目录下新建一个 server.cnf 文件来配置服务器信息:

#
# server.cnf
# [ req ]
prompt = no
distinguished_name = server_distinguished_name [ server_distinguished_name ]
commonName = localhost # 服务器域名,由于在本地测试,设为 localhost 即可
stateOrProvinceName = JS # 服务器所在省份
countryName = CN # 服务器所在国家(仅限2字符)
emailAddress = Hui4401@qq.com # 邮箱
organizationName = USTC # 组织名
organizationalUnitName = SE # 单位名

生成秘钥对和未经签名的服务器证书文件:

# 设置 openssl 环境变量,以服务器身份运行接下来的 openssl 命令
export OPENSSL_CONF=~/https/server/server.cnf # 生成临时服务器秘钥和未经签名的证书文件
openssl req -newkey rsa:2048 -keyout tempkey.pem -keyform PEM -out tempreq.pem -outform PEM # 将临时私钥转换为未加密状态,也可以直接改名,这样就是加密状态,要输入密码才能启动服务器
openssl rsa < tempkey.pem > server_key.pem

然后使用自建 CA 对服务器证书进行签名:

# 设置 openssl 环境变量,以 CA 身份运行接下来的 openssl 命令
export OPENSSL_CONF=~/https/myCA/caconfig.cnf
# 对服务器证书进行签名
openssl ca -in tempreq.pem -out server_crt.pem

删除临时证书和私钥文件:

rm tempkey.pem && rm tempreq.pem

现在,自签名的服务器证书和私钥文件便产生了:

  • server/server_crt.pem: 服务器证书
  • server/server_key.pem: 服务器私钥

2.3 使用https访问服务器

以 apache 为例来配置 https 服务,首先安装 apache:

sudo apt install apache2

apache 默认是 http 访问的,我们需要配置它的 https 服务并启用,首先 cd 到 apache 的可用站点目录:

cd /etc/apache2/sites-available/

其中有一个默认的 ssl 站点 default-ssl.conf,我们不用新建站点,修改它里面的 ssl 配置并启用即可,修改这个文件需要 sudo 权限,打开后找到其中的证书和私钥设置,修改为自己的服务器证书和私钥文件位置:

SSLCertificateFile  /home/{username}/https/server/server_crt.pem
SSLCertificateKeyFile /home/{username}/https/server/server_key.pem

然后重启 apache 服务器:

# 启用默认 ssl 站点和 ssl 模块
a2ensite default-ssl.conf
a2enmod ssl
# 重启 apache 服务
systemctl restart apache2

到这一步我们的 https 服务就搭建完成了,接下来在浏览器中手动导入自建 CA 的根证书,以 Chrome 为例,进入设置 -> 隐私设置和安全性 -> 安全 -> 管理证书 -> 授权机构,点击导入,选择 myCA 目录下的证书文件 cacert.pem,确定导入,然后就可以在列表中找到我们的 CA 根证书,看看证书信息:

打开浏览器访问:https://localhost

Chrome 比较严格,即使手动导入了 CA 根证书,它仍然不信任这个网站,但是访问是没有问题的,查看一下服务器下发的证书信息:

手动搭建 https 服务完成。

使用OpenSSL自建一个HTTPS服务的更多相关文章

  1. 基于gulp编写的一个简单实用的前端开发环境好了,安装完Gulp后,接下来是你大展身手的时候了,在你自己的电脑上面随便哪个地方建一个目录,打开命令行,然后进入创建好的目录里面,开始撸代码,关于生成的json文件请点击这里https://docs.npmjs.com/files/package.json,打开的速度看你的网速了注意:以下是为了演示 ,我建的一个目录结构,你自己可以根据项目需求自己建目

    自从Node.js出现以来,基于其的前端开发的工具框架也越来越多了,从Grunt到Gulp再到现在很火的WebPack,所有的这些新的东西的出现都极大的解放了我们在前端领域的开发,作为一个在前端领域里 ...

  2. 【HTTPS】自签CA证书 && nginx配置https服务

    首先,搭建https服务肯定需要一个https证书.这个证书可以看做是一个应用层面的证书.之所以这么说是因为https证书是基于CA证书生成的.对于正式的网站,CA证书需要到有资质的第三方证书颁发机构 ...

  3. 网络服务器之HTTPS服务

    import ssl, socket, time if __name__ == "__main__": context = ssl.SSLContext(ssl.PROTOCOL_ ...

  4. 为苹果ATS和微信小程序搭建 Nginx + HTTPS 服务

    昨天测试开发微信小程序,才发现微信也要求用HTTPS加密数据,想来是由于之前苹果的ATS审核政策的缘故吧,微信想在苹果上开放小程序必然也只能要求开发者必须使用HTTPS了,于是在服务器上测试安装Ngi ...

  5. 5个步骤创建你的第一个RESTFul 服务

    1.啥是RESTFul 服务 在我们创建简单小程序前,先来学习下RESTFul 服务.RESTFul服务就是遵循了 Representational State Transfer(可以参考http:/ ...

  6. .Net Core和jexus配置HTTPS服务

    花了几天时间,看了好多篇博客,终于搞定了网站的HTTPS服务,借此写篇博客,来让有需要的朋友少走弯路. 一.环境介绍 1.Linux下在Docker容器中部署好了一个网站,该网站需要通过外部提供程序访 ...

  7. centos httpd开启https服务并申请免费https

    安装httpd yum -y install httpd httpd配置文件路径  /etc/httpd/conf/httpd.conf 安装OpenSSL yum install mod_ssl o ...

  8. 本地开启https服务

    ### ##自签名证书 ##配置Apache服务器SSL ##自己作为CA签发证书 ###这里是OpenSSL和HTTPS的介绍 OpenSSL HTTPS 开启HTTPS配置前提是已在Mac上搭建A ...

  9. 给你的Kubernetes集群建一个只读账户(防止高管。。。后)

    给你的Kubernetes集群建一个只读账户 需求:我们知道搭完k8s集群会创建一个默认的管理员kubernetes-admin用户该用户拥有所以权限,有一天开发或测试的同学需要登录到k8s集群了解业 ...

随机推荐

  1. centos使用U盘做启动盘

    软件下载地址: http://sourceforge.net/projects/iso2usb/files/latest/download?source=dlp 写于: 2014年08月04日 更新于 ...

  2. CorelDRAW不同选择工具的作用及用法汇总

    在CorelDRAW中,"选择工具"是我们的好助手之一."选择工具"图标位于CDR界面左边的工具箱中.使用鼠标单击图标右下角的小三角,我们可以看到"选 ...

  3. 思维导图软件iMindMap幻灯片设置功能介绍

    我们运用iMindMap演示来播放幻灯片时,有没想过,我怎么改动幻灯片的播放时长,怎么设置它的播放速度这些基本设置呢.下面,本文就告诉你,我们该去哪里修改这些iMindMap幻灯片设置: 我们打开iM ...

  4. 系统兼容软件CrossOver和虚拟机软件,哪个好用?

    想要在Mac上运行Windows软件的方法有很多种,比较常见的有安装双系统以及虚拟机.但是安装双系统会导致一个很大的问题,就是占用了过多的硬盘空间,这样一来会导致可使用的空间减少. 目前来说,大家都不 ...

  5. FL studio系列教程(十四):如何在FL Studio播放列表中排列样式

    我们在FL Studio中做好了节奏样式后就可以在播放列表窗口中进行乐曲的编排了.刚接触这款软件的同学肯定会对如何编排比较陌生但也比较憧憬的,因为它是从一个窗口到另一个窗口中的操作.其实明白了这里的知 ...

  6. H5系列之常用的语义元素

    H5添加了几个新标签,带有语义化的标签,像我们的div 和 span 标签,你说他两能干嘛呢, 好像他两什么事都能干.举个例子,你家里的房子,有几个房间,如果不分房间的话,是不是你 今天睡这里,明天睡 ...

  7. 基于Python Requests的数据驱动的HTTP接口测试

    发表于:2017-8-30 11:56  作者:顾翔   来源:51Testing软件测试网原创 http://www.51testing.com/html/69/n-3720769-2.html   ...

  8. 【微信开发】缓存的asscess_token过期

    开发中有遇到这样一个问题,我们一般会将从微信拿到的寿命2个小时的access_token缓存起来,业务里这个缓存的时间是90分钟, 90分钟之后缓存过期,会重新请求新的access_token使旧的a ...

  9. SpringBoot中JPA的学习

    SpringBoot中JPA的学习 准备环境和项目配置 写一下学习JPA的过程,主要是结合之前SpringBoot + Vue的项目和网上的博客学习一下. 首先,需要配置一下maven文件,有这么两个 ...

  10. Netty源码解析 -- 内存池与PoolArena

    我们知道,Netty使用直接内存实现Netty零拷贝以提升性能, 但直接内存的创建和释放可能需要涉及系统调用,是比较昂贵的操作,如果每个请求都创建和释放一个直接内存,那性能肯定是不能满足要求的. 这时 ...