Automatic SSL Certificates - One Certificate Per Host (SKINS)

Version 1.62.0

Feature
Finished

BETA New feature which will automatically attempt to install and manage certificates for newly created domains, subdomains, and domain pointers. This will make use of the "one certificate per VirtualHost" concept, allowing for cleaner additions/removals (eg: subdomains), without the need for a new request on the main domain or other certificates. A new domain will attempt a wildcard cert, meaning subdomains created later do no need a certificate. However, if dns is external, it the domain would fall back to domain.com,www.domain.com, meaning a new sub.domain.com would retrieve it's own certificate as well (attempting dns first, falling back to http letsencrypt requests)) Writes to httpd.conf files will use the snidomains file to determine which certificate to use, assuming a cert has not already been explicitly set by the User. (The snidomains lookup only applies if the domain is using "Shared Server Certificate", and the domain is not literally in the shared server cert) Dovecot sni configs will also contain wildcards, instead of the full list of smtp, mail, pop, etc, if a wildcard cert is availble. Pointers would also get their own dovecot sni config file in a similar manner. The general change (when "Shared Server Cert" is selected) is that certificates are no longer linked to a domain. They're on a per-host basis, allowing any area that needs them to use them. This system also allowed for cross-User certificates, assuming there's a match (eg: *.domain.com owned by fred, but bob has domain sub.domain.com, no need for a new cert). However, the cross-User cert setting is only available in the DirectAdmin Pro Pack. =================== REQUIREMENTS 1) LetsEncrypt is installed and enabled: letsencrypt=1 If not, enable/install LE with this guide: https://help.directadmin.com/item.php?id=648 2) Domain pointers should be on their own VirtualHost: pointers_own_virtualhost=1 3) One SSL certificate per VirtualHost should be enabled: admin_ssl_cert_per_vh=1 4) The background retry check must be enabled: admin_ssl_check_retries=1 5) The /etc/virtual/snidomains must be in use: mail_sni=1 ------------------- ENABLE 6) In order for a domain (and all child hosts) is able to use the feature, it must be set to "Shared Server Certificate" on the "SSL Certificates" page. it must not be set to have a pasted cert, as this will be a fully separate system than the existing certificate requests. You can check any of the above settings with the ./directadmin c command, eg: ./directadmin c | grep mail_sni Most should already be enabled by default, but some on older boxes might not have them enabled, eg: ./directadmin set mail_sni 1 ./directadmin set pointers_own_virtualhost 1 ./directadmin set admin_ssl_cert_per_vh 1 ./directadmin set admin_ssl_check_retries 1 service directadmin restart ------------------- DISABLE Once enabled, the simplest way to disable the feature is to disable the background polling: ./directadmin set admin_ssl_check_retries 0 service directadmin restart =================== USAGE Assuming all of the above are enabled, and the current domain has ssl enabled, any new domain, subdomain, or pointer will create a retry file, which the background dataskq will find and execute. The system REQUIRES that a domain's certificate is using the "Shared Server Certificate". =================== FILES ------------------ /etc/virtual/snidomains The /etc/virtual/snidomains file is the core index for this new system; all areas branch from the values in this file, thus it must be correct. If you need to fully rebuild the file, see the task.queue call below, keeping in mind that it's a slightly different format using wildcards, vs before which listed each specific mail host explicitly. (eg: "mail.domain.com:fred:domain.com") The format is: host:user:domain.com Where "host" can be any host, like mail.domain.com, or *.domain.com, domain.com, etc... which is the lookup that all services use (exim, directadmin:(2222, apache+dovecot configs)) The user (eg: fred) refers to /usr/local/directadmin/data/users/fred and the last domain/host value is the value in that User's domain directory, eg: /usr/local/directadmin/data/users/fred/domains/domain.com.cert For example, this snidomains entry: *.sub.domain.com:fred:sub.domain.com would mean, that for the given service, if "www.sub.domain.com" is requested, the lookup would point to: /usr/local/directadmin/data/users/fred/domains/sub.domain.com.cert (or sub.domain.com.cert.combined, depending on which service is asking) ------------------ /usr/local/directadmin/data/users/fred/domains/domain.com.ssl This is the request file. It's essentially similar to a POST request, used back the dataskq to decide how the certificate should be created. This file is deleted after a request is successful. ------------------ /usr/local/directadmin/data/users/fred/domains/domain.com.ssl.next_retry This lets the dataskq know when it's allowed to try the domain.com.ssl request next. The frequency decreases over time, based on the directadmin.conf option: admin_ssl_poll_frequency=5m:15m:30m:1h:12h:1d:1w See the "Admin SSL" feature for more information on how admin_ssl_poll_frequency works: https://www.directadmin.com/features.php?id=2422 This lets a value retrieve a certificate as fast as possible, but also allowed for longer periods if the DNS is still being changed to the server.. while keeping the number of requests to a minimum. This file is deleted after a request is successful. ------------------ /usr/local/directadmin/data/users/fred/domains/domain.com.cert /usr/local/directadmin/data/users/fred/domains/domain.com.key /usr/local/directadmin/data/users/fred/domains/domain.com.cacert /usr/local/directadmin/data/users/fred/domains/domain.com.combined The actual certificate to be used by services: apache, exim, dovecot, directadmin, pure-ftpd. for secured SSL connections, using SNI. =================== JSON Most of the work and changes is all controlled silently by the back-end. However, there might be cases where a User needs to intervene: - Trigger a request for an already-existing domain/subdomain/pointer - Cancel the future retry attempts for a given host. - force a retry "now" instead of waiting for the next retry attempt ---- INFO / TABLES Relating to the skin tables below, they can be assembled, with even more detail, using the json output from: CMD_SSL?domain=domain.com&json=yes 1) where new json values are included: CAN_AUTO_SSL_CERT=1 : Set if this feature is even available for use. (We'll rely on SERVERCHECKED="checked" being set to offer the information to clients) "certificates" array, listing all host cert (domain, subdomain, pointer, sub-pointer, or other host, eg: mail.domain.com, if present) "certificates": { "/usr/local/directadmin/data/users/ssltest/domains/ssltest.com.cert": { "SSLCertificateFile": "/usr/local/directadmin/data/users/ssltest/domains/ssltest.com.cert", "cert_file_host": "ssltest.com", "certificate_domains" : [ ], "certificate_info": { "Issuer": "C = CA, ST = AB, L = St. Albert, O = Moop, OU = Perp, CN = ssltest.com, emailAddress = no@thanks.com", "Not After": "Mar 9 01:36:24 2022 GMT", "Not Before": "Mar 9 01:36:24 2021 GMT", "Subject": "C = CA, ST = AB, L = St. Albert, O = Moop, OU = Perp, CN = ssltest.com, emailAddress = no@thanks.com", "end": "1646814984", "signed": "self-signed", "start": "1615278984" }, "valid": "no", "warnings": "Could not find 'X509v3 Subject Alternative Name:' in output<br>\n" }, "/usr/local/directadmin/data/users/ssltest/domains/directadmin.com.cert": { "SSLCertificateFile": "/usr/local/directadmin/data/users/ssltest/domains/directadmin.com.cert", "cert_file_host": "directadmin.com", "certificate_domains" : [ "*.directadmin.com", "directadmin.com" ], "certificate_info": { "Issuer": "C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA", "Not After": "Jun 15 23:59:59 2022 GMT", "Not Before": "Mar 17 00:00:00 2020 GMT", "Subject": "CN = *.directadmin.com", "end": "1655359199", "issuer_simple": "sectigo", "signed": "yes", "start": "1584424800" }, "valid": "no" } }, If the certificate is signed, you'll see the "signed = yes" in the certificate_info. Only signed certificates make the "certificate_domains" list visible. Use the "cert_file_host" name for the actual cert filename where the info is from. The "start" and "end" timestamps will be the range for which the certificate is valid. The "issuer_simple" will be a "best attempt" for DirectAdmin to set a unified issuer name, which currently include: letsencrypt comodo letsencrypt cpanel sectigo other (for unknown cases) ---- 2) "next_retries", list of "next_retries": { "domain.com": { "action": "save", "admin_ssl": "yes", "background": "no", "domain": "domain.com", "encryption": "sha256", "keysize": "4096", "le_wc_select0": "*.domain.com", "le_wc_select1": "domain.com", "name": "domain.com", "next_retry": "1615860053", "request": "letsencrypt", "start": "1615860053", "submit": "Save", "type": "create", "wildcard": "yes" } }, Which lists all "next_retry" files for this User. The main thing to note will be the "next_retry" time: when the dataskq will next take notice. And the "wildcard=yes" value, if it's referencing "le_wc_select#" (for wildcard) or "le_select" for httpd-based LetsEncrypt requests. The listed variables are essentially what would be "POST"ed to DA normally for a normal LE request, but without affecting the certificate selection area. ---- 3) SNIDOMAINS All values for this Username taken from /etc/virtual/snidomains The "snidomains" array has sub-indexes for the host being used. This data will be purely informative, letting the User know which host points to which certificate file. The array index here (ssltest.com) will be the host being requested, while the "cert" value is the certificate host filename. "snidomains": { "ssltest.com": { "cert": "ssltest.com", "user": "ssltest" } } ---- CERTIFICATES REQUEST NEW CERT Issue a retry on an existing cert (perhaps it is expired or some other issuer) CMD_SSL method: POST action=certificate domain=domain.com select0=domain.com (host certificate file must already exist) retry=<anytext> DELETE any existing host certificate file: CMD_SSL method: POST action=certificate domain=domain.com select0=domain.com (host certificate file must already exist) delete=<anytext> ---- RETRIES List of the current "next_retries" to force to run "now" // end JSON section =================== SKINS Enhanced style skins: /usr/local/directadmin/data/skins/enhanced/user/ssl.html ----- 3 new tables within condition: |*if SERVERCHECKED="checked"| <b>|LANG_AUTO_SSL_CERT_INFO|</b> |AUTO_SSL_CERT_TABLE| |AUTO_SSL_RETRY_TABLE| |AUTO_SSL_SNI_TABLE| |*endif| ----- There is also a new form to force-trigger a retry on the current domain. CMD_SSL method: POST action=retries domain=domain.com select0=domain.com (this can be set to any domain/subdomain/pointer/sub-pointer/mail.domain.com type valid host for this User) retry_now=<any text> Optional: wildcard=yes subdomains=yes pointers=yes Absence will set wildcard=yes, subdomains=no, pointers=no. The above 3 optional values only apply to selectX values which are domains. By default, it's a wildcards, and background dns failure falls-back to http-01 letsencrypt requests for all subdomains automatically. =================== TASK.QUEUE There are several related commands to help get things synced, if they're ever out of sync or you wish to clean anything up. --------- /etc/virtual/snidomains echo "action=rewrite&value=snidomains" >> /usr/local/directadmin/data/task.queue; /usr/local/directadmin/dataskq Which holds the list of all valid certs, who owns them, and all hosts inside. It's used to redirect a requested SSL host to the cert that it lives in. The apache httpd.conf files need this file to be correct for the automatic SSL system to use the best value (domain must use "shared server" or "best match" option in SSL Management page to hunt in this file during the write) --------- dovecot sni configs You can rewrite the /etc/dovecot/conf/sni/* files (old are removed first) with: echo "action=rewrite&value=mail_sni" >> /usr/local/directadmin/data/task.queue; /usr/local/directadmin/dataskq -------- Force an "Ssl::admin_poll" This will hunt for all domain.com.next_retry files and process them if the window is correct. echo "action=ssl&value=admin_ssl" >> /usr/local/directadmin/data/task.queue; /usr/local/directadmin/dataskq -------- User httpd.conf files If needed, the User httpd.conf files can be rewritten, using the new snidomains lookup system: cd /usr/local/directadmin/custombuild ./build update ./build rewrite_confs This has a task.queue called within the build script, but the full rewrite is recommended for simplicity. ==== EVO2081

Interested to try DirectAdmin? Get a 30-day Free Trial!