Thursday, December 25, 2008

KB: WEBrick SSL Configuration

WEBrick SSL Configuration

Contents

Overview

This article assumes that you are working with an existing Ruby on Rails application and that you will be using a self-signed certificate.

Create a Self-signed Certificate

1. In a directory of your choosing, create an RSA Private Key:
openssl genrsa -des3 -out server.key 1024
2. Create a certificate signing request (CSR):
openssl req -new -key server.key -out server.csr
3. Remove the passphrase:
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
4. Create the self-signed certificate, follow the prompts and remember to set the CN to "localhost":
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Install the Private Key and Certificate

1. In your Rails application under the config directory, add a new directory named certs:
mkdir /home/krdavis/projects/openeprs/config/certs
2. Copy the private key and certificate to the new certs directory:
cp server.crt /home/krdavis/projects/openeprs/config/certs
cp server.key /home/krdavis/projects/openeprs/config/certs

Create a Secure Server Script

The following code does not modify script/server. The secure server code will be placed in script/server_secure. This can be useful if secure and non-secure instances of WEBrick need to be run simultaneously e.g. to verify redirects when using the ssl_requirement plugin.

This configuration uses a self-signed certificate. This means the first time a browser accesses the application at https://localhost:3001, an invalid certificate error will be raised. A certificate exception can be added via the browser to suppress this message.

Create script/server_secure:
#!/usr/bin/env ruby

require File.dirname(__FILE__) + '/../config/boot'

require 'webrick'
require 'webrick/https'

puts "=> Booting WEBrick..."

OPTIONS = {
  :port         => 3001,
  :ip           => "127.0.0.1",
  :environment  => (ENV['RAILS_ENV'] || "development").dup,
  :server_root  => File.expand_path(RAILS_ROOT + "/public/"),
  :pkey         => OpenSSL::PKey::RSA.new(
                      File.open(RAILS_ROOT + "/config/certs/server.key").read),
  :cert         => OpenSSL::X509::Certificate.new(
                      File.open(RAILS_ROOT + "/config/certs/server.crt").read),
  :server_type  => WEBrick::SimpleServer,
  :charset      => "UTF-8",
  :mime_types   => WEBrick::HTTPUtils::DefaultMimeTypes,
  :debugger     => false
}

ENV["RAILS_ENV"] = OPTIONS[:environment]
RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)

require RAILS_ROOT + "/config/environment"
require 'webrick_server'
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)

class SSLDispatchServlet < DispatchServlet
  def self.dispatch(options)
    Socket.do_not_reverse_lookup = true
    server = WEBrick::HTTPServer.new(
      :Port             => options[:port].to_i,
      :ServerType       => options[:server_type],
      :BindAddress      => options[:ip],
      :SSLEnable        => true,
      :SSLVerifyClient  => OpenSSL::SSL::VERIFY_NONE,
      :SSLCertificate   => options[:cert],
      :SSLPrivateKey    => options[:pkey],
      :SSLCertName      => [ [ "CN", WEBrick::Utils::getservername ] ]
    )

    server.mount('/', DispatchServlet, options)
    trap("INT") { server.shutdown }

    server.start
  end
end

puts "=> Rails application started on https://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
puts "=> Ctrl-C to shutdown"

SSLDispatchServlet.dispatch(OPTIONS)
Note: In OPTIONS, :pkey and :cert point to the private key and certificate that were created earlier and copied to config/certs.

Start the SSL enabled WEBrick by running the following command from the root of the Rails application:
script/server_secure
which will produce the following output:
=> Booting WEBrick...
=> Rails application started on https://127.0.0.1:3001
=> Ctrl-C to shutdown
[2008-12-25 16:25:17] INFO  WEBrick 1.3.1
[2008-12-25 16:25:17] INFO  ruby 1.8.7 (2008-08-11) [i686-linux]
[2008-12-25 16:25:17] INFO  
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            ca:11:ce:7e:d0:88:3d:d1
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, ST=MT, L=Billings, O=ZuniSoft, OU=Development, CN=localhost/emailAddress=info@zunisoft.com
        Validity
            Not Before: Dec 13 17:06:43 2008 GMT
            Not After : Dec 12 17:06:43 2013 GMT
        Subject: C=US, ST=MT, L=Billings, O=ZuniSoft, OU=Development, CN=localhost/emailAddress=info@zunisoft.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:b2:62:67:f8:99:f8:a7:a8:ae:0c:25:fe:c7:71:
                    91:b2:de:49:1c:97:02:7f:24:fa:27:bf:f1:90:72:
                    4b:85:15:90:75:8e:21:a0:28:f8:ba:60:28:22:91:
                    33:8c:c9:8d:9a:d9:2d:5f:af:d7:5f:d4:a7:fa:da:
                    ca:c2:b1:8e:cb:c6:14:9a:41:1e:fc:79:bf:b0:57:
                    52:8e:a7:82:4f:2b:4c:6a:02:c0:94:cc:db:58:ac:
                    47:6e:3d:d9:52:95:64:72:50:b3:67:7c:af:d2:f0:
                    3f:fb:c8:2b:b0:5d:81:21:7e:3c:23:88:a4:08:6e:
                    f8:09:c8:bc:6e:37:e8:6e:c3
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
        82:5e:f7:a7:e8:1d:58:08:d3:0a:c3:77:d0:b5:ce:12:ef:97:
        16:1e:c5:00:8c:a0:5b:9a:0f:a9:39:90:8d:2b:bf:97:bb:a3:
        09:2c:df:68:dd:84:e0:15:72:67:f8:95:9b:08:11:67:34:d9:
        01:33:b9:53:ce:d4:b7:d1:e8:64:b5:3d:9c:f8:7f:69:ec:50:
        aa:67:e2:cb:87:26:49:28:de:27:b6:09:0b:cc:f6:15:8d:9c:
        7d:03:ad:f1:80:41:b8:53:6c:a3:d0:28:8c:ab:dd:78:3a:ce:
        70:42:f1:08:79:40:3a:16:9d:0c:aa:d6:04:a0:09:6c:8e:c7:
        ff:95
[2008-12-25 16:25:17] INFO  WEBrick::HTTPServer#start: pid=2393 port=3001
To Top