背景
现在的网站基本都是全站https了,今年六月Spring团队也开源了nohttp项目,用于查找,替换,阻止Spring项目中http的使用。说明大家的安全意识越来越强,但也不可避免的有一些新的问题出现,如https证书会有过期并没有及时更换。这种情况我们也有遇到,我把处理办法列举一下,供大家参考。
处理方式一
采用被动监控方案,定期检测证书过期时间,并通过zabbix告警。
1,编写zabbix脚本(依赖openssl工具包,需提前安装),如下:
#脚本主要的目的是通过zabbix传入要检测的域名,并把过期时间小于10天的域名记录下来,告警
#!/bin/bash
DOMAIN_LIST=$1
error_msg=""
if [[ -z $DOMAIN_LIST ]]; then
error_msg="ERROR,can't found domain"
fi
count=1
for domain in $DOMAIN_LIST; do
END_TIME=`echo | openssl s_client -servername $domain -connect $domain:443 2>/dev/null | openssl x509 -noout -dates |grep 'After'| awk -F '=' '{print $2}'| awk -F ' +' '{print $1,$2,$4 }'`
END_TIME1=`date +%s -d "$END_TIME"`
NOW_TIME=$(date +%s -d "$(date | awk -F ' +' '{print $2,$3,$6}')")
days=$(($(($END_TIME1-$NOW_TIME))/(60*60*24)))
if [[ $days -lt 10 ]]; then
if [[ $count -eq 1 ]]; then
error_msg="ERROR,"
fi
error_msg=${error_msg}"域名证书 $domain 剩下 $days 天过期;"
let count=$count+1
fi
done
echo $error_msg
2,指定一台机器配置(如监控nginx的机器),配置调用的脚本参数,并重启zabbix-agent客户端:
UserParameter=nginx.ssl.cert.check[*],/etc/zabbix/scripts/ssl_cert_check.sh "$1"
3,在zabbix中创建template,定义zabbix-agent的类型Item,Key的值设置如下:
#your.domain.com your2.domain.com为要监控的域名,多个使用空格分开
#nginx.ssl.cert.check与步骤2的名称相同
nginx.ssl.cert.check[your.domain.com your2.domain.com]
4,定义Trigger,其中Expression设置为检测是否有ERROR字串:
{SslCertCheckTemplate:nginx.ssl.cert.check[your.domain.com your2.domain.com].str(ERROR)}<>0
说明:zabbix的Item的调用时间间隔可设置为每天。可配置对应的Action,通过邮件或微信,钉钉告警。
处理方式二
由于我们大量使用了 https://letsencrypt.org/ 的证书,则可通过ACME协议的命令行工具自动生成,更新证书。我们这边使用acme.sh(https://github.com/Neilpang/acme.sh)(还有其它的支持的客户端(https://letsencrypt.org/docs/client-options/),详细请参考链接)。
首先我列举一下acme.sh的一些tips:
acme.sh的优点:
1,纯shell脚本编写,完全兼容sh,bash
2,支持ACME v1,v2版本
3,支持生成通配符证书
4,不需要root用户权限
5,Docker友好
...
安装方式:
#1,直接使用在线安装方式:
curl https://get.acme.sh | sh
支持的模式,详情见链接(https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert),这里主要是说明一下,如果域名托管到阿里云的DNS API的方式:
1,配置阿里云的Secret与Key的环境变量(使用子帐户需要授于相关权限):
Ali_Secret=xxxx
Ali_Key=xxxxx
2,执行如下命令,生成nginx的证书:
acme.sh --issue --force -d *.example.org --dns dns_ali --nginx
支持直接安装证书到nginx,apache(生成证书后操作):
#--reloadcmd 参数用于指定web server reload操作,如果是apache,则可换成service apache2 force-reload
/root/.acme.sh/acme.sh --install-cert -d *.example.org \
--key-file /usr/local/openresty/nginx/conf/certs/essential_example_org.key \
--fullchain-file /usr/local/openresty/nginx/conf/certs/essential_example_org.pem \
--reloadcmd "service openresty force-reload"
#注意,使用--install-cert操作后,会自动生成一个cron,60天会重新更新一次证书
其它一些详细用法,见 https://github.com/Neilpang/acme.sh/wiki
我们这边有多台nginx,使用cron并不好实现。基于cron的思路,我们就自己定义一个脚本,检测过期,并同步证书到其它节点。脚本如下,供参考:
#!/bin/bash
Ali_Secret=xxx
Ali_Key=xxx
domain="www.example.org"
END_TIME=`echo | openssl s_client -servername $domain -connect $domain:443 2>/dev/null | openssl x509 -noout -dates |grep 'After'| awk -F '=' '{print $2}'| awk -F ' +' '{print $1,$2,$4 }'`
END_TIME1=`date +%s -d "$END_TIME"`
NOW_TIME=$(date +%s -d "$(date | awk -F ' +' '{print $2,$3,$6}')")
days=$(($(($END_TIME1-$NOW_TIME))/(60*60*24)))
# check ssl cert
if [[ $days -lt 10 ]]; then
/root/.acme.sh/acme.sh --issue --force -d *.example.org --dns dns_ali --nginx
\cp -rf /root/.acme.sh/\*.example.org/\*.example.org.key /usr/local/openresty/nginx/conf/certs/essential_example_org.key
\cp -rf /root/.acme.sh/\*.example.org/fullchain.cer /usr/local/openresty/nginx/conf/certs/essential_example_org.pem
service openresty force-reload
rsync -e "ssh -p17942" --delete -avpz /usr/local/openresty/nginx/conf/ root@xxx.xxx.xxxx.xxxx:/usr/local/openresty/nginx/conf/
sleep 3
ssh -p 17942 -l root other-nginx-host-name 'service openresty force-reload'
fi




