私网环境启用 https

2019/06/26

本文是搭建私网环境下的 go 自动集成环境的一部分。

go 项目使用 go mod 作依赖包管理,遇到一些问题。 对于依赖库是保存在内网仓库的情况,拉取代码会失败,原因是 go mod 获取 依赖包版本需要使用 https 请求,而自建的 git 服务没有启用 https 。

如果是传统的 gopath 依赖项目, 只需要 go get -insecure 即可绕过 https 限制, 但是这里我们选择用 go mod ,一方面这是 go 官方推荐的方式,也是未来的发展趋势, 另一方面是不希望依赖包放在 vendor 目录下一起提交到版本库造成源码目录过于庞大。

接下来讲一讲如何在私网中启用 https, 服务端系统以 CentOS7 为例。

环境准备

为了达到实验目的,先修改本地机器的 host 文件。

web 服务运行在 192.168.20.44 的局域网 IP 的主机上 添加一条虚拟的域名映射到这个 IP 。

192.168.20.44 vcs.private.org

创建 SSL 证书

创建目录

# 创建目录用于保存公共证书
sudo mkdir /etc/ssl/certs

# 创建目录用于保存私钥文件
sudo mkdir /etc/ssl/private

# 关键目录,设置访问权限
sudo chmod 700 /etc/ssl/private

创建自签名密钥证书对

sudo openssl req -x509 -nodes -days 365 \
    -newkey rsa:2048 -keyout /etc/ssl/private/selfsigned.key \
    -out /etc/ssl/certs/selfsigned.crt

命令参数解释

openssl 用于创建和管理OpenSSL证书,密钥和其他文件的基本命令行工具。

req -x509 表示我们想要使用 X.509 证书签名请求(CSR,certificate signing request)生成签名证书。

-nodes 跳过用密码保护证书的选项。

-days 365 有效期 365 天。

-newkey rsa:2048 同时生成新证书和新密钥,生成 2048 位的 RSA 密钥。

-keyout 密钥输出目录。

-out 证书输出目录。

接下来会被要求填写一些证书的基本信息,需要注意的一点是 CommonName 要填写服务相关的域名或者公共 IP 地址。 此处咱们填写 vcs.private.org

还可以一条命令完成
sudo openssl req -x509 -nodes -days 365 \
    -subj "/C=CN/ST=ZJ/L=HZ/O=private.org/CN=vcs.private.org" \
    -newkey rsa:2048 -keyout /etc/ssl/private/selfsigned.key \
    -out /etc/ssl/certs/selfsigned.crt

创建 Diffie-Hellman 组

据说用于与客户端协商 PFS (Perfect Forward Secrecy),能在私钥受损的情况下保证会话密钥不受损害。

创建要几十秒,需要稍微等一下。

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

这个 DH 组到底有多强大呢,等我学习后再总结下…… Orz

配置 Nginx 使用 SSL

安装 Nginx

# 启用 EPEL 库
sudo yum install epel-release
# 安装
sudo yum install nginx
# 开启
sudo systemctl start nginx
# 检查状态
systemctl status nginx

防火墙配置(如果未开启了防火墙,可跳过)

sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
sudo firewall-cmd --runtime-to-permanent
sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT

添加 TLS/SSL 服务配置块

sudo vim /etc/nginx/conf.d/ssl.conf

内容如下

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name vcs.private.org;

    ssl_certificate /etc/ssl/certs/selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/selfsigned.key;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    root /usr/share/nginx/html;

    location / {
    }

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}

参考这篇文章添加更多安全性配置

启用新配置

先检查配置文件是否有错误

sudo nginx -t

重载新配置

sudo service nginx reload

测试

curl https://vcs.private.org

你会看到报错

curl: (60) Peer's certificate issuer has been marked as not trusted by the user.
More details here: http://curl.haxx.se/docs/sslcerts.html
.....

更新客户端信任证书

服务端启用了 https,接下来让客户端接受这个自签署的证书。

签署好的 selfsigned.crt 文件复制到 /etc/ca-certificates/trust-source/anchors 目录下 运行 sudo update-ca-trust, 没有任何输出即更新成功。

签署好的 selfsigned.crt 文件复制到 /etc/pki/ca-trust/source/anchors 目录下 运行 sudo update-ca-trust extract, 没有任何输出即更新成功。

添加比较麻烦参考这篇文章。 虽然添加完成后 chrome 依旧是不接受这个证书的(应该是浏览器策略的问题),但是 cmd 里 curl 验证可以通过。

客户端信任了证书之后,再次 curl 请求就能成功了。

参考