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 的相关信息:

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

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

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

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

  1. # My sample caconfig.cnf file.
  2. #
  3. # Default configuration to use when one is not provided on the command line.
  4. #
  5. [ ca ]
  6. default_ca = local_ca
  7. #
  8. #
  9. # Default location of directories and files needed to generate certificates.
  10. #
  11. [ local_ca ]
  12. dir = /home/{username}/https/myCA # CA 目录
  13. certificate = $dir/cacert.pem
  14. database = $dir/index.txt
  15. new_certs_dir = $dir/signedcerts
  16. private_key = $dir/private/cakey.pem
  17. serial = $dir/serial
  18. #
  19. #
  20. # Default expiration and encryption policies for certificates.
  21. # 认证其他服务器证书设置
  22. default_crl_days = 365 # 默认吊销证书列表更新时间
  23. default_days = 1825 # 默认证书有效期
  24. default_md = sha256 # 默认对证书签名时的摘要算法
  25. #
  26. policy = local_ca_policy
  27. x509_extensions = local_ca_extensions
  28. #
  29. #
  30. # Default policy to use when generating server certificates. The following
  31. # fields must be defined in the server certificate.
  32. #
  33. [ local_ca_policy ]
  34. commonName = supplied
  35. stateOrProvinceName = supplied
  36. countryName = supplied
  37. emailAddress = supplied
  38. organizationName = supplied
  39. organizationalUnitName = supplied
  40. #
  41. #
  42. # x509 extensions to use when generating server certificates.
  43. #
  44. [ local_ca_extensions ]
  45. subjectAltName = DNS:alt.tradeshowhell.com
  46. basicConstraints = CA:false
  47. nsCertType = server
  48. #
  49. #
  50. # The default root certificate generation policy.
  51. # 生成 CA 根证书设置
  52. [ req ]
  53. default_bits = 2048 # 默认生成证书请求时的秘钥长度
  54. default_keyfile = /home/{username}/https/myCA/private/cakey.pem # 默认私钥存放位置
  55. default_md = sha256 # 默认证书签名时使用的摘要算法
  56. #
  57. prompt = no
  58. distinguished_name = root_ca_distinguished_name
  59. x509_extensions = root_ca_extensions
  60. #
  61. #
  62. # Root Certificate Authority distinguished name. Change these fields to match
  63. # your local environment!
  64. #
  65. [ root_ca_distinguished_name ]
  66. commonName = myCA # CA 机构名
  67. stateOrProvinceName = JS # 所在省份
  68. countryName = CN # 所在国家(仅限两字符)
  69. emailAddress = Hui4401@qq.com # 邮箱
  70. organizationName = USTC # 组织名
  71. organizationalUnitName = SE # 单位名
  72. #
  73. [ root_ca_extensions ]
  74. basicConstraints = CA:true

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

  1. # 设置 openssl 环境变量,以 CA 身份运行接下来的 openssl 命令
  2. export OPENSSL_CONF=~/https/myCA/caconfig.cnf
  3. # 生成 rsa 秘钥对和 pem 格式的 CA 自签名根证书,有效期 1825天
  4. # 需要输入密码,每次对服务器证书进行签名都需要这个密码,最少4位
  5. 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签名

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

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

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

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

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

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

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

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

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

  1. rm tempkey.pem && rm tempreq.pem

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

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

2.3 使用https访问服务器

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

  1. sudo apt install apache2

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

  1. cd /etc/apache2/sites-available/

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

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

然后重启 apache 服务器:

  1. # 启用默认 ssl 站点和 ssl 模块
  2. a2ensite default-ssl.conf
  3. a2enmod ssl
  4. # 重启 apache 服务
  5. 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. 增量式爬虫 Scrapy-Rredis 详解及案例

    1.创建scrapy项目命令 scrapy startproject myproject 2.在项目中创建一个新的spider文件命令: scrapy genspider mydomain mydom ...

  2. hashlib模块(摘要算法)

    hashlib(1) # hashlib模块 # 现在写登录认证的时候,需要保存用户名和密码,用户名和密码是保存在文件中,并且都是明文,一旦丢了就完蛋了.所以 # 可以用hashlib将密码转换成密文 ...

  3. kali 系列学习02 - 被动扫描

    被动扫描是指目标无法察觉的情况下进行信息收集,注意有经验的渗透工程师会在信息收集上花费整个测试过程一半以上的时间,信息量太大,需要自动化的信息收集工具. 一.借鉴<kali linux2 网络渗 ...

  4. [COCI2016-2017#1] Mag

    [COCI2016-2017#1] Mag 题解 题目TP门 题目描述 你将获得一棵由无向边连接的树.树上每个节点都有一个魔力值. 我们定义,一条路径的魔力值为路径上所有节点魔力值的乘积除以路径上的节 ...

  5. 【基于PUPPETEER前端自动化框架】【一】TypeScript+Puppeteer+Jest 整合

    前提:掌握Jest + Puppeteer 1.Jest环境配置 2.Jest-MATCHERS匹配器 3.Jest-全局变量设置 4.Puppeteer安装 5.Puppeteer元素获取 6.Pu ...

  6. Pytest学习(十一)- 失败重跑插件pytest-rerunfailures的使用

    环境依赖 Python 3.5, 最高 3.8, or PyPy3 pytest 5.0或更高版本 插件安装 pip3 install pytest-rerunfailures -i http://p ...

  7. go特性-数组与切片

    数组: 复制传递(不要按照c/c++的方式去理解,c/c++中数组是引用传递),定长 切片: 引用传递,底层实现是3个字段 array(数组) + len(长度) +cap(容量) type slic ...

  8. 【mq读书笔记】mq producer启动流程

    创建MQClientInstance实例.这里有个实例缓存 clienrId为客户端IP+instance+(unitname)注意到之前把instance替换为进程id,是为了instance为默认 ...

  9. JDK 15已发布,你所要知道的都在这里!

    JDK 15已经在2020年9月15日发布!详情见 JDK 15 官方计划.下面是对 JDK 15 所有新特性的详细解析! 官方计划 2019/12/12 Rampdown Phase One (fo ...

  10. CPU实现原子操作的原理

    586之前的CPU, 会通过LOCK锁总线的形式来实现原子操作. 686开始则提供了存储一致性(Cache coherence),  这是多处理的基础, 也是原子操作的基础. 1. 存储的粒度 存储的 ...