HTTP后台服务拥抱HTTPS方案

时间:2022-06-11
本文章向大家介绍HTTP后台服务拥抱HTTPS方案,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

自学微信小程序时,看到小程序现在只支持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 : %sn", 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证书管理控制台

进入可以申请亚洲诚信颁发的免费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证书部署至该负载均衡上,证书列表

C.设置负载均衡

然后就去负载均衡里面配置,这里的概念其实文档描述的并不够清晰,我捋一下:

  • 首先,创建HTTP/HTTPS监听器。因为我们走的是默认443端口,如下图填入。这是客户端连接负载均衡的时候要访问的那个端口。
  • 然后,继续点+,创建HTTP/HTTPS转发规则。这里的意思可以根据域名后面的url路径来分发流量,我们设置为/。例如这里可以设置/image转发给某台机器,/text转发给某台机器。均衡方式就是设置用什么方法来分发流量。后面继续下一步填健康检查和会话保持。
  • 最后,绑定云服务器CVM和端口。这里的意思,命中了转发规则后,分发给哪些云服务器、以及端口啊?因为我们的http后台服务在云服务器的8766端口,填入即可。

我们测试下https,可以看到证书和返回结果都正常,成功。

四、总结

这里只是简单举例,其中还涉及到很多东西没有囊括进来。例如依赖负载均衡来实现https,如何进行自动伸缩?云服务器如何设置安全组?等等,后面会继续写文章。

文中一些内容和示例还略简陋,抛砖引玉,共同交流~