自学微信小程序时, 看到小程序现在只支持 https 了. 而且现在 Chrome 中浏览 http 的网站, 网址前都会直接显示 "不安全" 字样. http 是明文传输, 相当于所有信息在网络上裸奔, 没有安全性可言. 现在都 2018 年了, 大家在做新项目的时候还是都上 https 吧.
这篇文章会简单介绍 https 的连接过程, 然后用 go 语言实现一个简单的 http 服务, 最后用例子演示了如何用 nginx 和腾讯负载均衡来改造 http 服务, 使其切换到 https.
一, 为什么要拥抱 https
https 可以理解为 http over ssl, 既把 http 明文流量通过 ssl 协议进行加密传送, 从而保证数据的安全性. 这里依赖的是非对称加密和对称加密. 网上相关介绍的文章很多, 简单列一下.
https 建立连接
客户端在使用 HTTPS 方式与 web 服务器通信时有以下几个步骤, 如图所示.
(1)客户使用 https 的 URL 访问 Web 服务器, 要求与 Web 服务器建立 SSL 连接.
(2)Web 服务器收到客户端请求后, 会将网站的证书信息 (证书中包含公钥) 传送一份给客户端.
(3)客户端的浏览器与 Web 服务器开始协商 SSL 连接的安全等级, 也就是信息加密的等级.
(4)客户端的浏览器根据双方同意的安全等级, 建立会话密钥, 然后利用网站的公钥将会话密钥加密, 并传送给网站.
(5)Web 服务器利用自己的私钥解密出会话密钥.
(6)Web 服务器利用会话密钥加密与客户端之间的通信.
引自: https://www.cnblogs.com/wqhwe/p/5407468.html
在 http 传输前建立了一个安全的加密通道. 几个地方小白可能不清晰, 解释下:
我们后面申请 https 的证书就是图中第 1 步返回的公钥, 用于非对称加密.
非对称加密只是用于客户端和服务端之间, 协商好一个对称加密的密钥, 后面的内容都使用对称机密. 为什么不直接全部用非对称加密呢? 因为非对称加密很慢, 性能差; 对称加密性能更高.
https 的好处:
基于 SSL 证书, 可将站点由 HTTP(Hypertext Transfer Protocol)切换到 HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)-- 即基于安全套接字层 (SSL) 进行安全数据传输的加密版 HTTP 协议.
站点应用 HTTPS 后将有以下优势:
1. 防流量劫持
全站 HTTPS 是根治运营商, 中间人流量劫持的解决方案, 不仅可以杜绝网页中被插入的小广告, 更可以保护用户隐私安全.
2. 提升搜索排名
采用 HTTPS 可以帮忙搜索排名的提升, 提高站点的可信度和品牌形象.
3. 杜绝钓鱼网站
HTTPS 地址栏绿色图标可以帮助用户识别出钓鱼网站, 保障用户和企业的利益不受损害, 增强用户信任.
二, 一个简单的 http 服务
下面会用 golang 实现一个简单 Web 服务, 它会返回 get 请求参数中 name 的参数, 并返回当前服务器的时间. Web 服务走 http, 作为例子方便后面的演示.
2.1 腾讯云服务器 go 环境部署
买了个最低配的腾讯云服务器, 操作系统是: Ubuntu Server 16.04.1 LTS 64 位.
登录服务器, 然后 go 应该是没有安装的. 先下载当前最新的 go 安装包:
Ubuntu@VM-45-13-Ubuntu:~$ wget https://dl.google.com/go/go1.11.Linux-amd64.tar.gz
解压缩:
Ubuntu@VM-45-13-Ubuntu:~$ sudo tar -C /usr/local -xzf go1.11.Linux-amd64.tar.gz
设置环境变量, 文件~/.profile 中增加一行:
export PATH=$PATH:/usr/local/go/bin
生效:
source ~/.profile
测试下, 查看当前 go 版本:
- Ubuntu@VM-45-13-Ubuntu:~$ go version
- go version go1.11 Linux/amd64
2.1.2 运行 Web 服务
设置 go 的 workplace 的路径为 $HOME/go, 在文件~/.profile 中增加一行:
export GOPATH=$HOME/go
然后 source 下:
source ~/.profile
创建文件夹:
mkdir -p ./go/src/testhttps/
2.2 本地部署简单的 Web 服务
我写了个简单的 Web 服务, 创建文件 main.go:
vi ~/go/src/testhttps/main.go
将下面代码复制进去:
- package main
- import (
- "fmt"
- "log"
- "net/http"
- "time"
- )
- func sayHelloTime(w http.ResponseWriter, r *http.Request) {
- r.ParseForm() //parse request
- log.Print(r.Form)
- name := r.Form.Get("name") // get argument
- result := fmt.Sprintf("Hello, %s! Current time : %s\n", name, time.Now()) // send data to client
- fmt.Fprintf(w, result)
- }
- func main() {
- http.HandleFunc("/", sayHelloTime)
- err := http.ListenAndServe("127.0.0.1:8765", nil) // run on 127.0.0.1:8765
- if err != nil {
- log.Fatal("error:", err)
- }
- }
然后就可以运行啦, go build 会生成一个可执行文件 testhttps:
- cd ~/go/src/testhttps
- go build
- ./testhttps
另开个 SSH, 我们发送 get 请求, 地址 http://127.0.0.1:8765/?name=jj. 返回信息如下:
- Ubuntu@VM-45-13-Ubuntu:~$ curl http://127.0.0.1:8765/?name=jj
- Hello, jj! Current time : 2018-10-03 01:09:45.860019907 +0800 CST m=+23.075722862
这时候 Web 服务是跑在本地端口, 外部网络是访问不到了. 接下来要设置反向代理, 让外部访问到.
2.3 设置 nginx 反向代理
安装 nginx:
sudo apt-get install nginx
设置反向代理, 文件 / etc/nginx/sites-available/default 中添加如下:
- server {
- listen 8766;
- server_name *.test.cn;# 这里乱弄得, 后面有用
- location / {
- proxy_pass http://localhost:8765;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_redirect off;
- }
- }
上面的意思是, nginx 监听外部 8766 端口, 将请求转发给 localhost:8765.
打开浏览器访问网址, http:// 你的腾讯云公网 ip:8766/. 可以看到, 我们在外网访问到了该服务.
8766 转发可以访问到
8765 端口外部访问不到
三, 切换 https
接下来, 我们将上面使用 http 协议的 Web 服务切换到 https.
3.1 申请证书
对于 https 协议, 我们可以简单理解为: 通过非对称加密技术建立起一个加密通道, 然后 http 的明文消息走加密信道, 保证安全. 这里的基础是非对称加密, 所以要求有公钥和私钥. 而通常说的 https 证书, 它里面包含了公钥等信息. 我们向可信的证书颁发机构申请证书, 浏览器收到服务器发来的证书会去机构进行签名验证, 确认无误后就可以进行开始建立安全的加密通信了.
企业型证书购买费用
写到这里就会想到很多事情:
由于国外技术的先入和垄断, 这些颁发证书的机构一般都是国外巨头, 我们申请证书虽然有免费的, 但是企业型证书需要交一笔不菲的费用.
这些证书颁发机构拥有你的私钥和公钥, 所以说如果他们想要做恶或者泄露了, 你的加密就没有任何意义了. 不知道大家是否有留意, 之前用 Web 登录 12306 购票网站, 会弹出证书不安全, 因为他们是用的自己颁发的证书, 而不是去机构申请, 可能就是考虑到这点. 但我刚登录了 12306, 发现现在已经切换为美国 DigiCert 机构颁发的证书.
不仅 https 证书, 还有申请域名, 解析等等都要花钱, 凭什么这些中介机构就能躺着赚钱呢? 现在区块链技术的出现, 给用技术打破不信任, 颠覆这些中介结构带来了曙光! 我还是很看好的!
12306 的证书
言归正传, 我用腾讯云里购买的域名作为例子:
3.1.1 腾讯云购买域名
这里不进行详细描述了, 直接买了交钱就行.
3.1.2 申请免费证书
腾讯云 SSL 证书管理控制台 https://console.cloud.tencent.com/ssl
进入可以申请亚洲诚信颁发的免费 1 年的域名型证书, 按照提示申请即可, 通过审核后可以下载证书.
3.2 两种方案
3.2.1 nginx
使用 Web 服务器来做, 这里以 nginx 为例子.
文件 / etc/nginx/sites-available/default 中添加如下, www.example.com 替换为自己的域名.
- server {
- listen 443 ssl;
- server_name www.example.com;
- ssl_certificate /etc/nginx/www.example.com.crt;# crt 的位置
- ssl_certificate_key /etc/nginx/www.example.com.key;# key 的位置
- proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
- location / {
- proxy_pass http://localhost:8765;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_redirect off;
- }
443 端口默认是 https 使用, 然后我们将请求转发给 http://localhost:8765. 这里还有一步就是需要设置域名解析到此云服务器 ip. 可以看到, https 正常访问, 返回结果正常, 我们的域名前有把锁啦!
https 设置成功
3.2.2 腾讯云负载均衡
证书部署到负载均衡
使用腾讯云的负载均衡来实现 https 是更推荐的, 2 个原因:
https 是有一定的性能影响的. 因为涉及到加解密消息, 对于响应和服务器性能都有一定的影响, 这也就是为什么 https 已出现多年没有全面普及的一个原因. 那么现在客户端到负载均衡间是 https 连接, 性能问题由负载均衡搞定, 由腾讯进行硬件级的优化等; 负载均衡再将请求用 http 转发给我们后台的服务器, 之前的代码也不需要做更改.
当流量过大时, 可以方便地进行横向扩展. 负载均衡可以设置按权重, iphash 等方式分发流量给后台.
有唯一一个弊端就是, 目前公网负载均衡是收费的, 0.02 元每小时, 折算每个月才 15 块钱. 所以大家可以根据自己的情况来做选择, 我是认为这点钱无所谓额.
基本流程: 负载均衡 CLB 就是一台服务器, 给我们转发用. 所以我们对域名设置解析, A 类型记录, ip 填入负载均衡 CLB 的 vip. 访问域名就会直接找到负载均衡 CLB, 然后 CLB 再把请求分发给我们绑定的云服务器.
ps: 这里我们针对第二部分的 http 后台服务改造, 端口 8766.
A. 购买负载均衡
先购买一个应用型负载均衡实例:
B. 证书部署到负载均衡
然后将 https 证书部署至该负载均衡上, 证书列表 https://console.cloud.tencent.com/ssl
C. 设置负载均衡
然后就去负载均衡里面配置, 这里的概念其实文档描述的并不够清晰, 我捋一下:
首先, 创建 HTTP/HTTPS 监听器. 因为我们走的是默认 443 端口, 如下图填入. 这是客户端连接负载均衡的时候要访问的那个端口.
然后, 继续点 +, 创建 HTTP/HTTPS 转发规则. 这里的意思可以根据域名后面的 url 路径来分发流量, 我们设置为 /. 例如这里可以设置 / image 转发给某台机器,/text 转发给某台机器. 均衡方式就是设置用什么方法来分发流量. 后面继续下一步填健康检查和会话保持.
最后, 绑定云服务器 CVM 和端口. 这里的意思, 命中了转发规则后, 分发给哪些云服务器, 以及端口啊? 因为我们的 http 后台服务在云服务器的 8766 端口, 填入即可.
我们测试下 https, 可以看到证书和返回结果都正常, 成功.
四, 总结
这里只是简单举例, 其中还涉及到很多东西没有囊括进来. 例如依赖负载均衡来实现 https, 如何进行自动伸缩? 云服务器如何设置安全组? 等等, 后面会继续写文章.
文中一些内容和示例还略简陋, 抛砖引玉, 共同交流~
来源: https://www.qcloud.com/developer/article/1351040