1. Introduction
前两天收到letsencrypt的邮件,说https快到期了,抓紧更新一下。我记得用linux的crontab开启自动更新https证书了,怎么还会收到?浏览器看了下证书日期,的确快要到期了,发现是nginx没有重启,证书缓存没有更新。
本文记录了使用LNMP搭建的博客添加https的过程,也可以参看uwsgi的配置。
2. HTTPS普及
使用https有哪些好处?
- 防止运营商劫持,家庭网络宽带运营商经常干这事
- HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
- HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
缺点是什么?
- 降低网站速度(尽管现在有很多技术可以提高)
- 配置可能麻烦
let's encrypt这个项目通过自动化,把ssl证书使用简单化了。本文就以针对个人用户免费的let's encrypt项目作为示范,官方的自动化工具certbot上https的步骤:
- 在vps上安装certbot
- 创建配置文件
- 执行证书自动化命令
3. 配置HTTPS
3.1 下载certbot
不同的浏览器和不同的webserver可以在certbot上看到相应的教程。
我的vps操作系统是 debian 8.0,但是源里并没有certbot工具,因此需要直接下载可执行文件
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
3.2 certbot验证的过程
certbot实际上在你的webroot下建立了.well-known/acme-challenge/
目录,在验证的时候,会在此目录下生成一些验证文件,然后通过在外部访问你网站的这个文件,如果正确获得了,那么验证通过,并将生成的文件都删除掉。
因此,.well-known
目录的权限很重要,比如lnmp安装的话,在root下执行certbot-auto,那么目录默认www用户是没有权限访问的,会导致验证失败,因此需要在nginx里对这个目录做特殊排除
修改nginx中你的域名的配置文件,比如在lnmp中,默认是/usr/local/nginx/conf/vhost/
,而通过apt默认安装的nginx,配置文件则在/etc/nginx/conf.d/
,在配置文件中添加如下内容:
location ^~ /.well-known {
allow all;
}
表示针对这个目录,允许所有人查看,如果配置文件中含有
location ~ /\.
{
deny all;
}
则需要在此段之前。
注意修改以后,别忘了通过service nginx -s reload
重启nginx。
3.3 对域名签发证书
3.3.1 一个网站目录映射多个域名
比如我的findhao.net 和findhao.net 以及www.的都是一个网站目录(webroot),在nginx的配置文件里,是通过
server_name findhao.net www.findhao.net findhao.net;
来实现映射的,那么使用certbot签发,只需要运行:
certbot-auto certonly --webroot -w /home/wwwroot/findhao.net -d findhao.net -d findhao.net -d www.findhao.net -d www.findhao.net
则就会进入自动验证的过程。 -w
是webroot,-d
是domain的缩写。
3.3.2 多个域名多个webroot
如果有好几个域名需要签发,而且每个域名的webroot(域名的文件存放目录)是不一样的,那就需要运行多次certbot-auto -w a_domain_webroot -d a_domain
。我们也可以给多域名多目录生成一个证书,即一次生成多个域名的一个证书。命令其实和3.3.1是一样的,只不过几个域名的验证文件是相同的。
出现
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/www.findhao.net/fullchain.pem. Your cert will
expire on 2017-09-30. To obtain a new or tweaked version of this
certificate in the future, simply run certbot-auto again. To
non-interactively renew *all* of your certificates, run
"certbot-auto renew"
则表示生成成功!
3.4 修改nginx配置文件
生成好了证书,那么还需要让nginx告诉浏览器你的证书。修改你的域名证书,比如/etc/nginx/conf.d/findhao.net.conf
:
# 一开始默认只有一个server来监听80端口,现在将80端口的访问转发到https上。
server {
listen 80 default_server;
# 监听了多个域名
server_name findhao.net www.findhao.net;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# 你的证书地址
ssl_certificate /etc/letsencrypt/live/findhao.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/findhao.net/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
server_name findhao.net www.findhao.net ;
index index.html index.htm index.nginx-debian.html;
# 这部分是表示将原来的域名,重定向到现在新的域名,如果一台vps
if ($host = 'findhao.net' ) {
rewrite ^/(.*)$ https://www.findhao.net/$1 permanent;
}
# 由于使用的是uwsgi,所以需要将数据转发过去。如果是lnmp之类安装,则这里默认没有下面特殊的规则
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5001;
uwsgi_param UWSGI_CHDIR /root/DownloadYoutube;
uwsgi_param UWSGI_SCRIPT manage:app;
}
}
80端口的监听部分,不建议此时修改,最好在单独测试https可以访问以后,再修改301跳转。
3.5 重启服务
重启nginx服务之前,一定要先用nginx -t
检查配置文件是否有语法错误!!
通过service nginx restart
或者nginx -s reload
或者systemctl nginx restart
。
3.6 nginx 支持HTTP2
如果你按照上面的配置文件添加了http2的关键字,那么在进行配置文件检查错误时,会出现:
nginx: [emerg] invalid parameter "http2" in /etc/nginx/conf.d/ssl.conf:2
nginx: configuration file /etc/nginx/nginx.conf test failed
HTTP2最低要求nginx 1.9.5,但是我vps的debian系统,nginx才1.6,因此需要手动升级nginx。
添加nginx的官方源:
#建立/etc/apt/sources.list.d/nginx.list 文件,内容如下
deb http://nginx.org/packages/mainline/debian/ jessie nginx
deb-src http://nginx.org/packages/mainline/debian/ jessie nginx
然后apt update && apt upgrade
即可发现nginx要求更新。注意,在upgrade时,可能会出现错误提示,说依赖问题。这是因为新版本的nginx已经没有nginx-commen包了。所以需要先卸载原来的版本:
apt-get remove nginx nginx-common
然后再install nginx即可。
3.7 设置开机启动项
手动更新nginx,那原来的nginx开机启动项就没有了,需要手动编写,现在systemd几乎已经统治了常见的linux发行版,因此/etc/rc.local
文件很可能已经没有了。简单学习下systemd的写法即可,你也可以直接用下面官方给的配置文件/lib/systemd/system/nginx.service
:
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
添加完成后,
# 重载所有修改过的配置文件
systemctl daemon-reload
# 先杀掉原来的nginx
pkill nginx
# 立即启动一个服务
systemctl start nginx.service
# 如果提示nginx service is masked,那么先解锁
systemctl unmask nginx.service
# 添加开机启动
systemctl enable nginx.servce
去访问下你的网站看是不是已经可以访问https啦
3.8 设置自动更新证书
由于let's encrypt的证书有效期只有三个月,每隔三个月需要更新一次,官方提供的certbot-auto 即可更新。结合linux的crontab工具即可实现,通过crontab -e
来编辑定时任务列表:
5 2 10 * * /usr/bin/certbot-auto renew --post-hook "lnmp nginx restart"
每个月的10号2点5分执行后面的命令,在执行/usr/bin/certbot renew
之后执行--post-hook
的参数,即重启nginx,这里的lnmp是一键安装工具,如果是普通方式安装nginx,直接使用3.5的重启命令即可。注意一定要重启nginx,不然证书更新以后,nginx还是用的原来的缓存。
Reference
使用 Certbot 自动签发 Let's Encrypt 证书
Comments