Lighttpd, pronounced "lighty", is a powerful light-weight web server that makes an ideal candidate for use in building dedicated SOAP application server.  In this article, I explore the use of Lighttpd as the engine in serving SOAP requests.  The following criteria was used in selecting the candidates:

  • small operational and memory footprint
  • able to handle multiple simultaneous requests
  • capable of running HTTP and/or HTTPS over SSL for encryption
  • Perl CGI capable
  • easy to configure

With that said, lighttpd seemed the perfect fit.  As I worked more and more with lighttpd, I found that all of the criteria was met, with one caveat. SSL client-side certificate validation cannot be disabled in the current release 1.4.20 that I am running.  While this is not a show-stopper, it is a hindrance and is very annoying because it means you cannot use self-signed certificates.

Step 1 - Building lighttpd

Lighttpd has required and optional library prerequisites that must be pre-compiled.  For the purposes of this article, I will stick with the minimum required libraries that I used to build lighttpd.

  1. download openssl from www.openssl.org (version 0.9.8i)
  2. download libpcre from http://www.pcre.org/ (version 7.8)
  3. download libz from http://www.zlib.net (version 1.2.3)
  4. download lighttpd from http://www.lighttpd.net/ (version 1.4.20)

Since we are building a SOAP web server application, its best to simplify the target prefix to a single location such as /export/opt/SOAPserver.  This will help centralize the configuration, file locations, directory structure, and ability to create an installation routine around it.  The following was performed to build the software:

zlib

./configure --shared --prefix=/export/opt/SOAPserver
make
make install

openssl

./Configure --prefix=/export/opt/SOAPserver zlib-dynamic shared solaris-sparcv9-cc
make
make install

libpcre

./configure --prefix=/export/opt/SOAPserver
make
make install

Before you can build lighttpd, you must put pcre-config in your current path or the configure command will fail. Since our prefix installation path has been /export/opt/SOAPserver, we need to add /export/opt/SOAPserver/bin to our current path:

PATH=$PATH:/export/opt/SOAPserver
export PATH

lighttpd

./configure --prefix=/export/opt/SOAPserver \
    --with-openssl=/export/opt/SOAPserver   \
    --with-zlib=/export/opt/SOAPserver/lib  \
    --with-pcre
make
make install

Step 2 - Configuring Lighttpd as a SOAP server

Next, lighttpd needs to be configured as a CGI server.  This section explains how to configure lighttpd to run HTTPS over a non-standard TCP port.  The following configuration steps are covered:

  1. create a self-signed x509 certificate using openssl
  2. create lighttpd.conf to run SSL on port 4443 using our openssl certificate
  3. configure lighttpd to run CGI programs
  4. install a SOAP CGI handler for our program

Creating self-signed Certificates using OpenSSL

First, it's always a good idea to make your openssl.cnf file known and set as the default when running openssl from the command line.  Your system may have multiple versions of SSL installed, and you want to ensure that you always use the intended config, binary CLI, and libraries when multiple copies reside on the system.  To set the path to our newly installed openssl installation, set the following environment variable to the fully-qualified path of the conf file:

OPENSSL_CONF=/export/opt/SOAPserver/ssl/openssl.cnf; export OPENSSL_CONF

For the SOAPserver, let's create an etc directory in the base path /export/opt/SOAPserver to store configuration files, as well as, our SSL keys for our daemon.  Generate an RSA key as follows:

# openssl genrsa 1024 > server.key
Generating RSA private key, 1024 bit long modulus
...++++++
........................++++++
e is 65537 (0x10001)
# chmod 400 server.key

Then create the self-signed certificate:

# openssl req -new -x509 -nodes -sha1 -days 365 -key server.key > server.cert
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]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:localhost
Email Address []:This email address is being protected from spambots. You need JavaScript enabled to view it.

Some applications call for the key and the certificate to be in one file or in PEM format.  The following step is optional, and its recommended only where called for.  Otherwise, the key and certificate can remain in two separate files.  Since lighttpd has only a single parameter for loading the key/cert file, cat them together as shown below:

# cat server.cert server.key > server.pem
# rm server.key
# chmod 400 server.pem

Configuring lighttpd to run SSL on port 4443

Create a document root directory called "docroot" in our base directory path of /export/opt/SOAPserver.  This will be the web server's main document root that will hold all cgi and/or html files that will be served.  To configure lighttpd, you must create a conf file that can be passed to the daemon at start-up.  Create lighttpd.conf in the /export/opt/SOAPserver/etc directory and provide the basic start up server directives:

server.document-root = "/export/opt/SOAPserver/docroot"
server.username = "www"
server.groupname = "www"
server.port = 4443

This is a minimal configuration file and is all that is needed to start the server  on our custom TCP port 4443.  To start the daemon, type the following command:

/export/opt/SOAPserver/sbin/lighttpd -D -f /export/opt/SOAPserver/etc/lighttpd.conf &

When the daemon is started without the error log directive, you may see output to the console.  Test the server by creating an index.html file in the docroot directory that displays "hello, world", and perform a test with the browser at http://localhost:4443/index.html
Next, let's configure lighttpd to run in SSL mode.  Do this simply by adding the following directives to the ex sting lighttpd.conf file:

ssl.engine = "enable"
ssl.pemfile = "/export/opt/SOAPserver/etc/server.pem"

Save the lighttpd.conf file, and restart the server.  Once restarted, re-test using the same URL that was previously tested.  You will notice that adding the SSL directives in this fashion disables the non-ssl web server, and the server now operates exclusively over SSL.  An additional SSL directive can be used called "ssl.ca-file".  This directive should be used to point to the chained certificate file or Certificate Authority File.  If the ssl.ca-file directive is NOT configured, MS IE will accept our certificate but firefox will not.  The server is now only reachable by https://localhost:4443/index.html

Configure lighttpd to run CGI programs

In the second to last step, all that is needed here is to load the CGI model and set the handler. Do this by adding the following two directives into our lighttpd.conf file:

server.modules = ( "mod_cgi" )
cgi.assign = ( ".pl"  => "/usr/bin/perl",
               ".cgi" => "/usr/bin/perl"
)

Stop and restart the server.  The server is now ready to serve perl CGI pages.
Install SOAP CGI Handler
To complete our SOAP server, install a simple SOAP CGI program.  It is assumed that all prerequisite libraries and perl modules are built and installed on the system. Create a new file in our docroot directory called hibye.cgi with the following code:

#!/usr/bin/perl -w
use SOAP::Transport::HTTP;

SOAP::Transport::HTTP::CGI   
    -> dispatch_to('Demo')     
    -> handle;

package Demo;
sub hi {                     
    return "hello, world";     
}
sub bye {                    
    return "goodbye, cruel world";
}


The following code sets up a simple class or package called Demo that contains two separate methods or subroutines that can be called remotely, "hi" and/or "bye". This code was pulled directly from the SOAP::Lite usage guide and should serve well as a test of our SOAP server.  It's not until this last step that problems surface.  Last, we'll need a client to test our SOAP server.  The following code snippet can be used to test the code above:

#!/usr/bin/perl -w

use SOAP::Lite;
print SOAP::Lite
-> uri('https://localhost:4443/Demo')
-> proxy('https://localhost:4443/hibye.cgi')
-> hi()
-> result;


When the SOAP client is run from the command line, you should see the output "hello, world". I found that this failed.  Debugging revealed that the SOAP client was failing SSL v3 negotiation because the SOAP server was performing SSL Client Certificate Validation, and currently lighttpd doesn't have a way of disabling that.  An open issue exists on the lighttpd web site describing this feature exactly.  This is supposed to be fixed or added to their next release 1.4.21.  For details on client-side validation refer to http://redmine.lighttpd.net/issues/show/1288.  While more testing is required, this is a show-stopper for any project that requires SSL authentication and/or encryption to work properly.  In search of a working solution, I have turned to a different implementation of the http/https daemon, using shttpd.  It is even more lightweight and easily built and configured.  To be continued....