从零开始搭建HTTPS服务

 |   

搭建 HTTPS 服务的最初目的是为了开发微信小程序,因为 wx.request 只允许发起 HTTPS 请求,并且还必须和指定的域名进行网络通信。要从零开始搭建一个 HTTPS 的服务需要下面 4 个要素:域名,备案,云服务器,服务搭建。本文将分别介绍这四要素的具体要求。

简介

HTTPS (Hyper Text Transfer Protocol over SecureSocket Layer)叫超文本传输安全协议,是一种通过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换资料的隐私与完整性。这个协议由网景公司(Netscape)在 1994 年首次提出,随后扩展到互联网上,目前基本上所有的网站都使用了 HTTPS 协议。下面就围绕域名,备案,云服务器,服务搭建这 4 个方面来从零搭建 HTTPS 服务。

域名

域名Domain Name)又叫网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位。例如, blog.haojunyu.com 是一个域名,可以通过域名名称系统(Domain Name System)将该域名映射成对应的 IP 地址。该操作可以通过域名解析来实现。

域名注册和解析

域名注册前,可以通过 WHOIS 来查询该域名是否被注册过。目前 BAT 都提供域名注册,如阿里的 万网,百度的 域名服务,腾讯的 Dnspod。我的域名 haojunyu.com 是在阿里的万网注册的,之前注册域名的初衷是为了给 github 上面的个人博客作个性化的域名。并在其中的域名解析中作了设置,这里并不需要做太多的改动,只需要添加如下图的解析记录:

解析记录
设置完成后,当我们向 https://api.haojunyu.com/* 发送请求时,DNS 会自动将其解析为映射的 IP 地址(上图中涂鸦的部分),并向目标服务器请求对应服务。

备案

这里的备案是针对像个人博客这类非经营性网站所做的备案,其目的是为了方便网站的管理。因为只有守法的网站才会对促进信息共享、文化繁荣和社会进步产生积极的作用。

目前网站域名的备案 BAT 都能提供,不过备案这个流程很长,大概要一个月,我的域名 haojunyu.com 是在百度云备案的,当时是先提交的资料(主要是身份证正反面照片),然后等百度快递来背景墙,再拍照片上传核实后才可以备案成功。

云服务器

服务器就是一台可以运行的电脑,可以是自己家里的电脑,也可以到 BAT 上买云服务。这里因为腾讯云上面有免费8天的试用,所以就试着在云服务上面搭建个 https 的服务,以方便微信小程序能成功发起 request 请求。如果试用体验还不错的话,可以续费(74元/月)。新建云主机时要选一个操作系统,鉴于对 Ubutnu 的熟悉以及服务器的需要,所以选择了 Ubuntu Server 16.04.1 LTS 64 的镜像做系统。当新建一个云主机后,百度云会提供一个对外的 IP 地址,这个 IP 地址就是域名解析中要填入的记录值。

服务搭建

服务器的配置主要有三步个,第一步是应用程序的布置,第二步是Nginx服务器的配置,第三步是 http 升级为 https 。前两步的配置是参考这篇博文 在Ubuntu上使用Nginx部署Flask应用,第三步是参考 腾讯云上Nginx证书安装

应用程序

考虑到微信小程序主要是用 json 的数据,所以就想服务器能够提供 restful 服务,又因为对 python 语言比较喜欢,所以就挑了 python 里的 Flask 这个轻量级的 Web 框架。服务器选择的是 Nginx ,而连接服务器和应用程序的是 uWSGI。具体的安装步骤如下:

  1. 环境配置

    1sudo apt-get update && sudo apt-get upgrade # 更新所有软件
    2sudo apt-get install build-essential  # 安装编译环境
    3sudo apt-get install  python python-dev python-setuptools # 安装python环境
    4sudo easy_install pip
    5sudo apt-get install nginx  # 安装Nginx
    6sudo apt-get install uwsgi uwsgi-plugin-python3  # 安装uwsgi及其插件
    7sudo apt-get install supervisor # 安装进程管理软件
    
  2. 应用配置

    1sudo mkdir -p /var/www/flaskApp # 创建应用程序文件夹
    2sudo chown -R ubuntu:ubuntu /var/www/flaskApp # 更改应用程序文件夹所有权
    3sudo pip install virtualenv # 安装python虚拟环境
    4# 创建python虚拟环境
    5cd /var/www/flaskApp
    6virtualenv venv
    7. venv/bin/activate # 激活python虚拟环境venv
    8pip install flask flask-restful # 在虚拟环境中安装flask Web框架
    
  3. 创建api.py代码

     1#!flask/bin/python
     2from flask import Flask, jsonify
     3
     4app = Flask(__name__)
     5
     6tasks = [
     7    {
     8        'id': 1,
     9        'title': u'Buy groceries',
    10        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
    11        'done': False
    12    },
    13    {
    14        'id': 2,
    15        'title': u'Learn Python',
    16        'description': u'Need to find a good Python tutorial on the web',
    17        'done': False
    18    }
    19]
    20
    21@app.route('/todo/api/v1.0/tasks', methods=['GET'])
    22def get_tasks():
    23    return jsonify({'tasks': tasks})
    24
    25if __name__ == '__main__':
    26    app.run(host='0.0.0.0', port=8080)
    

    执行脚本python api.py后可以通过浏览器来访问 http://主机IP:8080/todo/api/v1.0/tasks,以此来获取 tasks 数据。

服务配置

Nginx配置

  1. 删除nginx默认配置文件

    1sudo rm /etc/nginx/sites-enabled/default
    
  2. 创建新的配置文件/var/www/flaskApp/config/flaskApp_nginx.conf

     1server {
     2  listen      80;
     3  server_name api.haojunyu.com; #此时域名已经映射到主机IP
     4  charset     utf-8;
     5  client_max_body_size 75M;
     6
     7  location / { try_files $uri @yourapplication; }
     8  location @yourapplication {
     9      include uwsgi_params;
    10      uwsgi_pass unix:/var/www/flaskApp/config/flaskApp_uwsgi.sock;
    11  }
    12}
    
  3. 创建配置文件服务,重启服务

    1sudo ln -s /var/www/flaskApp/config/nginx.conf /etc/nginx/conf.d/ #将应用文件夹里的配置文件链接到nginx配置文件处
    2sudo nginx -t           # 检验nginx配置是否有误
    3sudo nginx -s reload    # 重新加载nginx配置
    4sudo /etc/init.d/nginx restart  # 重启nginx
    
  4. 验证
    现在通过浏览器来访问 http://api.haojunyu.com/todo/api/v1.0/tasks ,无法获取到数据,因为 flaskApp_uwsgi.sock 尚未生成,无法让 uwsgi 在 Nginx 和 python 应用程序之间构建一座桥。

uWSGI配置

  1. 创建新的配置文件/var/www/flaskApp/config/flaskApp_uwsgi.ini

     1[uwsgi]
     2#application's base folder
     3base = /var/www/flaskApp
     4
     5#python module to import
     6app = api
     7module = %(app)
     8
     9home = %(base)/venv
    10pythonpath = %(base)
    11## 使用virtualenvwrapper管理virtualenv后用下面的两个参数取代home和pythonpath
    12#chdir = %(base)
    13#virtualenvs = %HOME/.virtualenvs/flaskEnv
    14
    15#socket file's location
    16socket = /var/www/flaskApp/%n.sock
    17
    18#permissions for the socket file
    19chmod-socket    = 666
    20
    21#the variable that holds a flask application inside the module imported at line #6
    22callable = app
    23
    24#location of log files
    25logto = /var/log/uwsgi/%n.log
    
  2. 创建uWSGI日志文件夹,并更改文件所有权

    1sudo mkdir -p /var/log/uwsgi # uWSGI日志文件夹
    2sudo chown -R ubuntu:ubuntu /var/log/uwsgi # 更改uWSGI日志文件夹所有权
    3uwsgi --ini /var/www/flaskApp/config/flaskApp_uwsgi.ini --plugin python3 & # 后台启动uwsgi
    

supervisor配置

supervisor 是为了方便管理进程而存在的,因为每次开机后,都得重新执行 uwsgi --ini /var/www/flaskApp/config/flaskApp_uwsgi.ini 命令来启动 uwsgi ,这个很费神,因为你不可能永远记得清楚这么个应用,这么个配置。所以使用 supervisor 来管理,而我们只需要在开发这个应用时创建一个 flaskApp_supervisor.conf 配置文件,而重启机器后启动 supervisor 服务,即执行 sudo service supervisor start

  1. 安装 supervisor

    1sudo apt install supervisor
    
  2. 创建配置文件:

    1[program:flaskApp]
    2# 启动命令入口
    3command=/usr/local/bin/uwsgi --ini /var/www/flaskApp/flaskApp_uwsgi.ini
    4# 运行命令的用户名
    5user=ubuntu
    6autostart=true
    7autorestat=true
    8#日志地址
    9stdout_logfile=/var/log/supervisor/flaskApp_supervisor.log
    
  3. 创建配置文件副本并重启服务

    1sudo ln -s /var/www/flaskApp/flaskApp_supervisor.conf /etc/supervisor/conf.d/
    2sudo service supervisor restart
    

HTTP 升级 HTTPS

升级 HTTP 需要证书的支持,这里 BAT 都提供这样的服务,都有相对应的配置安装说明。我这里是按照 腾讯云上Nginx证书安装,主要就是将申请的证书保存到 config 目录中,并将 flaskApp_nginx.conf 修改如下:

 1server {
 2  listen 80;
 3  server_name api.haojunyu.com;
 4  return 301 https://api.haojunyu.com$request_uri;
 5}
 6
 7server {
 8  listen      443 ssl;
 9  server_name api.haojunyu.com; #此时域名已经映射到主机IP
10
11  ssl on;
12  ssl_certificate /var/www/flaskApp/1_haojunyu.com_bundle.crt;
13  ssl_certificate_key /var/www/flaskApp/2_haojunyu.com.key;
14  ssl_session_timeout 5m;
15  ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照这个协议配置
16  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
17  ssl_prefer_server_ciphers on;
18
19  location / { try_files $uri @yourapplication; }
20  location @yourapplication {
21      include uwsgi_params;
22      uwsgi_pass unix:/var/www/flaskApp/config/flaskApp_uwsgi.sock;
23  }
24}

当时 SSL 的证书有免费的可以用,限制就是一个证书只能帮忙一个二级域名或子域名。如果愿意折腾,可以使用 certbot 来自动化来配置 SSL 证书和定时更新。

certbot官网

详细的安装配置步骤可以参考官网(需要选择代理软件 nginx/apache 等和操作系统 Ubuntu/CentOS/MacOS 等)。

 1# 安装命令
 2sudo apt install certbot python-certbot-nginx  # cerbot及其插件
 3
 4# 配置域名 
 5sudo certbot certonly --nginx --cert-name haojunyu.com -d api.haojunyu.com
 6# 删除配置的域名
 7sudo certbot delete --cert-name haojunyu.com
 8# 查看配置的域名
 9sudo certbot certificates
10# 更新证书
11sudo certbot renew --dry-run

最终效果如下图所示, 访问 https://api.haojunyu.com/todo/api/v1.0/tasks 可以获得对应的数据。

https_api

参考文献

  1. wiki-域名
  2. whois域名查询
  3. 万网
  4. 百度域名服务
  5. Dnspod
  6. 在Ubuntu上使用Nginx部署Flask应用
  7. 腾讯云上Nginx证书安装
  8. certbot
技术茶话会
< 前一篇 后一篇 >