黑客见了吐血 -- 手把手教你配置 https 站

2022-06-27 13:34:16 浏览数 (1)

1. 引言

上一篇文章中,我们详细介绍了 SSL 协议与整个通讯流程。 那么,我们如何配置才能让我们自己的网站被浏览器鉴定为安全,并且从根本上保障通讯的安全性呢? 别着急,本文我们就来详细介绍如何配置我们自己的 https 服务。

2. 私钥与公钥的生成

2.1. openssl

我们可以通过开源的 openssl 工具来生成我们的私钥和公钥,openssl 是一个非常强大的开源套件,他包含三个部分:

  1. libcryto — 通用加密库,包含众多加密算法的实现
  2. libssl — ssl 机制的实现,用于实现 TLS/SSL 的功能
  3. openssl — 多功能命令行工具,可以用于加密或解密,甚至可以用来创建和吊销证书

有了 openssl,我们就可以轻松生成配置 ssl 所需的公钥和私钥文件了。

2.1.1. 安装

如果你使用的是 centos,执行下面命令即可:

yum install openssl yum install openssl-devel

如果你使用的是 ubuntu,执行下面的命令:

apt install openssl apt install libssl-dev

此外,你也可以到官网下载源码包编译安装: https://www.openssl.org/

2.2. 生成私钥

执行下面的命令即可生成私钥文件 ssl.key。

openssl genrsa -out ssl.key 2048

参数 2048 是秘钥的比特长度,2009年12月12日,编号为 RSA-768 的秘钥被成功分解,他的长度为 768 比特,1024 比特秘钥的安全性已经受到威胁,因此使用 2048 比特长度的秘钥目前是非常安全的,不建议生成 1024 比特长度的秘钥。

2.3. 生成证书请求csr

执行下面的命令生成包含公钥与服务信息的证书。

openssl req -new -key ssl.key -days 3650 -out ssl.csr

-days 参数是证书的有效期。

2.4. 一键生成上述的私钥与公钥文件

openssl 命令支持意见同时生成公钥与私钥文件:

openssl req -new -newkey rsa:2048 -sha256 -nodes -out test_com.csr -keyout test_com.key -subj "/C=CN/ST=Beijing/L=Beijing/O=website Inc./OU=Web Securi ty/CN=*.test.com"

完成这一步,就已经完成了我们的文件生成工作,如果你要让客户端新人,你必须有一个 CA 颁发的数字证书,到此你有两种选择:使用通用的 CA 认证机构颁发的证书或自己生成根证书与含链证书,具体请分别参考下面两部分中的对应部分。

3. 申请 CA 认证证书

根据我们的上一篇文章可以知道,整个信任链最重要的就是认证机构颁发的证书了。 我们可以找一个免费的 CA 机构,上传上面生成 csr 文件,按照 CA 的提示进行操作验证,最终获取到机构认证的数字证书,保存到服务器目录下。

4. 生成自己的根证书与含链证书

在免费 CA 认证机构中认证证书是最为方便的方式了,但有时,你不希望你的网站或接口被任意访问,因此不能让所有客户端都轻易获取到根证书,显然,在这样的情况下,通过 CA 生成数字证书就无法实现了,我们需要生成自己的根证书与含链证书。

4.1. 生成根证书私钥

我们要实现一个 CA,首先要生成 CA 的私钥,生成命令和过程上面已经介绍过,使用项目命令即可。

4.2. 生成根证书签发申请文件

执行下面的命令可以生成根证书:

openssl req -new -key ca/ca.key -out ca.csr

4.3. 签发根证书

执行下面的命令签发根证书:

openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.crt

4.4. 签发服务端数字证书

执行下面的命令签发服务端数字证书:

openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key

5. 证书的使用

在生成所有证书以后,我们只要在相应的客户端安装我们生成的 CA 根证书为信任机构,所有 CA 生成的数字证书都会在安装后被信任。 在 python 中,通过 requests 包方法众多 verify 参数传入证书文件地址即可:

代码语言:javascript复制
requests.get('https://exaple.com', verify='ca.crt')

6. nginx 配置

如果你的网站是通过 nginx 做负载均衡的,那么只需要在 server 配置中增加下面的配置即可:

代码语言:javascript复制
listen 443 default ssl;
ssl_certificate /etc/nginx/ssl/techlog/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/techlog/ssl.key;
ssl_session_cache    shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

如同我们开始的图片所示,谷歌浏览器已经自动标记我们的网站为安全的了。

7. 配置 http 请求自动转发到 https

既然我们已经使用了 https 来保障传输的安全性,那么我们就应该废弃原有的 http 请求方式,但我们也不能直接拒绝所有 http 请求。 最好的方式,是通过返回自动跳转代码,让客户端可以自动跳转到 https 的新网站中。 之前 http 协议的介绍中,我们介绍了自动跳转的代码和他们的不同: HTTP 协议简介

主要有两种 code:

  1. 301 Moved Permanently — 永久性转移
  2. 302 Found — 临时跳转

此处应该使用的 301 永久性转移,浏览器等客户端会存储旧链接与新链接的对应关系,下次请求旧链接将直接跳转到新链接,而避免了额外的网络请求。 下面,我们就来介绍如何配置 nginx 来实现这一过程:

7.1. rewrite

我们通过 nginx rewrite 的 flag 参数就可以实现 301 跳转,具体可以参考此前的文章: nginx rewrite 规则的配置

代码语言:javascript复制
server {
    listen 80;
    server_name domain.com;
    rewrite ^(.*) https://$server_name$1 permanent;
}

7.2. return

nginx 配置的 return 指令可以指定返回数据的 code 等信息,我们只要显式指定 301 code 即可。

代码语言:javascript复制
server {
    listen 80;
    server_name domain.com;
    return 301 https://$server_name$request_uri;
}

7.3. error_page

除上述跳转的方式,nginx 也定义了一种错误码,用来强制浏览器跳转到对应的 https 链接,这个错误码就是 497,这是 nginx 的内置 HTTP 状态码,HTTP 协议中并没有定义这个状态码,nginx 会自动处理他并跳转。

代码语言:javascript复制
server {
    listen 80;
    listen 443 ssl;
    server_name domain.com;
    ssl on;
    ssl_certificate     /etc/nginx/ssl/domain.com.crt; 
    ssl_certificate_key /etc/nginx/ssl/domain.com.crt;
    # other
    error_page 497 https://$server_name$request_uri;
}

0 人点赞