Proxy - certificate renewal on dc2-a-vcprx001
Proxy Solution · Config document · referenced from Certificate renewal
<COUNTRY>, Datacenter 2, Example Ltd) are placeholders for this write-up, not what was typed. rm -rf /var/lib/ssl_db deletes the whole certificate cache on purpose; run it only with Squid stopped and only when the cache is to be rebuilt.The command set that renewed the self-signed certificate of the datacenter 2 proxy dc2-a-vcprx001.adm.example.net, from a note filed under 2018 (the note itself carries no date; the step title "Create new CSR (if certificate is expired)" reads as the procedure for this host, and the certificate it checks ran out in April 2019): find which certificate and key the ssl-bump ports use, check when the certificate expires, make a new signing request from the existing key, self-sign it for another 365 days, then stop Squid, delete and re-create the ssl_crtd certificate cache, and start Squid again. The same note goes on with the SELinux problem of ssl_crtd, which is SELinux and client trust and its module squid-local.te.
| Item | Value |
|---|---|
| Host | dc2-a-vcprx001.adm.example.net, RHEL 7.5, Squid 3.5 (the RHEL 7.5 package, squid-3.5.20-12.el7; the notes print no version) |
| Run as | root; the notes do not record the working directory, every path is absolute |
| Private key | /etc/ssl/squid/dc2-a-vcprx001_2.key, kept, not regenerated |
| CSR | /etc/ssl/squid/dc2-a-vcprx001_2.csr |
| Certificate | /etc/ssl/squid/dc2-a-vcprx001_2.crt, overwritten in place, self-signed, 365 days |
| Certificate valid until | Apr 27 13:13:55 2019 GMT at the time of the check |
| Certificate cache | /var/lib/ssl_db, deleted and re-created with ssl_crtd -c -s, files owned by squid:squid |
| Service | squid, stopped before the cache is deleted, started after it is re-created |
| Handed over | the new ….crt to the colleague who runs the certificate deployment |
The commands
Check which certificate and private key the SSL interception uses. As root on dc2-a-vcprx001. The grep prints two lines, an http_port and an https_port … intercept, both on port 3128 and both without a comment sign; the notes hold nothing else of the production squid.conf. The two lines, and the question of how Squid ran with both, are in Squid port lines on dc2-a-vcprx001.
$ cat /etc/squid/squid.conf | grep ssl-bump
output 2 lines
http_port 3128 ssl-bump cert=/etc/ssl/squid/dc2-a-vcprx001_2.crt key=/etc/ssl/squid/dc2-a-vcprx001_2.key generate-host-certificates=on version=1 options=NO_SSLv2,NO_SSLv3,SINGLE_DH_USE https_port 3128 cert=/etc/ssl/squid/dc2-a-vcprx001_2.crt key=/etc/ssl/squid/dc2-a-vcprx001_2.key ssl-bump intercept generate-host-certificates=on version=1 options=NO_SSLv2,NO_SSLv3,SINGLE_DH_USE
Check when the certificate expires. Same host, as root.
$ openssl x509 -in /etc/ssl/squid/dc2-a-vcprx001_2.crt -text -noout | grep "Not After"
output 1 line
Not After : Apr 27 13:13:55 2019 GMT
Create the new certificate signing request from the existing private key. The notes title the step "Create new CSR (if certificate is expired)". openssl req asks for the distinguished name; the dialogue is in the output block (the notes do not keep the preamble that openssl req prints before the first question). The state, organisational unit, email address, challenge password and optional company name were left empty.
$ openssl req -new -key /etc/ssl/squid/dc2-a-vcprx001_2.key -out /etc/ssl/squid/dc2-a-vcprx001_2.csroutput 12 lines
Country Name (2 letter code) [XX]:<COUNTRY> State or Province Name (full name) []: Locality Name (eg, city) [Default City]:Datacenter 2 Organization Name (eg, company) [Default Company Ltd]:Example Ltd Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:dc2-a-vcprx001.adm.example.net Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Sign the request with the same key: a self-signed certificate for 365 days, written over the old ….crt. My NOTE above this step in the notes: the file /etc/ssl/squid/dc2-a-vcprx001_2.crt needs to be sent to the colleague who runs the certificate deployment (automatic deployment of certificates to servers).
$ openssl x509 -req -days 365 -in /etc/ssl/squid/dc2-a-vcprx001_2.csr -signkey /etc/ssl/squid/dc2-a-vcprx001_2.key -out /etc/ssl/squid/dc2-a-vcprx001_2.crt
Stop Squid and remove its SSL certificate cache. Same host, as root.
$ systemctl stop squid $ rm -rf /var/lib/ssl_db
Generate the certificate cache again and give its files to the squid user, then start Squid. The chown glob changes the owner of what is inside the directory, not of /var/lib/ssl_db itself (my reading; the notes do not remark on it).
$ /usr/lib64/squid/ssl_crtd -c -s /var/lib/ssl_db $ chown -R squid:squid /var/lib/ssl_db/* $ systemctl start squid
What the lines mean
| Line | Meaning |
|---|---|
grep ssl-bump | finds the listening ports that intercept TLS; the cert= and key= options name the files to renew |
version=1 and options=NO_SSLv2,NO_SSLv3,SINGLE_DH_USE | options of the production ports that the lab did not have; the notes do not say why they were set, see Squid with SSL interception |
openssl x509 -text -noout with grep "Not After" | prints the end of the validity period only |
openssl req -new -key … -out ….csr | a new request from the existing key; the key pair does not change, only the certificate |
openssl x509 -req -days 365 -signkey … | self-signs the request for a year; no extensions file, so the new certificate is, as I understand openssl x509, an X.509 version 1 certificate like the lab's |
rm -rf /var/lib/ssl_db and ssl_crtd -c -s /var/lib/ssl_db | throw away the host certificates generated under the old certificate and start an empty database; why, is discussed in Certificate renewal |
chown -R squid:squid /var/lib/ssl_db/* | the ssl_crtd helper runs as squid and writes into the database |
The file names of this host put the suffix before the extension and drop the domain (dc2-a-vcprx001_2.crt, .key, .csr); datacenter 1 uses dc1-a-vcprx001.adm.example.net.crt_1, .private_1 and .csr_1, see certificate renewal on dc1-a-vcprx001. The notes do not say where the difference comes from. The datacenter 1 dialogue also fills the email address with security@example.net; this one leaves it empty.
Checked against OpenSSL 3.5 and Squid 7.7
| As built | Today |
|---|---|
openssl req -new -key … then openssl x509 -req -days 365 -signkey … | Still works; -signkey is an alias of -key since OpenSSL 3.0, -days still defaults to 30, and since OpenSSL 3.2 x509 emits version 3 certificates with key identifiers. Without -extfile or -extensions the result still has no basicConstraints, so it is not a CA certificate |
| The renewed certificate as Squid's signing certificate | Squid 7.7 requires that with generate-host-certificates=on "the first tls-cert= option must be a CA certificate capable of signing the automatically generated certificates"; the Squid wiki's one-step openssl req … -x509 -extensions v3_ca recipe produces one |
| 365-day validity | Squid's generate-host-certificates documentation: "If there is a CA certificate lifetime of the generated certificate equals lifetime of the CA certificate", so the host certificates the proxy hands out are as short-lived as the signing certificate |
rm -rf /var/lib/ssl_db, re-create, start | The Squid wiki says the same: "whenever you change the signing CA be sure to erase and re-initialize the certificate database. It contains signed certificates and clients may experience connectivity problems when the signing CA no longer matches your configured CA" |
/usr/lib64/squid/ssl_crtd -c -s /var/lib/ssl_db | Renamed in Squid 4 to security_file_certgen (/usr/lib64/squid/security_file_certgen on RHEL 9 and 10); the compiled-in default database is now /var/spool/squid/ssl_db on RHEL builds; -s requires -M, so the re-creation is security_file_certgen -c -s DIR -M 4MB |
chown -R squid:squid /var/lib/ssl_db/* | The wiki says to make "the directory writable for the squid user"; the glob leaves the directory itself to root |
cert=, key=, version=1, options=NO_SSLv2,NO_SSLv3,SINGLE_DH_USE on the port lines | cert=/key= are now tls-cert=/tls-key= (the old spellings are still accepted); version= was removed in Squid 4 and 7.7 only warns "SSL version= is deprecated. Use options= and tls-min-version= to limit protocols instead"; NO_SSLv2 is an "Unknown TLS option" error, SSLv2 being force-disabled; NO_SSLv3 and SINGLE_DH_USE are unchanged |
| Squid 3.5.20 on RHEL 7.5 | Squid 3.5 ended with 3.5.27 in August 2018 and only 7.x is supported; RHEL 7 left Maintenance Support on 2024-06-30 |
The sequence itself is confirmed by the wiki, including the step that the notes do not explain, the erased database. What has changed is the certificate it renews: a current Squid wants a real CA certificate, which this two-step recipe does not make, and the helper that fills the database has another name, another default path and a mandatory -M.