Manual auto SSL pe Synology

Pentru ca sunt sărac și nu vreau sa dau o grămadă de bani pe un certificat wildcard pe un an, folosesc o struto-camila intre Cloudflare și Letsencrypt. Chiar dacă Cloudflare oferă certificat gratuit timp de un an (care se reinoieste gratuit o data la un an), nu poți să-l descarci de undeva ca să-l pui și pe alte servere, așa ca am rămas cu Letsencrypt pentru anumite servicii. Problema cu LE este ca certificatul trebuie schimbat la 3 luni, așa ca am încercat sa “automatizez” chestia asta cum am putut eu mai bine.

Disclaimer: Probabil exista și o alta metoda mult mai buna, dar pentru mine funcționează, deci I’m happy with it.

Ca sa înțelegeți putin infrastructura: 1 server web, 1 server de mail, 1 server de docker cu nginx care face reverse proxy și 1 server de “storage” pe un Synology. Singurul lucru comun între “servere”/locații e un certificat SSL.

Am început lejer, cu serverul de mail. Pe serverul de mail rulez un script care verifica atunci când certificatul a expirat și atunci când condiția se întâmplă, face un SSH pe serverul web și copiază certificatele noi, apoi da restart la servicii (postfix și dovecot). Bine, de fapt pe toate rulez același script, diferă doar ce se întâmplă în condiția logica atunci când certificatul expira. Trebuie sa menționez ca serverul web face reînnoire automata prin API-ul DNS Cloudflare cu ajutorul lui certbot. Asta e serverul principal, ca sa zic așa, de la el pornește tot, el deține adevarul.

Pe celălalt server de web/docker se întâmplă același lucru ca pe cel de mail, excepție fiind faptul ca dau restart la nginx și diferă calea unde e pus certificatul.

Iar acum vine durerea mare: NAS-ul Synology. A fost un fel de PITA sa mă prind pe unde isi arunca jegul certificatele, am căutat informații pe Google și am încercat tot felul de chestii pana m-am prins ce și cum. Se pare ca Syno nu folosește locația certificatului dintr-un loc predefinit, ci din mai multe locuri pentru diferite aplicații. Stupid, poate. Eu așa o văd. Te-ai gândi ca ai o locație de unde isi citește certificatele instalate în sistem, dar se pare ca nu, Syno e mai cu mot. Certificatul “principal” se afla în /usr/syno/etc/certificate/system. Certificatele pentru restul de aplicații sunt răspândite prin sistem. În fine, long story short, am ajuns la o varianta a scriptului așa:

#!/bin/bash

NOW=$(date +%s)
CERT_EXPIRY_DATE=$(echo | openssl s_client -servername subdomeniu.linux365.ro -connect subdom.linux365.ro:port 2>/dev/null | openssl x509 -noout -enddate | cut -d "=" -f 2)
CERT_EXPIRY_DATE_UNIX=$(date -d "$CERT_EXPIRY_DATE" +%s)

if [[ $NOW -gt $CERT_EXPIRY_DATE_UNIX ]]; then
    rsync -a --copy-links user@IP:/etc/letsencrypt/live/linux365.ro/ /tmp/certs/ && echo -e "Subject: Syno certs\n\nL365 syno certs sync'ed" | ssmtp [email protected]
	sudo cp -r /tmp/certs/* /usr/syno/etc/certificate/_archive/kVlb4z/
	sudo cp -r /tmp/certs/* /usr/local/etc/certificate/LogCenter/pkg-LogCenter/
	sudo cp -r /tmp/certs/* /usr/local/etc/certificate/ScsiTarget/pkg-scsi-plugin-server/
	sudo cp -r /tmp/certs/* /usr/local/etc/certificate/SynologyDrive/SynologyDrive/
	sudo chown -R root:root /usr/syno/etc/certificate/_archive/kVlb4z/
	sudo chown -R root:root /usr/local/etc/certificate/LogCenter/pkg-LogCenter/
	sudo chown -R root:root /usr/local/etc/certificate/ScsiTarget/pkg-scsi-plugin-server/
	sudo chown -R root:root /usr/local/etc/certificate/SynologyDrive/SynologyDrive/
	sudo chmod u=r -R /usr/syno/etc/certificate/_archive/kVlb4z/*.pem
	sudo chmod u=r -R /usr/local/etc/certificate/LogCenter/pkg-LogCenter/*.pem
	sudo chmod u=r -R /usr/local/etc/certificate/ScsiTarget/pkg-scsi-plugin-server/*.pem
	sudo chmod u=r -R /usr/local/etc/certificate/SynologyDrive/SynologyDrive/*.pem
	rm -rf /tmp/certs/
	sudo reboot
fi

Partea buna la Syno e ca folosește certificatele exact cu numele de la LE, deci nu mai trebuie redenumite. Partea proasta e ca trebuie împrăștiate prin sistem. În principiu /usr/syno/etc/certificate/_archive este calea comuna pentru toate Syno, apoi avem un folder cu un ID generat unde sunt puse efectiv certificatele. Partea de web (nginx) citește din calea aia cu ID certificatul SSL. Restul serviciilor, nu chiar, din câte vedeți. Aș fi putut sa fac symlink către certificatele din folderul _archive, dar mă gândesc ca poate o sa fie rescrise de către DSM la un moment dat, plus ca nu mă deranjează sa copiez certificatele “automat” în restul de foldere.

La final am ales sa dau reboot din mai multe motive. Nu știu toate serviciile ce necesita SSL și care trebuie sa fie restartate după schimbarea certificatului, plus ca sigur o sa rămână vreunul cu certificatul vechi. Dacă vrea cineva să-și bată capul, comanda de restart este synosystemctl restart pkgctl-Synology<MUMU>.service pe DSM 7, sau ceva de genul.

O alta chestie mai cu mot la Syno este faptul ca nu folosește comanda mail cam ca toate sistemele Linux, ci ssmtp. Mă rog, nu e un deal-braker, dar nah, a trebuit sa caut care era problema lui când nu găseam comanda mail, mai ales ca nici în Entware nu exista pachetul.

Dacă interesează pe cineva restul de scripturi o sa le postez, dar probabil no one cares.

Ah, am uitat partea cea mai importanta: cum funcționează de fapt scriptul.

  1. Se setează niște variabile care verifica timpul în Unix Time (timpul actual și cel de expirare al certificatului)
  2. Dacă timpul de acum e mai mare decât timpul de expirare al certificatului, atunci “fa chestii”
  3. ???
  4. Profit.

Încă o chestie, scriptul trebuie pus în cron, sa ruleze din minut în minut.

Q&A:
Se putea face altfel scriptul sau se putea scrie mai frumos? Probabil ca da.
Merge? Merge.
Are sens să-mi bat capul să-l modific? Nope. Dacă merge, atunci care e problema?

Referințe:

1. https://gist.github.com/catchdave/69854624a21ac75194706ec20ca61327
2. https://markvanlent.dev/2020/10/02/replacing-the-tls-certificate-on-a-synology-nas-via-the-command-line/
3. https://dokuwiki.bitaranto.ch/doku.php?id=synologyimportcertfrompfsense