A script that helps distribute/update local SSL certs from a centrally managed remote location via SCP or FTP. This allows reducing exposure to external services by retrieving SSL (wildcard) certificates from a single (centrally managed) ACME instance (e.g.) or a pfsense/opnsense box. Useful for local network Split-Brain-DNS Setups or for Demilitarized Zones (DMZ).
apt-get install ftp openssl sshpass
Note:
ftpis only needed if not usingscp.sshpassis only needed when usingscpwith a (password protected) keyfile
- Console
cd /etc/nginx/
# or /etc/apache2/
mkdir ssl
apt-get install ftp # if using ftp
git clone [email protected]:Sieboldianus/ssl_get.git
cd ssl_get
cp .env.example .env
nano .envChange the parameters in .env to your needs.
It is possible to define any after-script-hook
in .env such as reload service nginx, apache,
or docker restart. The command must be defined as
a variable RESTART_CMD that will be executed via
via /bin/bash in check_cert.sh.
Test script:
sh check_cert.shAdd cron:
sudo crontab -eAdd lines:
5 8 * * 0 /etc/nginx/ssl_get/check_cert.shThis will verify expiration of local SSL certs once a week at 08:05 and pull new certificates from the remote location, if expiring within the next 14 days. Adjust this default time buffer in check_cert.sh.
Use (e.g.) crontab.guru to change frequency/ timespan. If you have multiple servers pulling certificates and if you are using FTP, provide some variance to avoid FTP Error 421 (Too many simultaneous connections).
This is not related to this script in particular.
To store your wildcard certificates from the ACME script on pfsense or opnsense in a remote folder, go to Services > Acme Certificates and click on Edit SSL Certificate.
- Under Action list, add an action after "/etc/rc.restart_webgui" with the following target
sh /conf/acme/ftp.sh
- Create this script, to forward SSL certs to the central remote folder, e.g.
ftp -n $HOST <<END_SCRIPT
quote USER $USER
quote PASS $PASSWD
binary
cd certs
prompt
mput $FILE
quit
END_SCRIPT
exit 0Inspect crontab logs
sudo find /var/log/. -name \syslog.*.gz -print0 | xargs -0 zgrep "check_cert.sh"
# or individual
sudo grep "check_cert.sh" /var/log/syslog
sudo grep "check_cert.sh" /var/log/syslog.1
sudo zgrep "check_cert.sh" /var/log/syslog.2.gz
> Mar 21 08:05:01 cloud CRON[25307]: (root) CMD (/etc/nginx/check_cert.sh)
...Also, check mail:
mail
Example
Message 1:
From root@service Sun Aug 29 08:05:02 2021
X-Original-To: root
From: root@service (Cron Daemon)
To: root@service
Subject: Cron <root@service> /etc/apache2/ssl_get/check_cert.sh
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
Date: Sun, 29 Aug 2021 08:05:02 +0200 (CEST)
Checking SSL expiration date of wildcard.local.mytld.com.fullchain..
/etc/apache2/ssl/wildcard.local.mytld.com.fullchain
Expiration date not yet reached (notAfter=Sep 9 00:16:51 2021 GMT)
Test all crontab entries:
crontab -l | grep -v '^#' | cut -f 6- -d ' ' | while read CMD; do eval $CMD; doneCheck expiration of web address manually:
openssl s_client \
-servername service.local.mytld.com \
-connect service.local.mytld.com:443 | openssl x509 -noout -datesCheck SSL cert:
openssl s_client \
-showcerts -connect service.local.mytld.com:443 </dev/nullCheck local SSL cert from disk:
openssl x509 -noout -text -in wildcard.local.mytld.com.fullchain