Self-signed SSL certificate generation
Server setup | |
← Previous | Next → |
NTP | MDA (Dovecot) |
Eclectica has a good guide to setting up SSL certificates. Basically, I followed the instructions given there, except that I didn't rebuild the /etc/ssl/openssl.cnf file, as described at Eclectica.
Initial configuration
- Install OpenSSL, installed as part of the SSH server package:
root@server:~# apt-get install openssh-server
- I did all the creation work in
/etc/ssl/domain
, so create the directory structure:
root@server:~# cd /etc/ssl root@server:/etc/ssl# mkdir -p domain/private domain/certs domain/newcerts
- Create a couple of files for the database of keys
root@server:~# echo '01' > domain/serial root@server:~# touch domain/index.txt
- Create a list of key revocations
root@server:~# echo '01' > domain/crlnumber
- Create the
/etc/ssl/openssl.cnf
file as shown below.
Create the root certifiate
root@server:/etc/ssl# openssl req -new -x509 -extensions v3_ca \ -keyout domain/private/cakey.pem -out domain/cacert.pem \ -days 3650 -config ./openssl.cnf Using configuration from ./openssl.cnf Generating a 1024 bit RSA private key .......++++++ ..........................++++++ writing new private key to 'domain/private/cakey.pem' Enter PEM pass phrase:demo Verifying password - Enter PEM pass phrase:demo ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Organization Name (company) [The Sample Company]:<enter> Organizational Unit Name (department, division) []:CA Division Email Address []:ca@sample.com Locality Name (city, district) [Your Town]:<enter> State or Province Name (full name) [Your State]:<enter> Country Name (2 letter code) [UK]:<enter> Common Name (hostname, IP, or your name) []:My Root CA
- Carefully note the passphrase used to generate this root CA. This generates a private key in domain/private/cakey.pem and a root CA certificate in domain/cacert.pem . It is the latter that can be distributed.
Create a certificate signing request
Now to create a certificate signing request for all of the systems that need them. For the server, that's the MTA, the IMAP server, and the Squirrelmail web mail server.
root@server:/etc/ssl# openssl req -new -nodes \ -out domain/squirrelmail-req.pem \ -keyout domain/private/squirrelmail-key.pem -config ./openssl.cnf ... Organizational Unit Name (department, division) []:Webmail Server Email Address []:postmaster@sample.com Common Name (hostname, IP, or your name) []:squirrelmail.domain.tld ...
Change the name squirrelmail-req.pem for the purpose needed. Make sure that the common name given is the fully-qualified domain name of the machine that will use the certificate.
Each CSR will create a pair of files: a private key squirrelmail-key.pem and a signing request squirrelmail-req.pem
Sign the request
root@server:/etc/ssl# openssl ca -out domain/certs/squirrelmail-cert.pem \ -config ./openssl.cnf -infiles domain/squirrelmail-req.pem Using configuration from ./openssl.cnf Enter PEM pass phrase:demo Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows organizationName :PRINTABLE:'The Sample Company' organizationalUnitName:PRINTABLE:'Webmail Server' emailAddress :IA5STRING:'postmaster@sample.com' localityName :PRINTABLE:'Your Town' stateOrProvinceName :PRINTABLE:'Your State' countryName :PRINTABLE:'UK' commonName :PRINTABLE:'squirrelmail.domain.tld' Certificate is to be certified until Dec 8 04:37:38 2002 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
This creates the signed certificate in squrrelmail-cert.pem and a copy in newcerts/<serial>.pem.
Installing certificates
This is detailed in the information for the particular applications. One wrinkle is that the certificate for Apache needs to be modified so that Apache doesn't request the passphrase every time it starts.
root@server:/etc/ssl# openssl rsa -in domain/private/squirrelmail-key.pem \ -out domain/private/squirrelmail-key.insecure.pem
Full details on setting up Apache are in the Web server setup notes. Read more on generating SSL keys for Apache and more notes for Apache + SSL.
Revoking a certificate
When certificates expire or become compromised, they can be revoked.
- Revoke a certificate with the command:
root@server:/etc/ssl# openssl ca -revoke domain/certs/squirrelmail-cert.pem
- Once you've done all the revocations you need to, generate the certificate revocation list (CRL):
root@server:/etc/ssl# openssl ca -gencrl -out domain/root.crl
- You can check the contents of the revocation list with:
root@server:/etc/ssl# openssl ca -gencrl -out domain/root.crl
- Copy the new CRL to the correct directory on the wweb server:
root@server:/etc/ssl# cp domain/root.crl /var/www/domain.tld/root.crl
You can then generate new certificates to replace the revoked ones.
Viewing the contents of a certificate
root@server:/etc/ssl# openssl x509 -in domain/certs/squirrelmail-cert.pem -text
Contents of /etc/ssl/openssl.cnf
Note the change to the dir entry in the [ CA_default ] section.
# # OpenSSL example configuration file. # This is mostly being used for generation of certificate requests. # HOME = . RANDFILE = $ENV::HOME/.rnd oid_section = new_oids #################################################################### [ ca ] default_ca = CA_default # The default ca section #################################################################### [ CA_default ] dir = ./domain # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificate serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number # must be commented out to leave a V1 CRL crl = $dir/root.crl # The current CRL private_key = $dir/private/cakey.pem# The private key RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options crl_extensions = crl_ext default_days = 3650 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering policy = policy_match # For the CA policy [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional # For the 'anything' policy [ policy_anything ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional #################################################################### [ req ] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # The extentions to add to the self signed cert string_mask = nombstr req_extensions = v3_req # The extensions to add to a certificate request [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = UK countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Your State localityName = Locality Name (eg, city) localityName_default = Your Town 0.organizationName = Organization Name (eg, company) 0.organizationName_default = Your Org Name organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, YOUR name) commonName_default = Domain commonName_max = 64 emailAddress = Email Address emailAddress_default = webmaster@domain.tld emailAddress_max = 64 [ req_attributes ] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 unstructuredName = An optional company name [ usr_cert ] # These extensions are added when 'ca' signs a request. basicConstraints=CA:FALSE nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer keyUsage = digitalSignature,keyEncipherment extendedKeyUsage = serverAuth crlDistributionPoints = URI:http://domain.tld/root.crl subjectAltName = @alt_names [alt_names] DNS.1 = domain.tld DNS.2 = *.domain.tld [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ v3_ca ] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always basicConstraints = CA:true [ crl_ext ] authorityKeyIdentifier=keyid:always,issuer:always [ proxy_cert_ext ] basicConstraints=CA:FALSE nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer:always proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo