LetEncrypt为域名证书,需要先申请域名,并配置解析。
本文以www.example.com为例,请替换所有www.example.com为自己的域名
nginx需要安装sub_filter与ssl模块
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module
一、nginx 配置ssl证书反向代理tomcat
安装 acme.sh
curl https://get.acme.sh | sh
cd ~/.acme.sh/
http验证
yum install socat
需要保证80端口未被占用,如果nginx占用了80端口,需要先停止nginx
sh acme.sh --issue -d www.example.com --standalone
copy证书至nginx目录下
cd /root/.acme.sh/www.example.com
cp www.example.com.cer /usr/local/nginx/conf
cp www.example.com.key /usr/local/nginx/conf
nginx配置
在http如下配置
upstream tomcat {
server 127.0.0.1:8080 fail_timeout=0; #反向代理到本地tomcat端口
}
server { #监听80端口http访问,强制跳转到https
listen 80;
server_name 127.0.0.1;
location / {
rewrite ^(.*)$ https://www.example.com$1 permanent; #重写为https
}
}
server {
listen 443 ssl;
server_name 127.0.0.1;
ssl_certificate /usr/local/nginx/conf/www.example.com.cer;
ssl_certificate_key /usr/local/nginx/conf/www.example.com.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
underscores_in_headers on;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header referer “$host“;
proxy_redirect off;
proxy_connect_timeout 240;
proxy_send_timeout 240;
proxy_read_timeout 240;
# note, there is not SSL here! plain HTTP is used
proxy_pass http://tomcat;
sub_filter 74.xxx.xxx.xxx www.example.com; #替换ip为域名,74.xxx.xxx.xxx为服务器ip
sub_filter_once off;
}
}
tomcat配置
开启ssl支持
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" proxyPort="443" URIEncoding="UTF-8"/>
并添加
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for"
remoteIpProxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto"/>
更新证书
目前证书在 60 天以后会自动更新, 你无需任何操作. 今后有可能会缩短这个时间, 不过都是自动的, 你不用关心.
更新 acme.sh
目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.
升级 acme.sh 到最新版 :
acme.sh --upgrade
如果你不想手动升级, 可以开启自动升级:
acme.sh --upgrade --auto-upgrade
关闭自动更新:
acme.sh --upgrade --auto-upgrade 0
二、tomcat 服务器配置ssl证书
下载脚本
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
获取证书
./letsencrypt-auto certonly --standalone --email email@qq.com -d example.com -d www.example.com
注意将上面的邮箱和域名替换成自己的。上面命令中的 certonly 表示只获取证书,不安装;-d 有两个,表示将要获取的SSL证书绑定两个域名。运行前需要保证80端口未被占用。
上面的命令在执行过程中,会有两次确认。命令执行完成后,如果看到提示信息"Congratulations! Your certificate and chain..."就说明证书创建成功了
成功之后再/etc/letsencrypt/live/example.com/目录会生成4个证书
cd /etc/letsencrypt/live/example.com
可以看到
cert.pem
chain.pem
fullchain.pem
privkey.pem
我们需要将 fullchain.pem 和 privkey.pem转换成tomcat支持的 .jks 格式。
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out zyxx_letsencrypt.p12 -name tomcat_letsencrypt
需要输入密码 随便输入
keytool -importkeystore -deststorepass 'zxxx_123' -destkeypass 'zxxx_123' -destkeystore zyxx_letsencrypt.jks -srckeystore zyxx_letsencrypt.p12 -srcstoretype PKCS12 -srcstorepass 'zxxx_123' -alias tomcat_letsencrypt
替换命令中的zxxx_123为上面输入的密码
修改tomcat的server.xml
<Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="/etc/letsencrypt/live/example.com/zyxx_letsencrypt.jks"
keystorePass="zxxx_123"
/>
keystorePass 为上面输入的密码
出于安全原因,Let's Encrypt 颁发的 SSL 证书有效期为90天,我们可以通过自动续期来解决。如果到期没有更新证书,Let's Encrypt 会向申请证书时提交的email发送提醒邮件。
进入到 letsencrypt-auto 脚本所在目录,执行下面的命令即可完成 SSL 证书的续期。
./letsencrypt-auto renew
默认情况下,在证书即将到期之前才能执行续期操作,否则会提示“Cert not yet due for renewal”,即证书尚未到期。如果需要强制执行续期操作,可以加上参数 --force-renew ,命令如下:
./letsencrypt-auto renew --force-renew
如果nginx想使用这4个证书实现ssl需要在server中添加如下配置。
listen 8081 ssl;
server_name nginx;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
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;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
add_header Strict-Transport-Security max-age=60;