标记为不安全的,所以为网站添加 https 已经变得刻不容缓。对于商业网站来说,花钱购买 SSL/TLS 证书并不是什么问题。但对于个人用户来说,如果能有免费的 SSL/TLS 证书可用将会是非常幸福的事情! 就是一个提供免费 SSL/TLS 证书的网站,由于其证书期限只有三个月,所以需要我们用自动化的方式去更新证书。本文将介绍如何为通过 docker 运行的 nginx 中的站点添加 https 支持,并自动完成证书的更新。本文的演示环境为:运行在 Azure 上的 Ubuntu 16.04 主机(此图来自互联网):
pid /var/run/<span style="color: #000000">nginx.pid;
events {
worker_connections <span style="color: #800080">2048<span style="color: #000000">;
}
http {
include /etc/nginx/<span style="color: #000000">mime.types;
default_type application/octet-<span style="color: #000000">stream;
sendfile on;
keepalive_timeout </span><span style="color: #800080">65</span><span style="color: #000000">;
client_max_body_size 10M;
include </span>/etc/nginx/conf.d<span style="color: #008000">/*</span><span style="color: #008000">.conf;
}
location </span>^~ /.well-known/acme-challenge/<span style="color: #000000"> {
default_type </span><span style="color: #800000">"</span><span style="color: #800000">text/plain</span><span style="color: #800000">"</span><span style="color: #000000">;
root </span>/usr/share/nginx/<span style="color: #000000">html;
}
location </span>= /.well-known/acme-challenge/<span style="color: #000000"> {
return </span><span style="color: #800080">404</span><span style="color: #000000">;
}
location </span>/<span style="color: #000000"> {
proxy_pass http:</span><span style="color: #008000">//</span><span style="color: #008000">web;</span>
<span style="color: #000000"> }
}
是一个提供免费 SSL/TLS 证书的网站,它为用户提供了 certbot 工具用来生成 SSL/TLS 证书。方便起见,我们把 certbot 简单的封装到容器中。在用户的家目录下创建 certbot 目录,进入 certbot 目录并把下面的内容保存到 Dockerfile 文件中:
后执行下面的命令创建 certbot 镜像:
自动更新证书的脚本 renew_cert.sh,内容如下:
<span style="color: #0000ff">echo <span style="color: #800000">'<span style="color: #800000">Failed domain:<span style="color: #800000">'
<span style="color: #0000ff">for (( i=<span style="color: #800080">0; i<${#Failed_LIST[@]}; i++<span style="color: #000000"> ));
<span style="color: #0000ff">do
<span style="color: #0000ff">echo<span style="color: #000000"> ${Failed_LIST[$i]}
<span style="color: #0000ff">done
<span style="color: #0000ff">fi
用户的家目录中执行 ./renew_cert.sh /home/nick 命令就可以生成新的证书(/home/nick 为当前用户的家目录)。生成的证书被保存在 /home/nick/Nginx/conf.crt/live 目录下,以域名命名的目录下保存着该域名的证书:
Nginx/html 目录,发现多了一个隐藏的 .well-known 目录,这个目录就是在生成证书时创建的:
站点了。
站点配置 SSL/TLS 证书
Nginx 的配置文件就可以了,更新 Nginx/conf.d/default.conf 的内容如下:
listen <span style="color: #800080">80<span style="color: #000000">;
listen [::]:<span style="color: #800080">80<span style="color: #000000">;
server_name filterinto.com www.filterinto.com;
location </span>^~ /.well-known/acme-challenge/<span style="color: #000000"> {
default_type </span><span style="color: #800000">"</span><span style="color: #800000">text/plain</span><span style="color: #800000">"</span><span style="color: #000000">;
root </span>/usr/share/<a href="/tag/Nginx/" target="_blank" class="keywords">Nginx</a>/<span style="color: #000000">html;
}
location </span>= /.well-known/acme-challenge/<span style="color: #000000"> {
return </span><span style="color: #800080"><a href="/tag/404/" target="_blank" class="keywords">404</a></span><span style="color: #000000">;
}
return </span><span style="color: #800080"><a href="/tag/301/" target="_blank" class="keywords">301</a></span> https:<span style="color: #008000">//</span><span style="color: #008000">$server_name$request_uri;</span>
<span style="color: #000000">}
server {
listen <span style="color: #800080">443<span style="color: #000000">;
listen [::]:<span style="color: #800080">443<span style="color: #000000">;
server_name filterinto.com;
# enable ssl
ssl on;
ssl_protocols TLSv1 TLSv1.</span><span style="color: #800080">1</span> TLSv1.<span style="color: #800080">2</span><span style="color: #000000">;
ssl_prefer_server_ciphers on;
ssl_ciphers </span><span style="color: #800000">"</span><span style="color: #800000">EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4</span><span style="color: #800000">"</span><span style="color: #000000">;
# config ssl certificate
<span style="color: #ff0000"> ssl_certificate conf.crt<span style="color: #ff0000">/live/filterinto.com/fullchain.pem;
ssl_certificate_key conf.crt/live/filterinto.com/<span style="color: #000000"><span style="color: #ff0000">privkey.pem;
location </span>^~ /.well-known/acme-challenge/<span style="color: #000000"> {
default_type </span><span style="color: #800000">"</span><span style="color: #800000">text/plain</span><span style="color: #800000">"</span><span style="color: #000000">;
root </span>/usr/share/<a href="/tag/Nginx/" target="_blank" class="keywords">Nginx</a>/<span style="color: #000000">html;
}
location </span>= /.well-known/acme-challenge/<span style="color: #000000"> {
return </span><span style="color: #800080"><a href="/tag/404/" target="_blank" class="keywords">404</a></span><span style="color: #000000">;
}
location </span>/<span style="color: #000000"> {
proxy_pass http:</span><span style="color: #008000">//</span><span style="color: #008000">web;</span>
<span style="color: #000000"> }
}
server {
listen <span style="color: #800080">443<span style="color: #000000">;
listen [::]:<span style="color: #800080">443<span style="color: #000000">;
server_name www.filterinto.com;
# enable ssl
ssl on;
ssl_protocols TLSv1 TLSv1.</span><span style="color: #800080">1</span> TLSv1.<span style="color: #800080">2</span><span style="color: #000000">;
ssl_prefer_server_ciphers on;
ssl_ciphers </span><span style="color: #800000">"</span><span style="color: #800000">EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4</span><span style="color: #800000">"</span><span style="color: #000000">;
# config ssl certificate
<span style="color: #ff0000"> ssl_certificate conf.crt<span style="color: #ff0000">/live/www.filterinto.com/fullchain.pem;
ssl_certificate_key conf.crt/live/www.filterinto.com/<span style="color: #000000"><span style="color: #ff0000">privkey.pem;
location </span>^~ /.well-known/acme-challenge/<span style="color: #000000"> {
default_type </span><span style="color: #800000">"</span><span style="color: #800000">text/plain</span><span style="color: #800000">"</span><span style="color: #000000">;
root </span>/usr/share/<a href="/tag/Nginx/" target="_blank" class="keywords">Nginx</a>/<span style="color: #000000">html;
}
location </span>= /.well-known/acme-challenge/<span style="color: #000000"> {
return </span><span style="color: #800080"><a href="/tag/404/" target="_blank" class="keywords">404</a></span><span style="color: #000000">;
}
location </span>/<span style="color: #000000"> {
proxy_pass http:</span><span style="color: #008000">//</span><span style="color: #008000">web;</span>
<span style="color: #000000"> }
}
删除容器 gateway 并用下面的脚本重新创建:
站点了:
自动更新证书
自动更新证书的方法。自动化更新证书提供了最大的便利(其实是使用 docker 带来的便利),在定时任务中添加下面两条记录就可以了:
Nginx 的配置。
站点(还是免费的)!在方便的同时,其隐患也是显而易见的:既然谁都可以无门槛的获得 SSL/TLS 证书,那么非法网站也可以通过它把自己伪装成看上去合法的站点。 所以千万不要片面的认为 HTTPS 站点就是安全的!