近几年,在浏览器厂商的强力推动下,HTTPS的使用率大增。据统计,Firefox加载的网页中启用HTTPS的占比为67%,谷歌搜索结果中HTTPS站点占比已达50%,HTTPS网站已获得浏览器和搜索引擎的共同青睐。据悉,浏览器开发商Mozilla,Google准备采取下一步措施:将所有的HTTP网站标记为不安全。
近两年,微信小程序也异常火爆,小程序相关话题频频在朋友圈刷屏。如果你想开发微信小程序,一样绕不开HTTPS。根据微信小程序开发文档介绍,小程序与服务器交互必须使用HTTPS协议。
不管是大势所趋,还是实际项目开发需要,掌握如何给网站添加HTTPS协议支持(Web服务器设置使用SSL证书后,网站就能支持HTTPS访问了)都是非常有必要的。
一般来说,很多公司都会直接购买由GlobalSign、GeoTrust、Verisign等全球公认的数字证书颁发机构颁发的SSL证书。购买?没错,大多数SSL证书都需要按年付费使用,而且价格不菲。很多小公司、创业团队或个人开发者往往不愿意承担这笔费用,那有没有免费的SSL证书可以使用?
Let's Encrypt 是一个免费、开放,自动化的证书颁发机构,由 ISRG(Internet Security Research Group)运作。ISRG 是一个关注网络安全的公益组织,其赞助商包括 Mozilla、Akamai、Cisco、EFF、Chrome、IdenTrust、Facebook等公司。ISRG 的目的是消除资金和技术领域的障碍,全面推进网站从HTTP到HTTPS过度的进程。
目前,包括FireFox、Chrome在内的主流浏览器都支持Let's Encrypt证书,已经有不少用户在真实项目中使用Let's Encrypt证书。Let's Encrypt免费SSL证书的有效期是90天,到期后可以再续期,这样也就可以变相长期使用了。
项目主页:https://github.com/letsencrypt/letsencrypt
实验环境
[plain] view plain copy
- Ubuntu 14.04.2 LTS
- Python 2.7.6
- tomcat-7.0.68
PS:所有不说明实验环境的技术文章都是耍流氓!
笔者使用的是一台 Ubuntu 测试机,上面没有跑 Apache 和 Nginx,单独运行的 Tomcat,然后通过 iptables 进行端口转发(将 80 端口的请求转发到 8080,将 443 端口的请求转发到 8443),并且已完成域名解析。
获取Let's Encrypt免费SSL证书
首先,我们需要从 https://github.com/letsencrypt/letsencrypt 上下载 letsencrypt-auto 脚本,使用它能够很方便地完成域名验证和SSL证书的获取。
[plain] view plain copy
- # 使用git下载脚本
- $ git clone https://github.com/letsencrypt/letsencrypt
- # 进入到脚本所在目录
- $ cd letsencrypt
- # 查看 letsencrypt-auto 工具的用法
- $ ./letsencrypt-auto --help
脚本下载好了,来看看怎么使用吧。letsencrypt-auto工具的用法如下:
[plain] view plain copy
- root@iZ28425ljejZ:~/letsencrypt# ./letsencrypt-auto --help
- -------------------------------------------------------------------------------
- letsencrypt-auto [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...
- Certbot can obtain and install HTTPS/TLS/SSL certificates. By default,
- it will attempt to use a webserver both for obtaining and installing the
- certificate. The most common SUBCOMMANDS and flags are:
- obtain, install, and renew certificates:
- (default) run Obtain & install a certificate in your current webserver
- certonly Obtain or renew a certificate, but do not install it
- renew Renew all previously obtained certificates that are near expiry
- -d DOMAINS Comma-separated list of domains to obtain a certificate for
- --apache Use the Apache plugin for authentication & installation
- --standalone Run a standalone webserver for authentication
- --nginx Use the Nginx plugin for authentication & installation
- --webroot Place files in a server's webroot folder for authentication
- --manual Obtain certificates interactively, or using shell script hooks
- -n Run non-interactively
- --test-cert Obtain a test certificate from a staging server
- --dry-run Test "renew" or "certonly" without saving any certificates to disk
- manage certificates:
- certificates Display information about certificates you have from Certbot
- revoke Revoke a certificate (supply --cert-path)
- delete Delete a certificate
- manage your account with Let's Encrypt:
- register Create a Let's Encrypt ACME account
- --agree-tos Agree to the ACME server's Subscriber Agreement
- -m EMAIL Email address for important account notifications
- More detailed help:
- -h, --help [TOPIC] print this message, or detailed help on a topic;
- the available TOPICS are:
- all, automation, commands, paths, security, testing, or any of the
- subcommands or plugins (certonly, renew, install, register, nginx,
- apache, standalone, webroot, etc.)
- -------------------------------------------------------------------------------
这里只对几个重要的命令参数进行说明:
[plain] view plain copy
- run:获取并安装证书到当前的Web服务器
- certonly:获取或续期证书,但是不安装
- renew:在证书快过期时,续期之前获取的所有证书
- -d DOMAINS:一个证书支持多个域名,用逗号分隔
- --apache:使用 Apache 插件来认证和安装证书
- --standalone:运行独立的 web server 来验证
- --nginx:使用 Nginx 插件来认证和安装证书
- --webroot:如果目标服务器已经有 web server 运行且不能关闭,可以通过往服务器的网站根目录放置文件的方式来验证
- --manual:通过交互式方式,或 Shell 脚本手动获取证书
关于域名验证和证书的获取安装,上面提到了5种方式:--apache, --standalone, --nginx, --webroot 和 --manual,请根据实际情况选择其一。再次重申,笔者使用的是公司的其中一台测试机,上面没有跑 Apache 和 Nginx,单独运行的 Tomcat,然后通过 iptables 进行端口转发(将 80 端口的请求转发到 8080,将 443 端口的请求转发到 8443),并且已完成域名解析。因此,笔者选择采用 --standalone 方式进行域名验证和证书获取。
[plain] view plain copy
- # 获取证书
- $ ./letsencrypt-auto certonly --standalone --email 58472399@qq.com -d quqianzhao.top -d www.quqianzhao.top
此处需要注意:
(1)执行此命令必须使用 root用户获得文件夹的权限
(2)域名能访问并且有绑定的公网IP
(3)必须在此域名绑定的服务器上运行
(4)会使用80断端口,如果nginx监听80端口,把nginx先关掉
注意将上面的邮箱和域名替换成自己的。上面命令中的 certonly 表示只获取证书,不安装;-d 有两个,表示将要获取的SSL证书绑定两个域名。
上面的命令在执行过程中,会有两次确认。命令执行完成后,如果看到提示信息"Congratulations! Your certificate and chain..."就说明证书创建成功了,如下图所示。
如果使用nginx,可以直接在nginx上配置,具体参见https://blog.csdn.net/u013378306/article/details/80029828,把自己生成的正证书替换一下
-
server {
-
listen 443 ssl;
-
server_name kf.aigoes.com;
-
#ssl on;
-
-
ssl_certificate /etc/letsencrypt/live/quqianzhao.top/fullchain.pem; #2
-
ssl_certificate_key /etc/letsencrypt/live/quqianzhao.top/privkey.pem; #3
-
ssl_session_cache shared:SSL:1m;
-
ssl_session_timeout 5m;
-
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
-
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
-
ssl_prefer_server_ciphers on;
-
location / {
-
root html;
-
index index.html index.htm;
-
}
-
location /aaa {
-
-
proxy_redirect off;
-
-
proxy_set_header Host $host;
-
-
proxy_set_header X-Real-IP $remote_addr;
-
-
proxy_set_header X-Forwarded-Proto https;
-
proxy_read_timeout 3600s;
-
proxy_pass http://127.0.0.1:8080;
-
-
}}
Tomcat7配置Let's Encrypt免费SSL证书
从上图(证书获取成功的提示信息)可以看出,获取到的 Let's Encrypt 证书保存在 /etc/letsencrypt/live/quqianzhao.top/ 目录下,相关的证书文件有4个:
[plain] view plain copy
- cert.pem
- chain.pem
- fullchain.pem
- privkey.pem
我们需要用到的是后面两个证书文件: fullchain.pem 和 privkey.pem。接下来,还需要用到 Linux 下的 openssl 和 keytool 工具,将SSL证书由 .pem 格式转换成 Tomcat 所支持的 .jks 格式。
[plain] view plain copy
- # 导出.p12格式的证书
- $ openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out zyxx_letsencrypt.p12 -name tomcat_letsencrypt
- # 再将证书由.p12格式转换成.jks格式
- $ keytool -importkeystore -deststorepass 'zxxx_123' -destkeypass 'zxxx_123' -destkeystore zyxx_letsencrypt.jks -srckeystore zyxx_letsencrypt.p12 -srcstoretype PKCS12 -srcstorepass 'zxxx_123' -alias tomcat_letsencrypt
说明:执行 openssl 命令导出 .p12 格式证书时会要求设置密钥,执行 keytool 命令时也有3处要写密钥,最简单的方式就是所有需要密钥的地方,都使用同一个,这样也不会搞混。
经过上面的两步操作,/etc/letsencrypt/live/quqianzhao.top/ 目录下就生成了一个新的证书 zyxx_letsencrypt.jks。接下来,修改 %tomcat%/conf/server.xml 文件,添加 keystoreFile 和 keystorePass 两行配置。其中,keystoreFile 指向 jks 证书文件,而 keystorePass 则为证书的密钥。修改后的关键配置如下:
[plain] view plain copy
- <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="false" sslProtocol="TLS"
- keystoreFile="/home/test/zyxx_letsencrypt.jks"
- keystorePass="zxxx_123"
- />
OK,到这里 Tomcat 的配置工作就完成了。接下来,重启 Tomcat,然后使用浏览器访问 https://www.quqianzhao.top 来验证服务器证书是否生效。
查看服务器证书信息:
Let's Encrypt 证书续期
出于安全原因,Let's Encrypt 颁发的 SSL 证书有效期为90天,我们可以通过自动续期来解决。如果到期没有更新证书,Let's Encrypt 会向申请证书时提交的email发送提醒邮件。
进入到 letsencrypt-auto 脚本所在目录,执行下面的命令即可完成 SSL 证书的续期。
[plain] view plain copy
- ./letsencrypt-auto renew
默认情况下,在证书即将到期之前才能执行续期操作,否则会提示“Cert not yet due for renewal”,即证书尚未到期。如果需要强制执行续期操作,可以加上参数 --force-renew ,命令如下:
[plain] view plain copy
- ./letsencrypt-auto renew --force-renew
以下是笔者强制执行证书续期的操作结果:
[plain] view plain copy
- root@iZ28425ljejZ:~/letsencrypt# ./letsencrypt-auto renew --force-renew
- Saving debug log to /var/log/letsencrypt/letsencrypt.log
- -------------------------------------------------------------------------------
- Processing /etc/letsencrypt/renewal/quqianzhao.top.conf
- -------------------------------------------------------------------------------
- Plugins selected: Authenticator standalone, Installer None
- Renewing an existing certificate
- Performing the following challenges:
- tls-sni-01 challenge for quqianzhao.top
- tls-sni-01 challenge for www.quqianzhao.top
- Waiting for verification...
- Cleaning up challenges
- -------------------------------------------------------------------------------
- new certificate deployed without reload, fullchain is
- /etc/letsencrypt/live/quqianzhao.top/fullchain.pem
- -------------------------------------------------------------------------------
- -------------------------------------------------------------------------------
- Congratulations, all renewals succeeded. The following certs have been renewed:
- /etc/letsencrypt/live/quqianzhao.top/fullchain.pem (success)
- -------------------------------------------------------------------------------
考虑到有可能会忘记续期,或者每3个月就要续期一次太麻烦,可以使用 linux crontab 每两个月(0 0 1 */2 *)执行一次证书续期操作。
关于 https 页面使用http请求的问题
首先https页面不支持http请求,会报错 Mixed Content:This request has been blocked; the content must be served over HTTPS.,
(1)如果请求的地址可以为https,则可以直接在<head> 中加入
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
(2)可以在相应的页面的<head>里加上这句代码,意思是自动将http的不安全请求升级为https
如果必须为http请求,则 可以使用<iframe> 把http请求的页面嵌套进来
最后注意ssl 443端口 防火墙 问题
其他参考地址https://zhuanlan.zhihu.com/p/24996258?refer=diamondfsd