Iawen's Blog

我喜欢这样自由的随手涂鸦, 因为我喜欢风......

在计算机网络上, OpenSSLOpenSSL官方网站是一个开放源代码的软件库包, 应用程序可以使用这个包来进行安全通信, 避免窃听, 同时确认另一端连线者的身份。这个包广泛被应用在互联网的网页服务器上。

其主要库是以C语言所写成, 实现了基本的加密功能, 实现了SSL与TLS协议。OpenSSL可以运行在OpenVMS、 Microsoft Windows以及绝大多数类Unix操作系统上(包括Solaris, Linux, Mac OS X与各种版本的开放源代码BSD操作系统)。

OpenSSL计划在1998年开始, 其目标是发明一套自由的加密工具, 在互联网上使用。OpenSSL以Eric Young以及Tim Hudson两人开发的SSLeay为基础, 随着两人前往RSA公司任职, SSLeay在1998年12月停止开发。因此在1998年12月, 社群另外分支出OpenSSL, 继续开发下去。

OpenSSL支持许多不同的加密算法:

  • 加密: AES、Blowfish、Camellia、Chacha20、Poly1305、SEED、CAST-128、DES、IDEA、RC2、RC4、RC5、TDES、GOST 28147-89、SM4
  • 密码散列函数: MD5、MD4、MD2、SHA-1、SHA-2、SHA-3、RIPEMD-160、MDC-2、GOST R 34.11-94、BLAKE2、Whirlpool、SM3
  • 公开密钥加密: RSA、DSA、ECDSA、ECDHE、迪菲-赫尔曼密钥交换、椭圆曲线密码学、X25519、Ed25519、X448、Ed448、GOST R 34.10-2001、SM2

1. SSH 生成公钥和私钥

是在访问的机子上生成, 然后上传公钥到服务端, 首先查看系统当前熵池的大小: cat /proc/sys/kernel/random/entropy_avail . 如果发现熵池的size 不够, 导致生成random的时候卡住, 则可以通过安装rng-tools自动补充熵池: yum install rng-tools, 同时修改/etc/sysconfig/rngd 文件:

cat /etc/sysconfig/rngd 
OPTIONS="-r /dev/urandom"

启动服务, 并重新查询熵池, 然后生成公钥和私钥:

service rngd start
cat /proc/sys/kernel/random/entropy_avail 
ssh-keygen -t rsa

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh 
chmod 600 ~/.ssh/authorized_keys

# 查询本私钥对应的公钥
chmod 400 newkey.pem
ssh-keygen -y -f newkey.pem

2. 使用 ACME 安装 SSL 证书

acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书. 项目地址: https://github.com/Neilpang/acme.sh

2.1 安装

#curl https://get.acme.sh | sh
curl https://get.acme.sh | sh -s email=my@example.com

2.2 生成证书

acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证

2.2.1 http 方式需要在你的网站根目录下放置一个文件, 来验证你的域名所有权,完成验证. 然后就可以生成证书了

acme.sh --issue -d www.iawen.com -w /data/website/iawen.com/

只需要指定域名, 并指定域名所在的网站根目录. acme.sh 会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证. 最后会聪明的删除验证文件. 整个过程没有任何副作用. 但你需要自己配置 ssl 的配置, 否则只能成功生成证书, 你的网站还是无法访问https. 但是为了安全, 你还是自己手动改配置吧.

ssl on;
ssl_certificate /data/cert/wwwiawen.com.pem;
ssl_certificate_key /data/cert/wwwiawen.com.key;

如果你用的 apache服务器, acme.sh 还可以智能的从 apache的配置中自动完成验证, 你不需要指定网站根目录:

acme.sh --issue -d iawen.com --apache

如果你用的 nginx服务器, 或者反代, acme.sh 还可以智能的从 nginx的配置中自动完成验证, 你不需要指定网站根目录:

acme.sh --issue -d iawen.com --nginx

2.2.2 手动 dns 方式, 手动在域名上添加一条 txt 解析记录, 验证域名所有权.

这种方式的好处是, 你不需要任何服务器, 不需要任何公网 ip, 只需要 dns 的解析记录即可完成验证. 坏处是, 如果不同时配置 Automatic DNS API, 使用这种方式 acme.sh 将无法自动更新证书, 每次都需要手动再次重新解析验证域名所有权。

acme.sh  --issue  --dns   -d mydomain.com --yes-I-know-dns-manual-mode-enough-go-ahead-please

然后, acme.sh 会生成相应的解析记录显示出来, 你只需要在你的域名管理面板中添加这条 txt 记录即可.
等待解析完成之后, 重新生成证书:

acme.sh  --renew   -d mydomain.com --yes-I-know-dns-manual-mode-enough-go-ahead-please

2.3 copy/安装 证书

前面证书生成以后, 接下来需要把证书 copy 到真正需要用它的地方.
注意, 默认生成的证书都放在安装目录下: ~/.acme.sh/, 请不要直接使用此目录下的文件, 例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件. 这里面的文件都是内部使用, 而且目录结构可能会变化.
正确的使用方法是使用 –install-cert 命令,并指定目标位置, 然后证书文件会被copy到相应的位置, 例如:

# Apache example:
acme.sh --install-cert -d example.com \
--cert-file      /path/to/certfile/in/apache/cert.pem  \
--key-file       /path/to/keyfile/in/apache/key.pem  \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd     "service apache2 force-reload"

# Nginx example:
acme.sh --install-cert -d example.com \
--key-file       /path/to/keyfile/in/nginx/key.pem  \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd     "service nginx force-reload"

2.4 更新

目前证书在 60 天以后会自动更新, 你无需任何操作. 今后有可能会缩短这个时间, 不过都是自动的, 你不用关心.
目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.

升级 acme.sh 到最新版 :acme.sh --upgrade
如果你不想手动升级, 可以开启自动升级: acme.sh --upgrade --auto-upgrade, 之后, acme.sh 就会自动保持更新了.
你也可以随时关闭自动更新: acme.sh --upgrade --auto-upgrade 0

3. 本地证书生成

3.1 本地证书

# VSFTP
openssl req -x509 -days 3650 -newkey rsa:1024 -nodes -keyout /etc/vsftpd/vsftpd.key -out /etc/vsftpd/vsftpd.pem

# MONGODB
openssl req -x509 -days 3650 -newkey rsa:2048 -nodes -keyout mongodb-cert.key -out mongodbcert.crt 

3.2 使用 openssl 自行签发证书

3.2.1 CA 私钥

$ openssl genrsa -out "root-ca.key" 4096

3.2.2 利用私钥创建 CA 根证书请求文件

$ openssl req \
-new -key "root-ca.key" \
-out "root-ca.csr" -sha256 \
-subj '/C=CN/ST=Shanxi/L=Datong/O=iawen.com/CN=Iawen.com Docker Registry CA'

以上命令中 -subj 参数里的 /C 表示国家, 如 CN ; /ST 表示省; /L 表示城市或者地区; /O 表示组织名; /CN 通用名称。

3.2.3 配置 CA 根证书

新建 root-ca.cnf

[root_ca]
basicConstraints = critical,CA:TRUE,pathlen:1
keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
subjectKeyIdentifier=hash

3.2.4 签发根证书

$ openssl x509 -req -days 3650 -in "root-ca.csr" -signkey "root-ca.key" -sha256 -out "root-ca.crt" -extfile "root-ca.cnf" -extensions root_ca

3.2.5 生成站点 SSL 私钥

$ openssl genrsa -out "docker.domain.com.key" 4096

3.2.6 使用私钥生成证书请求文件

$ openssl req -new -key "docker.domain.com.key" -out "site.csr" -sha256 -subj '/C=CN/ST=Shanxi/L=Datong/O=iawen.com/CN=Iawen.com Docker Registry CA'

3.2.7 配置证书

新建 site.cnf 文件

[server]
authorityKeyIdentifier=keyid,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage=serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
subjectAltName = DNS:docker.domain.com, IP:127.0.0.1
subjectKeyIdentifier=hash

3.2.8 签署站点 SSL 证书

$ openssl x509 -req -days 750 -in "site.csr" -sha256 -CA "root-ca.crt" -CAkey "root-ca.key" -CAcreateserial -out "docker.domain.com.crt" -extfile "site.cnf" -extensions server

这样已经拥有了 docker.domain.com 的网站 SSL 私钥 docker.domain.com.key 和 SSL 证书 docker.domain.com.crt 及 CA 根证书 root-ca.crt. 新建 ssl 文件夹并将 docker.domain.com.key docker.domain.com.crt root-ca.crt 这三个文件移入, 删除其他文件.