Description: Cherokee is a flexible, very fast, lightweight Web server. It is implemented entirely in C, and has no dependencies beyond a standard C library. It is embeddable and extensible with plug-ins. It supports on-the-fly configuration by reading files or strings, TLS/SSL (via GNUTLS or OpenSSL), virtual hosts, authentication, cache friendly features, PHP, custom error management, and much more.
Keywords: cherokee web server httpd http

## Index → Cookbook

## Cookbook: SSL, TLS and certificates

This section answers some general questions and details the procedure to generate SSL keys.

### General questions

Can the same server provide HTTP and HTTPS?

Yes. HTTP and HTTPS use different server ports. The former binds to port 80 and the latter to port 443, so there is no conflict between them. To provide HTTPS you will need matching certificates.

Keep in mind that to have one of your virtual servers with HTTPS enabled you will need to configure HTTPS settings for all of them.

Which port does HTTPS use?

HTTPS can run on any port, but the standards specify port 443. That’s where any HTTPS compliant browser will look by default. You can change that by specifying another port in the URL. For example, https://example.com:8080/ would look for an HTTPS server on port 8080.

Can one host handle HTTPS requests for multiple virtual servers?

Yes, it can. This is a common question because a web server cannot see the hostname header when the HTTPS request is being processed. The user entered host part of the URI must match the Common Name (CN) provided by the certificate. Since virtual hosts are in use, the CN of the first available certificate may or may not match the one specified in the early stages of TLS negotiation.

Fortunately this can be overcomed by using SNI (Server Name Indication), which places the host information in the SSL handshake. If the web server is accessed through a web browser that supports SNI, things will just work. Every modern web browser does.

For legacy scenarios where using SNI if not possible, there is a workaround detailed in the next question.

Are there workarounds when SNI can’t be used?

Using SNI is the clean and standard way to go. For legacy scenarios where using SNI is not and option, Cherokee supports a workaround. The mechanism requires the web server to listen to several IPs, and to assign a specific one for each virtual server. This can be done through the `Match` tab of the virtual server configuration, by assigning an IP-method to the desired IP. Remember that the list of virtual servers is evaluated from top to bottom, so in case you specify the same IP for several virtual servers, only the first one will actually match. In case you need more flexibility than that to match your domains, you can always add more than one matching criteria on that section. An IP/Subnet match plus a simultaneous wildcard match is a combination likely to cover every corner-case scenario you are presented with.

How to enable the SSL support?

SSL support is not enabled by default. You will have to perform three straightforward actions is order to enable it:

1. The first step is to enable a TLS/SSL engine. The option is located in the General configuration setting. Cherokee is shipped with a libssl plug-in.

2. Once the engine is configured, a new binding port must be configured. By default, HTTPS uses the port 443. Remember to add this port, and to check the TLS toggle button.

3. The last step would be to assign SSL certificates to the virtual servers, starting with the default virtual server. Cherokee uses SNI to distinguish between virtual servers. The certificate specified in the default server will be used in the first negotiation. If not present, the startup sequence will fail. The configuration is found inside each virtual server configuration, under the Security tab. This part is very important: you have to concatenate your certificates into a single file in order to use them in Cherokee.

How to manually test HTTP/HTTPS?

HTTP can easily be tested like this:

    $ telnet localhost 80
     GET / HTTP/1.0

For HTTPS it is not so easy because of the SSL protocol between TCP and HTTP. However you can do a similar check with the help of OpenSSL’s s_client command.

    $ openssl s_client -connect localhost:443 -state -debug
     GET / HTTP/1.0

You will receive detailed information about the SSL handshake before the actual HTTP response.

A more general command line client is probably a better choice. cURL deals with both HTTP and HTTPS, and performs a bunch of other interesting stuff.

    $ curl http://localhost/
    $ curl https://localhost/

### Private keys and Certificates overview

First some terminology:

1. RSA private key file: a digital file that can be used to decrypt messages sent to you. It has a public component that must be distributed (via your Certificate file) to allow people to encrypt those messages.

2. CSR, or Certificate Signing Request: a digital file containing your public key and your name. It is sent to a Certifying Authority (CA) that will convert sign it to convert it into a real Certificate.

3. Certificate: contains your RSA public key and name, the name of the CA, and is digitally signed by the CA. A browser that knows the CA can verify the signature and obtain your RSA public key, which can be used to send messages which only you can decrypt.

Does the startup between a non-SSL and an SSL-aware web server differ?

Yes. Although in essence it is exactly the same, if you have a passphrase on your SSL private key file, a startup dialog will asks you to enter it. This can be problematic if the web server needs to be started automatically. In this case, the passphrase can be removed from your private key at the cost of erasing a security layer, which brings additional security risks.

Does Cherokee offer any help for Certificate Generation?

Yes. A script is provided to assist you with Certificate Generation.

Just locate the `contrib` subdirectory and type:

    make-cert.sh

And follow the instructions. It will generate the required files, but you will have to install them manually.

It has been tested and has worked fine every time, but if you don’t find the script or it doesn’t work for you can always follow the rest of the procedure described in this recipe to manually generate the certificates.

### Locate CA.pl or CA.sh

- On Debian or Ubuntu those are usually located under /usr/lib/ssl/misc/

- On MacOS X, you will find them in /System/Library/OpenSSL/misc/

In any other case ``find / -iname CA.pl -print`` will help you to locate it.

### Create a new CA

         $ /usr/lib/ssl/misc/CA.pl -newca
         CA certificate filename (or enter to create) <press enter>
         Making CA certificate ...
         Generating a 1024 bit RSA private key
         .............++++++
         .......................................++++++
         writing new private key to './demoCA/private/cakey.pem'
         Enter PEM pass phrase: <type the secret phrase again>
         Verifying - Enter PEM pass phrase: <type the secret phrase again>
         -----
         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) [AU]:ES
         State or Province Name (full name) [Some-State]:.
         Locality Name (eg, city) []:.
         Organization Name (eg, company) [Internet Widgits Pty Ltd]:Cherokee Team
         Organizational Unit Name (eg, section) []:<Enter>
         Common Name (eg, YOUR name) []:Cherokee Certificate Master
         Email Address []:alvaro@alobbs.com

### Generate a certificate request

         $ /usr/lib/ssl/misc/CA.pl -newreq
         Generating a 1024 bit RSA private key
         .....................................++++++
         ...++++++
         writing new private key to 'newreq.pem'
         Enter PEM pass phrase: <another phrase>
         Verifying - Enter PEM pass phrase: <repeat it>
         -----
         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) [AU]:ES
         State or Province Name (full name) [Some-State]:.
         Locality Name (eg, city) []:.
         Organization Name (eg, company) [Internet Widgits Pty Ltd]:Cherokee web server
         Organizational Unit Name (eg, section) []:.
         Common Name (eg, YOUR name) []:www.cherokee-project.com
         Email Address []:sysop@cherokee-project.com

         Please enter the following 'extra' attributes
         to be sent with your certificate request
         A challenge password []: <Enter>
         An optional company name []: <Enter>
         Request (and private key) is in newreq.pem

### Sign the certificate request

      $ /usr/lib/ssl/misc/CA.pl -sign:
      Using configuration from /usr/lib/ssl/openssl.cnf
      Enter pass phrase for ./demoCA/private/cakey.pem:
      Check that the request matches the signature
      Signature ok
      Certificate Details:
            Serial Number: 1 (0x1)
            Validity:
                Not Before: Aug 17 13:12:44 2003 GMT
                Not After : Aug 16 13:12:44 2004 GMT
            Subject:
                countryName               = ES
                organizationName          = Cherokee web server
                commonName                = www.cherokee-project.com
                emailAddress              = sysop@cherokee-project.com
            X509v3 extensions:
                X509v3 Basic Constraints:
                CA:FALSE
                Netscape Comment:
                OpenSSL Generated Certificate
                X509v3 Subject Key Identifier:
                14:6A:45:66:A2:EB:73:74:5A:C5:68:80:50:D5:48:94:DD:ED:25:F7
                X509v3 Authority Key Identifier:
                keyid:9E:E0:E2:6E:1B:02:17:F2:72:C9:0D:E3:DA:C9:E1:8F:CE:BC:6E:A2
                DirName:/C=ES/ST=Madrid/L=Madrid/O=Cherokee Team/CN=Cherokee Certificate Master/emailAddress=alvaro@alobbs.com
                serial:00

      Certificate is to be certified until Aug 16 13:12:44 2004 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
      Signed certificate is in newcert.pem

### Self signed certificates

It is another way to generate certificate files. Ramon Pons sent this little script to create self signed certificates::

    #!/bin/sh
    CERTNAME=cherokee.pem
    openssl req -days 1000 -new -x509 -nodes -out $CERTNAME -keyout $CERTNAME
    chmod 600 $CERTNAME
    openssl verify $CERTNAME
    if [ $? != 0 ]; then
        \mv $CERTNAME $CERTNAME.not_valid
    fi

You can see that, in essence, it issues the following command:

    $ openssl req -new -x509 -nodes -out server.crt -keyout server.key

Which would produce a couple of files: the SSL Certificate File (server.crt) and the SSL Certificate key file (server.key).

This server.key does not have any passphrase. To add a passphrase to the key, you should run the following command, and enter & verify the passphrase as requested.

    $ openssl rsa -des3 -in server.key -out server.key.new
    $ mv server.key.new server.key

You should probably backup the key file and the entered passphrase in a secure location.

### Pass-phrase issues

As noted above, if you have a pass-phrase on your SSL private key file, the web-server start up will remain on hold until you enter it. Here is the information needed to change it or even remove it, but bare in mind the security implications.

How to change the pass-phrase on a private key file?

Simply read it with the old pass-phrase and write it again, specifying a new pass-phrase. This can be done withe these commands:

    $ openssl rsa -des3 -in server.key -out server.key.new
    $ mv server.key.new server.key

How to get rid of the pass-phrase?

The RSA private key inside the server.key file is stored in encrypted format for security reasons. The pass-phrase is needed to decrypt this file, so it can be read and parsed. Thus, removing it removes a layer of security from the web server. It is advised to keep a backup copy of the original file before proceeding.

     $ cp server.key server.key.org
     $ openssl rsa -in server.key.org -out server.key
     $ chmod 400 server.key

Since the server.key now contains an unencrypted copy of the key, if anyone gets it they will be able to impersonate you on the net.

### Verifying that a private key matches its Certificate

To view the Certificate and the key run the commands:

    $ openssl x509 -noout -text -in server.crt
    $ openssl rsa  -noout -text -in server.key

The `modulus` and the `public exponent` portions in the key and the Certificate must match. It is difficult to visually check that the long modulus numbers are the same, so this approach can be used instead to obtain the numbers to compare (though it is mathematically less rigorous).

    $ openssl x509 -noout -modulus -in server.crt | openssl md5
    $ openssl  rsa -noout -modulus -in server.key | openssl md5

To check to which key or certificate a particular CSR belongs you can perform the same calculation on the CSR as follows:

    $ openssl req -noout -modulus -in server.csr | openssl md5