kssl - an in-kernel SSL proxy
There is an interesting feature in Solaris. It is called kssl. One component of this feature is obvious: SSL. So it has something to do with SSL encryption. As you may have already guessed, the k at the beginning stands for kernel. And kssl is exactly this: A proxy to do all the encryption stuff in a kernel module.
This feature is already four years old. I’ve reported about kssl back in December 2005[^24] for the first time. After talking with a customer two days ago and looking at some new material about it[^25], i thought it could not harm to write a new tutorial about this topic. So much appearances in such a small timeframe are a hint ;) .
The reasons for SSL in the kernel
There are several good reasons to to encryption in the kernel.
-
The kssl proxy uses the Solaris Cryptographic Framework. Even when the application doesn«t support cryptographic libraries with PKCS#11 support, you can use the advantages of the framework like the seamless integration of hardware cryptography
-
The application server just see unencrypted traffic. The complete handshake is done in the kernel-space. It«s done asynchronously and the application isn«t involved in this task.
-
You don«t have to wake up the webserver for the SSL handshake to process all the messages nescessary for SSL.
-
By offloading SSL into this kernel module you can yield a much better performance. Krishna Yenduri states in a presentation: SPECweb05 banking is the main benchmark. Performance gain of more than 20% compared to a user land SSL web server. SPECweb99_SSL showed gains of more than 35%
Configuration
The configuration of an SSL proxy is really easy. At first you need a certifcate and the key. For this experiment we will use a self-signed certificate. I«ve called the system a380, thus i have to use this name in my certificate. Use the name of your own system in your configuration. Furthermore the kssl system expect key and certificate in a single file. We concatenate both files afterwards:
# mkdir /etc/keys
# cd /etc/keys
# openssl req -x509 -nodes -days 365 -subj "/C=DE/ST=Hamburg/L=Hamburg/CN=a380" -newkey rsa:1024 -keyout /etc/keys/mykey.pem -out /etc/keys/mycert.pem
# cat mycert.pem mykey.pem > my.pem
# chown 600 *
Now we configure the kssl proxy:
# echo "pass" > /etc/keys/my.pass
# ksslcfg create -f pem -i /etc/keys/my.pem -x 8080 -p /etc/keys/my.pass a380 443
At first we create a file to automatically answer the passphrase question. Afterwards we configure the kssl service. This configuration statement tells the system to get the keys and from a pem file. The -i option specifies the location of the file. -p tells the service where it finds the passphrase file. At the end you find a380 443. This specifies on which interface and on which port the ssl should listen. At last the -x 8080 specifies to what port the the unencrypted traffic should be redirected.
After configuring this service, you should see a new service managed by SMF:
# svcs -a | grep "kssl"
online 9:03:33 svc:/network/ssl/proxy:kssl-a380-443
Obviously we need a webserver in the backend that listens to port 8080. I assume, that you’ve already installed an Apache on your server. We just add a single line to the configuration file of the webserver.
# svcadm disable apache22
# echo "Listen 192.168.178.108:8080" >> /etc/apache2/2.2/httpd.conf
# svcadm enable apache22
When you put https://a380:443 in your browser, you should see an encrypted "It works" page after you dismissed the dialog warning you of the self-signed certificate. Or to show it to you on the command line:
# openssl s_client -connect 192.168.178.108:443
CONNECTED(00000004)
depth=0 /C=DE/ST=Hamburg/L=Hamburg/CN=a380
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=DE/ST=Hamburg/L=Hamburg/CN=a380
verify return:1
---
Certificate chain
0 s:/C=DE/ST=Hamburg/L=Hamburg/CN=a380
i:/C=DE/ST=Hamburg/L=Hamburg/CN=a380
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICoTCCAgqgAwIBAgIJAKyJdj/
[...]
V5jX3MU=
-----END CERTIFICATE-----
subject=/C=DE/ST=Hamburg/L=Hamburg/CN=a380
issuer=/C=DE/ST=Hamburg/L=Hamburg/CN=a380
---
No client certificate CA names sent
---
SSL handshake has read 817 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-SHA
Session-ID: 32CEF20CB9FE2A71C74D40BB2DB5CB304DA1B57540B7CFDD113915B99DBE9812
Session-ID-ctx:
Master-Key: 1E7B502390951124779C5763B5E4BBAF0A9B0693D08DCA8A587B503A5C5027B6FAD9CA7626B1AD8C62219E8502A5C21E
Key-Arg : None
Start Time: 1242985143
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
GET / HTTP/1.0
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 09:39:13 GMT
Server: Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8a DAV/2
Last-Modified: Thu, 21 May 2009 21:26:30 GMT
ETag: "341f3-2c-46a72cc211a8f"
Accept-Ranges: bytes
Content-Length: 44
Connection: close
Content-Type: text/html
<html><body><h1>It works!</h1></body></html>
read:errno=0
Voila, web server encrypted without a single line of SSL configuration in the webserver config files itself.
Conclusion
It«s really easy to add an kssl proxy in front of your webserver. So it isn’t difficult to make encrypted webserving more efficient.
Do you want to learn more?
man pages
ksslcfg(1m) [^26]
Other
CZOSUG: KSSL - Solaris Kernel SSL proxy - presentation about KSSL.[^27]
KSSL Ð A Kernel Level SSL Server Proxy - a deep dive presentation about KSSL.[^28]