Creating a self-signed certificate with openssl

openssl req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes -keyout server.key -out server.crt -subj '/O=MyCompany/OU=MyDepartment/CN=www.mycompany.com'

Above generates,

server.key
server.crt

Options in detail –

  • -x509 identifies that a certificate is required, rather than just a certificate request (CSR).
  • -days 365 sets the certificate to expire in a year.
  • -sha1 specifies that SHA1 encryption should be used.
  • rsa:1024 sets the key as 1024 bit RSA.
  • -nodes specifies no passphrase.
  • -keyout and -out specify where to store the certificate and key. (Make sure key is root read only)
  • -subj flag sets the company name, department name, and the web site address.
    If you leave these out, you’ll be prompted for them.
    The CN must be the same as the address of your web site, otherwise the certificate won’t match and users will receive a warning when accessing the site.

    Please note you will also get another warning with above cert, i.e.

    Any browser connecting to the site will not recognize the certificate authority. This means that the user will be asked to verify the certificate.
    It’s fine for test purposes, may not be worth paying for a certificate from an external CA like Verisign.

    If you decide to use a certificate signed by external certificate authority then,

    To get a certificate signed by a CA, you first need to create a keypair and a certificate request:

    openssl req -new -sha1 -newkey rsa:1024 -nodes -keyout server.key -out www.mycompany.com.csr -subj '/O=Company/OU=Department/CN=www.mycompany.com'

    Please note we have not used -x509 option hence above command will only generate a key and certificate request, but not a certificate itself.

    The server key (server.key, which again should only be readable by root) stays on your web server; the request (www.mycompany.com.csr) goes to the CA.

    You can call the CSR file whatever you want, but calling it by your domain name will simplify life for the CA.

    Once signed, you will receive a certificate in PEM format, rename it to .crt (Please note if you need both private key and public key from CA instead of using your own then format would be .pfx/.pkcs12/.p12).

    Verifying that a Certificate is issued by a CA

        openssl verify -CAfile /path/to/trusted_ca.crt -purpose sslserver server.crt
    
        server.crt: OK

    If you get any other message, the certificate was not issued by that CA.

    Next, check that the output of these two commands is the same, i.e., that the certificate corresponds to the private key:

        openssl x509 -noout -modulus -in server.pem | openssl sha1
    
        openssl rsa -noout -modulus -in server.key | openssl sha1

    Now install your key (generated as server.key above) and certificate (server.crt), into /etc/apache2/ssl, or your preferred Apache2 config directory, if that’s different. As mentioned above, it’s important to make sure that the server.key is readable only by root, while the server certificate should be world-readable, but owned and writeable only by root.
    You can create your certificate either with or without a passphrase.
    The major disadvantage of using a passphrase is that it must be typed every time the web server starts up.
    So it won’t start unattended or automatically on boot, for example, after a power cut.

    You may look at this, if you really want to use a key passphrase,

    http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslpassphrasedialog

    If you only have one SSL site on your server, the simplest form of this would be:

    # either of these will work
    SSLPassPhraseDialog |/path/to/passphrase-script
    SSLPassPhraseDialog exec:/path/to/passphrase-script
    You would then create a very simple script called /path/to/passphrase-script that contains something like the following:

    #!/bin/sh
    echo “put the passphrase here”

    chmod +x /path/to/passphrase-script

    Configuring Apache with SSL

    Include /etc/apache2/mod_ssl.conf in httpd.conf

    If you wish to run both a secure server (on port 443) and a regular server (on port 80).

    In httpd.conf,

    Listen 80
    Listen 443

    virtual_hosts.conf (include this in httpd.conf -> include virtual_hosts.conf )

    NameVirtualHost *:443

    <VirtualHost *:443>
    
    
        ServerName mysite.co.uk
        DocumentRoot "/data/websites/mysite.co.uk/docroot"
        DirectoryIndex index.html
        DebugConfigInfo ON
    
        SSLEngine on
    
        SSLOptions +StrictRequire
    
        <Directory />
    
            SSLRequireSSL
    
        </Directory>
    
        SSLProtocol -all +TLSv1 +SSLv3
    
        SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM
    
        SSLRandomSeed startup file:/dev/urandom 1024
    
        SSLRandomSeed connect file:/dev/urandom 1024
    
        SSLSessionCache shm:/usr/local/apache2/logs/ssl_cache_shm
    
        SSLSessionCacheTimeout 600    
    
        SSLCertificateFile /etc/apache2/ssl/server.crt
    
        SSLCertificateKeyFile /etc/apache2/ssl/server.key
    
        SSLVerifyClient none
    
        SSLProxyEngine off
    
        <IfModule mime.c>
    
            AddType application/x-x509-ca-cert      .crt
    
            AddType application/x-pkcs7-crl         .crl
    
        </IfModule>
    
        SetEnvIf User-Agent ".*MSIE.*" \  
    
          nokeepalive ssl-unclean-shutdown \  
    
          downgrade-1.0 force-response-1.0
    
    </VirtualHost>

    A few notes on this configuration:

    SSLEngine must be enabled so that the server uses SSL.
    DocumentRoot sets the root directory for this virtual host. This means that you can separate secure content entirely from regular content.
    SSLRequireSSL requires SSL to be used (on this virtual host): i.e., a user can’t connect to this host using a regular HTTP request. This is why we separate out the secure and regular root directory.
    SSLProtocol disables all protocols other than TLS v1.0 and SSL v3.0. This will be OK for current web browsers.
    SSLCipherSuite is set to use only HIGH and MEDIUM security cipher suites. SHA1 is considered to be more secure than MD5 so is preferred.
    SSLCertificateFile and SSLCertificateKeyFile should be set to the locations where you put your certificate and key files.
    SSLVerifyClient should be set to none if not using client authentication.

    To run the regular server on port 80, add the following section to the config file:

    NameVirtualHost *:80
    
    <VirtualHost *:80>
    
        DocumentRoot "/local/www/html"
    
        # Host-specific directory setup, options, etc
    
        # Most of these options are likely to be set outside the VirtualHosts
    
        # sections.
    
    </VirtualHost>

    After you’ve saved the edited configuration file, restart the web server. If you did use a passphrase when generating your certificate, you’ll need to enter it when challenged.

    Testing

    Create a basic index.html page wherever the root directory for your web server is located, if you don’t already have content there.

    Then point your web browser at https://www.yoursite.com. You should see an SSL connection opened and the page delivered. If you’re using a self-signed certificate, your browser will pop up an alert warning you that the server’s identity cannot be verified. You can choose to view and accept the certificate. If using an external certificate, it should all happen without intervention.

    Make sure as well that you can’t access the protected content using http://. If you try, you should get an error message.

    Troubleshooting

    If it’s not working as expected, first check that your server is actually running, using ps -a | grep apache. If that doesn’t return anything, try restarting it, and check for error messages on the terminal.

    Also check that the permissions on your key and certificate files are set correctly (see above), as well as the permissions on your test HTML file and its parent directory.

    Next, check the logs. You should check both the main server logs and also the SSL logs that you set up in your config file above. If you don’t get anything useful, try changing the LogLevel value in the Apache2 config file to “debug”, restart Apache2, and test again. This should give more logfile data.

    If you are running a regular web server on port 80 as well, try fetching a test page via http:// rather than https:// to help identify whether the problem is with the web server or with the SSL connection. Note that in the setup above, the web server’s root directory is different for http:// and https://, so you won’t (or shouldn’t!) be able to access the same content. If your test page in the http:// root directory works fine, though, and your test page in the https:// root directory doesn’t, then that can help you to pinpoint the problem.

    If the problem is the SSL connection, a useful tool is s_client, which is a diagnostic tool for troubleshooting TLS/SSL connections. The basic usage is: /usr/bin/openssl s_client -connect localhost:443. There are numerous other options as well, for which you can check the documentation. If you get error messages, this should help you in locating the problem.

    ALL CREDIT: http://www.onlamp.com/pub/a/onlamp/2008/03/04/step-by-step-configuring-ssl-under-apache.html