This cheat sheet helps to set up web server with TLS authentication. We'll use our own certificate authority.
As a prerequisite You have to own the server and the domain, pointed to this server.
Prepare easy-rsa
We need to create several cipher keys. OpenSSL can do it for us, but it's not the
easiest tool. Much simpler way is to use easy-rsa
. It
comes with openvpn in Debian-8. Make a local copy and apply some changes:
cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/.keys-infrastructure
edit vars:
+++ /usr/share/doc/openvpn/examples/easy-rsa/2.0/vars 2011-07-01 12:31:26.000000000 +0400
@@ -26,8 +26,7 @@
# This variable should point to
# the openssl.cnf file included
# with easy-rsa.
-#export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
-export KEY_CONFIG=$EASY_RSA/openssl-1.0.0.cnf
+export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
# Edit this variable to point to
# your soon-to-be-created key
@@ -51,13 +50,13 @@
# down TLS negotiation performance
# as well as the one-time DH parms
# generation process.
-export KEY_SIZE=4096
+export KEY_SIZE=1024
# In how many days should the root CA key expire?
export CA_EXPIRE=3650
# In how many days should certificates expire?
-export KEY_EXPIRE=365
+export KEY_EXPIRE=3650
# These are the default values for fields
# which will be placed in the certificate.
@@ -65,11 +64,11 @@
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
-export KEY_ORG="ACME"
-export KEY_EMAIL="info@example.com"
-export KEY_ALTNAME="example.com"
+export KEY_ORG="Fort-Funston"
+export KEY_EMAIL="me@myhost.mydomain"
+export KEY_EMAIL=mail@host.domain
export KEY_CN=changeme
export KEY_NAME=changeme
-export KEY_OU=IT Department
+export KEY_OU=changeme
export PKCS11_MODULE_PATH=changeme
-export PKCS11_PIN=7266
+export PKCS11_PIN=1234
edit openssl-1.0.0.cnf
--- openssl-1.0.0.cnf 2016-10-11 09:56:47.895473062 +0300
+++ /usr/share/doc/openvpn/examples/easy-rsa/2.0/openssl-1.0.0.cnf 2011-07-01 12:31:26.000000000 +0400
@@ -182,7 +182,7 @@
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
-nsComment = "ACME certfication"
+nsComment = "Easy-RSA Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
@@ -193,10 +193,10 @@
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
-subjectAltName = "DNS.1:example.com,DNS.2:*.example.com"
+# subjectAltName=email:copy
# Copy subject details
-issuerAltName=issuer:copy
+# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
@@ -210,8 +210,7 @@
# JY ADDED -- Make a cert with nsCertType set to "server"
basicConstraints=CA:FALSE
nsCertType = server
-nsComment = "ACME certification"
-subjectAltName="DNS.1:example.com,DNS.2:*.example.com"
+nsComment = "Easy-RSA Generated Server Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
extendedKeyUsage=serverAuth
@@ -251,9 +250,9 @@
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
-subjectAltName="DNS.1:example.com,DNS.2:*.example.com"
+# subjectAltName=email:copy
# Copy issuer details
-issuerAltName=issuer:copy
+# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
pkitool:
+++ /usr/share/doc/openvpn/examples/easy-rsa/2.0/pkitool 2011-04-27 13:52:59.000000000 +0400
@@ -322,7 +322,7 @@
# Build root CA
if [ $DO_ROOT -eq 1 ]; then
- $OPENSSL req $BATCH -days $CA_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE -sha256 \
+ $OPENSSL req $BATCH -days $CA_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE -sha1 \
-x509 -keyout "$CA.key" -out "$CA.crt" -config "$KEY_CONFIG" && \
chmod 0600 "$CA.key"
else
@@ -347,7 +347,7 @@
echo "Generating key pair on PKCS#11 token..."
$PKCS11TOOL --module "$PKCS11_MODULE_PATH" --keypairgen \
--login --pin "$PKCS11_PIN" \
- --key-type rsa:4096 \
+ --key-type rsa:1024 \
--slot "$PKCS11_SLOT" --id "$PKCS11_ID" --label "$PKCS11_LABEL" || exit 1
PKCS11_ARGS="-engine pkcs11 -keyform engine -key $PKCS11_SLOT:$PKCS11_ID"
fi
@@ -356,7 +356,7 @@
( [ $DO_REQ -eq 0 ] || $OPENSSL req $BATCH -days $KEY_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE \
-keyout "$FN.key" -out "$FN.csr" $REQ_EXT -config "$KEY_CONFIG" $PKCS11_ARGS ) && \
( [ $DO_CA -eq 0 ] || $OPENSSL ca $BATCH -days $KEY_EXPIRE -out "$FN.crt" \
- -in "$FN.csr" $CA_EXT -md sha256 -config "$KEY_CONFIG" ) && \
+ -in "$FN.csr" $CA_EXT -md sha1 -config "$KEY_CONFIG" ) && \
( [ $DO_P12 -eq 0 ] || $OPENSSL pkcs12 -export -inkey "$FN.key" \
-in "$FN.crt" -certfile "$CA.crt" -out "$FN.p12" $NODES_P12 ) && \
( [ $DO_CA -eq 0 -o $DO_P11 -eq 1 ] || chmod 0600 "$FN.key" ) && \
Creating key infrastructure
First thing to do is to build certificate authority. It can sign other certificates and validate them.
root@debian:/etc/.keys-infrastructure# ./build-ca
Generating a 4096 bit RSA private key
...................................................................++
....................++
writing new private key to 'ca.key'
-----
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.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [SanFrancisco]:
Organization Name (eg, company) [ACME]:
Organizational Unit Name (eg, section) [IT]:IT Department
Common Name (eg, your name or your server's hostname) [changeme]:exmaple.com
Name [changeme]:ca
Email Address [info@example.com]:
Next we'll build and sign key and certificate for our server.
root@debian:/etc/.keys-infrastructure# ./build-key-server my-nginx
Generating a 4096 bit RSA private key
...........................++
.................
writing new private key to 'my-nginx.key'
-----
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.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [SanFrancisco]:
Organization Name (eg, company) [ACME]:
Organizational Unit Name (eg, section) [IT]:IT Department
Common Name (eg, your name or your server's hostname) [nginx]:example.com
Name [changeme]:nginx
Email Address [info@example.com]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/.keys-infrastructure/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'CA'
localityName :PRINTABLE:'SanFrancisco'
organizationName :PRINTABLE:'ACME'
organizationalUnitName:PRINTABLE:'IT Department'
commonName :PRINTABLE:'exmaple.com'
name :PRINTABLE:'nginx'
emailAddress :IA5STRING:'info@exmaple.com'
Certificate is to be certified until Oct 11 07:00:59 2017 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
Managing clients
When client connects to our server, she must provide signed certificate. To be able to encrypt data, she also must have private key. Let's create it
root@debian:/etc/.keys-infrastructure# ./build-key alice
Generating a 4096 bit RSA private key
....................................
......++
writing new private key to 'alice.key'
-----
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.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [SanFrancisco]:
Organization Name (eg, company) [ACME]:
Organizational Unit Name (eg, section) [IT]:IT Department
Common Name (eg, your name or your server's hostname) [alice]:
Name [changeme]:alice
Email Address [info@example.com]:alice@example.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/.keys-infrastructure/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'CA'
localityName :PRINTABLE:'SanFrancisco'
organizationName :PRINTABLE:'ACME'
organizationalUnitName:PRINTABLE:'IT Department'
commonName :PRINTABLE:'alice'
name :PRINTABLE:'alice'
emailAddress :IA5STRING:'alice@example.com'
Certificate is to be certified until Oct 11 07:02:12 2017 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
Sometimes cilent need p12
certificate with private key in it. You can
get it with the following command:
openssl pkcs12 -export -in alice.crt -inkey alice.key -out alice.p12 -CAfile ca.crt -caname ACME
We would call revoke-full
if we decided to restrict Alice access to
the server. This command will update crl.pem
file, containing revoke
certificates.
root@debian:/etc/.keys-infrastructure# ./revoke-full unwanted
Using configuration from /etc/.keys-infrastructure/openssl-1.0.0.cnf
Revoking Certificate 02.
Data Base Updated
Using configuration from /etc/.keys-infrastructure/openssl-1.0.0.cnf
alice.crt: C = US, ST = CA, L = SanFrancisco, O = ACME, OU = IT Department, CN = alice, name = alice, emailAddress = alice@example.com
error 23 at 0 depth lookup:certificate revoked
Note the "error 23" in the last line. It is normal - it indicates that a certificate verification of the revoked certificate failed.
Setting up nginx server
Nginx server configuration section:
server {
listen 127.0.0.1:443;
server_name localhost;
ssl on;
ssl_certificate /etc/ssl/nginx/nginx.crt;
ssl_certificate_key /etc/ssl/nginx/nginx.key;
ssl_client_certificate /etc/ssl/nginx/ca.crt;
ssl_crl /etc/ssl/nginx/crl.pem;
ssl_verify_client on;
access_log /var/log/nginx/localhost.ssl_access_log main;
error_log /var/log/nginx/localhost.ssl_error_log info;
location / {
root /var/www/localhost/htdocs;
}
}
Client examples
Browser
Alice need to import ca.crt in the Certificate Authorities section and
allow it to identify cites. In Personal section she need to import her
p12
certificate.
Curl
We need to add private key into Alice's certificate. We can just concatenate it:
cp alice.crt alice.pem
cat alice.key >> alice.pem
curl --cacert ca.crt -E alice.pem https://example.com
Python
It's very easy with help of Requests library.
rs = requests.get('https://example.com', verify='/path/to/ca.crt', cert=('/path/to/alice.crt', '/path/to/alice.key')
Comments
comments powered by Disqus