上一节中我们已经基本完成了django项目部署到nginx,这一节我们将http改为https,提升访问的安全性。
我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。
几个概念
https虽然只比http多了一个s,但是却涉及到了很多新的概念,这些概念也很容易混淆。这里不会对https的流程做详细说明,只是为了便于理解,将关键步骤和概念进行简要说明。
对称加密和非对称加密
通信两端用同一个密码来进行信息加密和解密就叫做对称加密,而采用不同密码分别进行加密和解密就要做非对称加密。很容易想到对称加密要更简易和高效,但是安全性较低;相对而言非对称加密更安全,但是实现起来却更复杂。
https中将两者进行了结合。
私钥和公钥
非对称加密中,一个密钥会公布出来,想要给服务器发加密消息就用公布的密钥来加密,服务端保存另一个密钥专门用来解密。这个公布出来的密钥叫做公钥,而不能公开必须自己保存的密钥叫做私钥。当然,用私钥加密的消息也可以反过来用公钥解密。
客户端将用于对称加密的密码通过服务器的公钥加密再发送给服务器,这样就避免了对称加密的密码被人窃取。等到双方都获取了对称加密的密码,后续就可以用对称加密的方式进行高效传输了。
先用非对称加密,再用对称加密,这就是https的原理。
证书
现在问题来了,中间人有可能拦截服务器真正的公钥,而把自己的公钥发给客户端,解密了客户端返回的消息以后再用真正的公钥加密返回给服务器,从而达到嗅探的目的。
题外话,这也是抓包工具fiddler抓取https包的原理
那么客户端怎么知道得到的公钥就是服务器真正的公钥呢?现在的做法是找一个权威的第三方机构(Certificate Authority,CA),用CA的私钥对服务器的公钥以及url等等信息一起进行加密,之后再发送给客户端。客户端首先用CA的公钥进行解密获取到真正的服务器公钥,然后再进行后续操作。这个用CA的私钥加密过的用来鉴定服务器公钥真伪的文件就叫做证书。
这个世界上被大众承认的CA本来就不多,拿着自家服务器公钥去找他们申请证书基本是要花钱的。但是也不乏像Let’s Encrypt这种良心CA可以免费提供证书服务,不过前提是要一个可使用的DNA域名才行。
当然,也可以随便找个机构(例如你自己)做为CA给自己的公钥做一个证书。这样的好处是免费而且操作简单,缺点就是在进行https请求的时候会弹出类似如下的警告
证书的警告归警告,但是选择信任证书继续访问之后的数据还是经过加密了的。所以接下来我们会自己做为CA给自己服务器的公钥进行认证。
csr/crt/key/pem的区别
csr全称是certificate signing request,是向CA去申请证书的请求文件的后缀,其中包含了服务器的公钥和一些基本信息。crt是certificate的简写,就是最后拿到的证书文件的后缀。key是密钥的后缀。不同工具有不同编码方式,pem后缀的文件也有可能是证书或者密钥。
实际操作
nginx中已经为我们准备好了https的配置模板,我们需要的只是两个文件而已:服务器的私钥和证书。自己给自己生成签发证书的工具也有很多,这里我们选用openssl。
openssl生成私钥和证书
首先生成私钥文件ca.key
openssl genrsa -out ca.key 1024
然后生成请求文件ca.csr
openssl req -new -key ca.key -out ca.csr
这个过程中会要求输入一些个人信息,类似下面这样,大多数可以直接回车跳过
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SG
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:xiaofu
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
最后把服务器的私钥做为CA的私钥来对刚才的csr进行签发证书
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
提示成功完成操作
Signature ok
subject=/C=SG/L=Default City/O=xiaofu
Getting Private key
这时候就有了证书和私钥了。
nginx配置https
下面编辑nginx配置文件,将下面这一段去注释
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
root /root/projects/therm/API;
ssl_certificate "/root/cert/ca.crt";
ssl_certificate_key "/root/cert/ca.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /static {
#alias /root/projects/therm/API/static;
try_files $uri /static/1.jpg;
}
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:9999;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
这里做的修改如下
- 首先按照上一节的方法将root、静态文件以及uwsgi的连接配置的和80端口的一样
ssl_certificate
字段放刚才生成的证书的绝对路径ssl_certificate_key
字段放刚才生成的私钥的绝对路径
之后重新载入nginx配置即可
nginx -s reload
nginx开始监听443端口
(base) [root@ai-therm ~]# netstat -ntlp | grep 443
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 30015/nginx: master
tcp6 0 0 :::443 :::* LISTEN 30015/nginx: master
成功用https访问上一节的测试url
因为是自签名证书,所以会显示Not secure
。如果是用程序访问这种url记得设置为忽略https警告。
总结
通过三节的学习和配置,静态资源、动态资源和加密都搞定了,到这里django项目才算真正部署到了nginx上面。