如何使用letsencrypt生成服务器ssl证书

我的VPS系统是CentOS6,以下的全部言论基于CentOS6,并不适用于CentOS7。

查看端口

首先我想查看一下目前系统端口的占用情况,执行一下命令

1
netstat -ntlp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:29187 0.0.0.0: LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:
LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0: LISTEN -
tcp 0 0 :::29187 :::
LISTEN -
tcp 0 0 ::1:25 ::: LISTEN -
tcp 0 0 :::443 :::
LISTEN -
tcp 0 0 :::8443 :::* LISTEN

80端口被nginx占用,443端口被goproxy-vps占用,8443端口被shadowsockR占用。端口都没有问题,处于监听中。

查看防火墙

接下来,查看一下防火墙

1
/etc/init.d/iptables status

Table: filter
Chain INPUT (policy ACCEPT)
num target prot opt source destination

Chain FORWARD (policy ACCEPT)
num target prot opt source destination

Chain OUTPUT (policy ACCEPT)
num target prot opt source destination

注:查看防火墙状态可能会报错,需要重置一下防火墙配置

我没有配置过防火墙,没有端口被防火墙禁止。

下载CertBot

目前Let’s Encrypt推荐使用certbot来生成ssl证书,先下载certbot

1
2
wget https://dl.eff.org/certbot-auto
chmod 755 certbot-auto

解析域名

在生成证书前,需要将域名全部解析到服务器上,否则生成失败。这在我之前的文章中提到过,这里就不赘述。

生成域名证书

1
./certbot-auto certonly --standalone -d yourdomain.com

如果你要生成更多域名,直接后面再加 -d xxxxx.xx 即可啦。

执行命令后报错,需要安装Python 3.0以上版本,缺少Python组件。

Bootstrapping dependencies for RedHat-based OSes that will use Python3… (you can skip this with –no-bootstrap)

No supported Python package available to install. Aborting bootstrap!

走过的弯路

我的VPS上已经安装了Python2.6.6,执行命令查看Python版本

1
python -V

官方说法是Let’s Encrypt使用Python 2.7以上来创建证书。也就是说,要么将Python 2.6.6升级到Python 2.7以上,要么再安装一个Python 2.7以上的版本。因为提示告诉我需要安装Python 3,我采用了后者,安装Python 3.6.3。

1
2
3
4
5
6
7
8
9
10
# 切换到下载文件的目录中
cd /usr/local/
# 下载Python
wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz
# 解压下载的文件
tar -zxvf Python-3.6.3.tgz
# 切换到源码包
cd Python-3.6.3
# 配置指定python的安装目录
./configure --prefix=/usr/local/python3

到配置指定python的安装目录这一步报错,缺少gcc组件,我之前没有安装过。CentOS6上安装Python需要用到gcc,安装gcc

1
yum install gcc

过了之后编译和安装python

1
make && make install

报错没有创建/usr/local/python3文件夹的权限,查看Python-3.6.3文件夹的权限

1
ls -al /usr/local

发现用户名和组权限都是example。将其改成你的用户名和组

1
chown -R yourusername:yourgroupname

注:我之前改了权限也不行,仍然报错没有权限创建目录,不得已切换到root账户去创建,但不推荐这么做,原因是切换回你的用户名之后仍旧没有这个文件夹,它不属于你的账户。后来Python3.6.3行不通,我又换到Python2.7.3,同样的命令就不报错了,不知道为什么。

再一次执行编译安装python,报错

zipimport.ZipImportError: can’t decompress data

需要安装zlib相关的依赖包

1
yum -y install zlib*

再一次编译总算通过了,接下来需要备份原来的python版本

1
mv /usr/bin/python /usr/bin/python2.6.6

创建软链接指向

1
ln -s /usr/local/python3/bin/python3  /usr/bin/python

此时,查看python版本就会看到发生了改变

1
2
python -V
# 3.6.3

更新python过程中,我们有一步是备份原有的老版本python,原因就是系统的很多基本的命令、软件包都要依赖预装的老版本python的,比如yum,千万不要把老版本的删除!新老版本是可以共存的。

升级完Python3.6.3后我们再使用yum命令,发现已经不能使用了,处理方法也很简单

1
2
3
vi /usr/bin/yum
# 把文件头部的改成之前我们备份的老版本号即可
#!/usr/bin/python2.6.6

再次执行生成证书命令后,又报错提示找不到ssl模块,网上的说法是

先查看openssl安装包,如果缺少openssl-devel安装包需要yum安装

1
2
3
rpm -aq|grep openssl 
# openssl-0.9.8e-26.el5_9.1
# openssl-devel-0.9.8e-26.el5_9.1

接下来修改Setup文件

1
vi /usr/local/Python-3.6.3/Modules/Setup

修改成下面的内容

1
2
3
4
5
6
7
8
9
Socket module helper for socket(2)
_socket socketmodule.c timemodule.c

Socket module helper for SSL support; you must comment out the other
socket line above, and possibly edit the SSL variable:
SSL=/usr/local/ssl
_ssl _ssl.c \
-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \

-L$(SSL)/lib -lssl -lcrypto

重新编译

1
make && make install

总算通过了,我心想这一次总算能生成证书了吧,没想到,在生成证书的时候又报错了,这一次提示

“module ‘enum’ has no attribute ‘IntFlag’” when installing python3

找了一圈说是PYTHONPATH环境变量的问题,但是我看下来没啥问题。网上说这是Python 3.6版本会出现的问题,实在没办法,我不得不重新换一个Python版本

安装Python2.7.3

好吧,这也是不得已而为之,前面的步骤和安装Python3.6.3没多少差别,编译几乎没出过问题。

启用EPEL源

但需要注意的是,python2.7里的某些模块依赖于CentOS里的EPEL源,比方说python-virtualenv以及python-pip,CentOS中有的源是被禁用的,比如EPEL。如果不启用epel,证书就无法生成

1
2
3
4
// 查看启用的源列表
yum repolist
// 查看禁用的源列表
yum repolist disabled

通过命令,可以查看到epel源的确被centos处于禁用状态,那么如何启用呢?修改文件

1
vi /etc/yum.repos.d/epel.repo

将文件内容中的enabled=0统统改成enabled=1,即可。

生成证书

在生成证书之前,必须确保nginx处于关闭状态,否则证书生成时会报错。停止nginx服务

1
service nginx stop

最后执行证书生成命令如果成功的话,会有提示

IMPORTANT NOTES:

  • Congratulations! Your certificate and chain have been saved at

/etc/letsencrypt/live/example.com/fullchain.pem. Your cert will

expire on 2018-02-08. To obtain a new version of the certificate in

the future, simply run Let’s Encrypt again.

  • If you like Let’s Encrypt, please consider supporting our work by:

Donating to ISRG / Let’s Encrypt: https://letsencrypt.org/donate

Donating to EFF: https://eff.org/donate-le

GoProxy-VPS添加自证书

证书生成目录在 /etc/letsencrypt/live/,该目录下可以看到对应域名的文件夹。文件夹里的cert.pem以及privkey.pem就是goproxy-vps需要用到的ssl证书了。将这两个文件的内容复制到你的goproxy-vps的配置文件goproxy-vps.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[[http2]]
listen = ":443"
server_name = ["example.org"]
disable_legacy_ssl = false
proxy_fallback = "http://127.0.0.1:80"
proxy_auth_method = "pam"
pem = """
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
"""


[[https]]

listen = ":443"
server_name = ["proxy.example.org"]
proxy_fallback = "http://127.0.0.1:80"
proxy_auth_method = "pam"
pem = """
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
"""

自此,goproxy-vps使用自证书的问题总算完工了。

总结

之前goproxy-vps的missing certificate错误不报了,但是我还是没法翻墙啊,后来无意间,我把代理切换回本地模式,以https协议访问了我的域名网址,竟然能够访问了,还记得上一篇我说无法以https协议访问我的域名网址,估计证书是生效了,但chrome提示证书不安全。然而更有意思的是,我竟然能够翻墙了。顺序必须是先以https协议访问我的域名,让浏览器拿到证书,以后就不用了,然后再翻墙。就在第二天,我再次用https协议访问我的域名,竟然提示证书安全了,不知道为什么会有时间差。莫非VPS主机和我本地客户端存在时差吗?

就目前来看,letsencrypt生成的证书有效期为三个月,过期后还得重新生成证书。如何自动化实现证书续约将是我接来下研究的目标。

avatar

chilihotpot

You Are The JavaScript In My HTML