需求
在nginx配置OCSP结果缓存后,通过openssl查询可以看到OCSP的状态,示例如下:
[root@localhost ~]# openssl s_client -connect www.seafog.cn:443 -servername www.seafog.cn -status -tlsextdebug 2> /dev/null | grep -A 16 'OCSP response'
OCSP response:
======================================
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: 55744FB2724FF560BA50D1D7E6515C9A018*****
Produced At: Jun 30 08:06:33 2022 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 978B4716E5B0F658BAE69DAB1689B8363AE*****
Issuer Key Hash: 55744FB2724FF560BA50D1D7E6515C9A018*****
Serial Number: 0254BD766BD41E41B86F71602E4*****
Cert Status: good
This Update: Jun 30 07:51:01 2022 GMT
Next Update: Jul 7 07:06:01 2022 GMT
可以看到OCSP的状态有7天有效时间,如果超过Next Update没更新的话,在https://www.ssllabs.com/ssltest中检查网站SSL的时候,会提示有以下提示:
OCSP STAPLING ERROR: OCSP response expired on Tue Jun 30 05:30:01 UTC 2022
所以还是有必要定时去更新OCSP缓存文件。因此,使用脚本可以定时更新Nginx的OCSP stapling缓存文件,以及session ticket文件。
实现
Bash脚本实现如下:
#!/bin/bash
USER_ID=501001
GROUP_ID=501001
TRY_COUNT=10
SLEEP_TIME=3
TEMP_FILE='ocsp.resp'
function log(){
echo "$(date +"%Y-%M-%d %H:%m:%S") $1"
}
function get_OCSP(){
CERT_KEY=$1
CA_KEY=$2
OCSP_FILENAME=$3
log "start for $CERT_KEY get_OCSP"
log "CERT_KEY=$CERT_KEY, CA_KEY=$CA_KEY, OCSP_FILENAME=$OCSP_FILENAME"
OCSP_URI=$(openssl x509 -in $CERT_KEY -noout -ocsp_uri)
HOST=$(echo $OCSP_URI | awk -F '/' '{print $3}')
for (( num=1;num<=$TRY_COUNT;num++ ))
do
log "try $num"
openssl ocsp -issuer $CA_KEY \
-cert $CERT_KEY \
-no_nonce \
-text \
-url "$OCSP_URI" \
-header "HOST" "$HOST" \
-text \
-verify_other $CERT_KEY \
-respout $OCSP_FILENAME > $TEMP_FILE 2>&1
grep -q 'OK' $TEMP_FILE
if [ $? -eq 0 ];then
rm -f $TEMP_FILE
log "get OCSP success!"
break
else
log "get OCSP failure!"
log "time sleep $SLEEP_TIME seconds"
sleep $SLEEP_TIME
fi
done
chown $USER_ID:$GROUP_ID $OCSP_FILENAME
}
function refresh_session_ticket(){
SESSION_TICKET=$1
log "start for refresh session_ticket"
openssl rand 80 >$SESSION_TICKET
log "refresh session_ticket success!"
chown $USER_ID:$GROUP_ID $OCSP_FILENAME
}
function nginx_reload(){
NGINX_CONTAINER_NAME=$1
docker exec $NGINX_CONTAINER_NAME nginx -s reload
log "$NGINX_CONTAINER_NAME reload success!"
}
get_OCSP 'www.seafog.cn.pem' 'ca.pem' 'ocsp.pem'
refresh_session_ticket 'session_ticket.key'
nginx_reload 'nginx'
通过执行get_OCSP
、refresh_session_ticket
、nginx_reload
这3个方法来实现获取OCSP缓存、刷新session ticket,以及nginx的reload重载生效。
其中,get_OCSP
方法里生成OCSP的openssl
命令里,添加了-verify_other
,也就是指定我们的完整证书链,也就是 域名证书+中间证书的合并文件,也就是 nginx 里的 ssl_certificate 配置文件。不然生成OCSP文件的时候会报以下错误:
140063168673680:error:27069076:OCSP routines:OCSP_basic_verify:signer certificate not found:ocsp_vfy.c:92:
脚本参数解释及用法如下:
USER_ID
和GROUP_ID
用于更改生成结果文件的权限。TRY_COUNT
是用于在get_OCSP
方法中用来设定错误重试次数,因为由于网络原因,生成OCSP的时候,会经常认证失败,所以需要进行重试。SLEEP_TIME
是用于在get_OCSP
方法中错误重试时的间隔时间。TEMP_FILE
是用于在get_OCSP
方法中生成的临时文件。get_OCSP
方法需要带入3个参数,依次是:- ssl_certificate域名证书
- ssl_trusted_certificate的CA证书
- 生成的ocsp文件名
refresh_session_ticket
方法需要带入1个参数:- 生成的session_ticket.key文件名
nginx_reload
方法需要带入1个参数:- nginx容器的容器名。
另推荐几个可以检查SSL的状态的网站: