HOWTO setup a small server

OpenSSL (Keys and Certificates)

Installation

Install OpenSSL by running:

apt-get install openssl ssl-cert

OpenSSL Helper Tools

You can use one of the numerous scripts and tools for easier key and certificate management (e.g., easy-rsa which is shipped with OpenVPN). To make your decision even a bit harder, I also wrote such a tool (ssl-util.sh). More details are given by the tools.

If you do not want to use such a helper, the next two section will give an introduction on how to do key and certificate management manually.

Configuration

Configure OpenSSL using the following example which seems to work with most applications:

File: /etc/ssl/openssl.cnf

#
# OpenSSL configuration based on sample configuration shipped
# with OpenVPN.
#

#############################################################
# modify according to your needs

KEY_SIZE               = 2048
KEY_COUNTRY            = DE
KEY_PROVINCE           = NO
KEY_CITY               = NOWHERE
KEY_ORG                = EXAMPLE.COM
KEY_ORGUNIT            = IT-DIVISION
KEY_EMAIL              = root@server.example.com
HOME                   = /root
KEY_DIR                = $ENV::HOME/certs
RANDFILE               = $ENV::HOME/.rnd

#############################################################

openssl_conf           = openssl_init

[ openssl_init ]

oid_section            = new_oids
engines                = engine_section

[ new_oids ]

[ engine_section ]

[ ca ]

default_ca             = CA_default

[ CA_default ]

dir                    = $ENV::KEY_DIR
certs                  = $dir
crl_dir                = $dir
database               = $dir/index.txt
new_certs_dir          = $dir
certificate            = $dir/ca.crt
serial                 = $dir/serial
crl                    = $dir/crl.pem
private_key            = $dir/ca.key
RANDFILE               = $dir/.rand
x509_extensions        = usr_cert
default_days           = 3650
default_crl_days       = 30
# IMPORTANT: The next must no longer be md5, if used with
# Debian's OpenLDAP package being compiled against libgnutls.
default_md             = sha1
preserve               = no
policy                 = policy_match

[ policy_match ]

countryName            = match
stateOrProvinceName    = match
organizationName       = match
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ policy_anything ]

countryName            = optional
stateOrProvinceName    = optional
localityName           = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ req ]

default_bits           = $ENV::KEY_SIZE
default_keyfile        = privkey.pem
distinguished_name     = req_distinguished_name
attributes             = req_attributes
x509_extensions        = v3_ca
string_mask            = nombstr

[ req_distinguished_name ]

countryName            = Country Name (2 letter code)
countryName_default    = $ENV::KEY_COUNTRY
countryName_min        = 2
countryName_max        = 2

stateOrProvinceName    = State or Province Name (full name)
stateOrProvinceName_default = $ENV::KEY_PROVINCE

localityName           = Locality Name (eg, city)
localityName_default   = $ENV::KEY_CITY

0.organizationName     = Organization Name (eg, company)
0.organizationName_default = $ENV::KEY_ORG

organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = $ENV::KEY_ORGUNIT

commonName             = Common Name (eg, your name or your server\'s hostname)
commonName_max         = 64

emailAddress           = Email Address
emailAddress_default   = $ENV::KEY_EMAIL
emailAddress_max       = 40

[ req_attributes ]

challengePassword      = A challenge password
challengePassword_min  = 4
challengePassword_max  = 20
unstructuredName       = An optional company name

[ usr_cert ]

basicConstraints       = CA:FALSE
nsComment              = "OpenSSL Generated Certificate"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer:always
extendedKeyUsage       = clientAuth
keyUsage               = digitalSignature

[ server ]

basicConstraints       = CA:FALSE
nsCertType             = server
nsComment              = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer:always
extendedKeyUsage       = serverAuth
keyUsage               = digitalSignature, keyEncipherment

[ 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

Now you will have to initialize the directory specified as KEY_DIR in the above configuration file:

# mkdir -m 700 /root/certs
# touch /root/certs/index.txt
# echo "01" > /root/certs/serial

Generation of Keys and Certificates

In order to create the certificate authority (CA), run the following command. The question for the common name (CN) might, e.g., be answered with CA. It might be a good idea to omit the -nodes parameter and thus encrypting the CA key.

# cd /root/certs
# openssl req -nodes -new -x509 -keyout ca.key -out ca.crt

In order to create server key and certificate, run the following commands. The question for the common name (CN) should be answered with the FQDN of the server, so server.example.com in our example.

# cd /root/certs
# openssl req -nodes -new -extensions server \
  -keyout server.key -out server.csr
# openssl ca -extensions server \
  -out server.crt -in server.csr

In order to create a client key and certificate, run the following commands. As the option -nodes has been omitted, the key will be encrypted by the supplied password and because of -days 365 the certificate is only valid for one year. Concerning the question for the CN the same as for a server certificate applies.

# cd /root/certs
# openssl req -days 365 -new \
  -keyout client.key -out client.csr
# openssl ca -days 365 \
  -out client.crt -in client.csr

In order to revoke a certificate (the last command should fail, if revoking was successful):

# cd /root/certs
# openssl ca -revoke certificate.crt
# openssl ca -gencrl -out crl.pem
# cat ca.crt crl.pem > revoke-test.pem
# openssl verify -CAfile revoke-test.pem -crl_check certificate.crt

WARNING: Do not forget to distribute the new certificate revokation list (CRL) crl.pem to any application and/or host using the public key infrastructure!

Note: OpenSSL is also able to print certificate details at a later time. This is particularly useful when debugging connection problems.

# openssl x509 -in certificate.crt -noout -text

Installation of Keys and Certificates

Finally, you will have to install the CA certificate and the server's key and certificate:

# cd /root/certs
# cp ca.crt server.crt /etc/ssl/certs
# cp server.key /etc/ssl/private
# chown root:ssl-cert /etc/ssl/private/server.key
# chmod 640 /etc/ssl/private/server.key

Back to index.