Why I use Hiawatha Webserver

As it has been for many years, Apache is the incumbent web server used to host a majority of websites in the world. According to the most recent Netcraft survey, it still runs around 52% of all active sites on the Internet. It’s also been showing its age for some time, often having major difficulties in scaling. Ironically, this is especially true in its most common incarnation, the prefork processing module. For example, without special (and rarely-used) tuning and configuration, prefork is extremely vulnerable to resource exhaustion attacks including the well-known Slowloris method. By simply hanging on to HTTP sessions for as long as possible, a single malicious user with an ancient computer and an average Internet connection could tie up any one of the majority of websites in the world. Indefinitely.

Tattered Apache feather

In light of Apache’s shortcomings, I’ve been advocating for alternative open-source web servers for some years now. Nginx struck my fancy for a while, with its light weight and high performance. As time wore on, however, feature creep made it less and less appealing to me. Besides this, its configuration syntax reminds me a bit of Sendmail. For those without experience with Sendmail, this is not a compliment. I also experimented with various other web servers, such as Lighttpd and Cherokee. While these were all more desirable than Apache in various ways, there were elements of each I didn’t care for, and ultimately they didn’t meet all of my requirements. That’s when I happened to stumble upon Hiawatha in a Wikipedia article.

About Hiawatha

Hiawatha webserver is an advanced, lightweight, and high-performance webserver written by Hugo Leisink over the course of more than a decade. It was designed with a special emphasis on security, which has always been a field of interest for me. The configuration syntax is refreshingly sane, the codebase is immaculate, and it doesn’t attempt to do any more or any less than a webserver should reasonably be expected to.

Due to the author’s accent on both security and clean, understandable code, in January of 2012, Hugo made the decision to replace OpenSSL as Hiawatha’s cryptography library in favor of the lesser-known PolarSSL. While some balked at this decision, it turned out to be very nearly prophetic, as OpenSSL has been at the center of several Internet-disrupting security flaws over the last few years, the most infamous and devastating of which was of course the notorious Heartbleed. As a Hiawatha user, my own web servers escaped the fiasco completely unscathed.

Hiawatha Webserver

Security Features

Hiawatha’s code base has been audited for security and best-practice, and received favorable results. In addition to the tidy and straightforward design, Hiawatha boasts many security features as standard which would normally be included as modules (or not at all) in other webservers. These vary from preventing various common attacks to banning and even re-banning abusive hosts for a specified amount of time.

Attack Prevention

Hiawatha has several built-in methods available which, while optional, can be enabled to prevent many prevalent attacks. These include resource exhaustion, cross-site scripting, cross-site request forgery, and SQL injection.

  • MaxServerLoad — When the server has a load higher than N, Hiawatha will drop incoming connections.
  • MaxUrlLength — The maximum length of the path of an URL that the webserver accepts as being valid. Otherwise, a 414 error code is returned.
  • MaxRequestSize — The maximum size of a request in kilobytes the webserver is allowed to receive. This does not include PUT requests.
  • ConnectionsPerIP — Limits the maximum number of simultaneous connections per IP address.
  • PreventXSS — Prevent cross-site scripting via the URL by replacing a less-then, greater-then, quote or double-quote in the URL with an underscore.
  • PreventCSRF — Prevent Cross-site Request Forgery by ignoring all cookies sent by a browser when following an external link to this website.
  • PreventSQLi — Prevent SQL-injection by detecting injections and denying the request via a 409 response.
  • DenyBody — If the request body matches the regular expression, return a 403 Forbidden.

Banning Attackers

Some web clients are simply no good, and it’s a waste of time and resources to continue to serve their requests. Thus Hiawatha also possesses the ability to block these users for a period of time which may be specified by configuration.

  • BanOnDeniedBody — Number of seconds to ban an IP in case of a denied request body.
  • BanOnFlooding — When a client sends more than X requests in Y seconds, the IP will be banned for Z seconds.
  • BanOnGarbage — Number of seconds to ban an IP in case of a misformed HTTP request (400 Bad Request).
  • BanOnInvalidURL — Number of seconds to ban an IP in case of an invalid URL.
  • BanOnMaxPerIP — How many seconds a client will be banned when the maximum number of simultaneous connections has been crossed.
  • BanOnMaxReqSize — Number of seconds to ban an IP in case of an oversized HTTP request (413 Request Entity Too Large).
  • BanOnWrongPassword — Number of seconds to ban an IP in case of N wrong passwords for HTTP authentication.
  • BanOnSQLi — Number of seconds to ban an IP in case of a detected SQL-injection attempt.
  • BanOnTimeout — Number of seconds to ban an IP in case of a timeout before the first request has been sent.
  • KickOnBan — Close all other connections that originate from the same IP in case of a ban.
  • RebanDuringBan — Reset the ban-time when a client tries to reconnect during a ban.

Encryption

Cryptography has been gaining a lot of attention lately, and rightly so. This is also one of the areas in which Hiawatha happens to excel, due in part to the inclusion of PolarSSL, which is indeed a substantial advantage over webservers which rely on OpenSSL. But, as the implementation of cryptography is as important as the ciphers themselves, Hiawatha also contains some other interesting attributes.

  • RandomHeader — Adds an X-Random HTTP header to the response for HTTPS connections. The header contains a random string. The length of that string is a random value between 1 and N. This header helps to prevent attackers from guessing what was transferred based on the response length.
  • RequiredCA — Aka mutual TLS. Use the CA certificates in this file to authenticate users. Users without a certificate from one of the listed CAs will not be allowed.
  • RequireSSL — Specify that a domain must be visited with a SSL connection. If it is visited via HTTP, Hiawatha will send a redirect (301) with a HTTPS URL. The HSTS time is the max-age value of the Strict-Transport-Security HTTP header.
  • SSLcertFile — Use this option inside a virtualhost block if you want to make use of the SNI capabilities of Hiawatha.
  • DHsize — Set the size of the Diffie-Hellman key. Default = 2048
  • MinSSLversion — Specify the minimum SSL version Hiawatha accepts for HTTPS connections. Default = TLS1.0
  • The RC4 cipher is considered obsolete, and further, has been the target of patent trolls. Thus, it is disabled by default in Hiawatha.

With its out-of-the-box TLS settings, assuming you’ve correctly issued and installed your cert bundle, you should be able to easily achieve a best-practice crypto implementation. Take for example the humble blog you’re reading now:

Qualys SSL Labs test result for dotbalm.org (A+)

The score would be even higher (400/400) if I set a 4096-bit DH key and required at least TLS1.2.

Performance

As an advanced, event-driven web server, Hiawatha of course performs quite well. Recent versions of Hiawatha also dynamically set its ulimit settings based upon the ConnectionsTotal value in the main Hiawatha configuration file, in order to ensure that the operating system doesn’t arbitrarily limit its scalability. It’s extremely lightweight, requiring only minimal hardware resources, which means it will run well even on embedded systems. On relatively up-to-date server hardware, it’s easy to maintain many thousands of connections per second, though of course this depends largely on the type of content you’re actually serving, whether you’re terminating SSL/TLS, and other factors.

The above in mind, Hiawatha has some useful settings to help improve performance even further. It’s capable of caching up to 100MB [edit: now 1GB] of static content in memory, or even CGI output. If you’re using Hiawatha’s ReverseProxy function to protect or scale a back-end server, such as a legacy Apache site, this can further reduce load on the downstream web server by serving those assets directly from Hiawatha’s own cache. The built-in cache may also be used to store reverse-proxied content with the CacheRProxyExtensions option.

Since security is the main focus of Hiawatha, it may go without saying that it also performs quite well even while under attack:

Hiawatha SlowHTTPTest graph

Hiawatha 9.4 performance while under an extended Slowloris/slowheaders attack (with ‘ConnectionsPerIP’ unset).

Simplicity

One of the things I like best about Hiawatha is the sanity of its configuration syntax. It maintains an excellent balance between comprehensibility and flexibility which is rarely seen in web servers. Contrast the main configuration file of Apache or Nginix with the following example hiawatha.conf:


# Hiawatha main configuration file
#

# VARIABLES
# Here we can set persistent variables.
#
Set LOCALHOST = 127.0.0.0/8
Set LAN = 192.168.1.0/24
Set WLAN = 172.16.1.0/24

# GENERAL SETTINGS
#
ServerString = Hiawatha
ServerId = hiawatha
ConnectionsTotal = 10000
ConnectionsPerIP = 25
ThreadPoolSize = 100
ThreadKillRate = 10
LogFormat = common
SystemLogfile = /var/log/hiawatha/system.log
GarbageLogfile = /var/log/hiawatha/garbage.log
CacheSize = 100
CacheMaxFilesize = 256
MinSSLversion = TLS1.0
DHsize = 2048
SocketSendTimeout = 30
LogfileMask = deny LOCALHOST, deny LAN
RequestLimitMask = deny LOCALHOST, deny LAN

# BINDING SETTINGS
# A binding is where a client can connect to.
#
Binding {
Port = 80
MaxKeepAlive = 100
TimeForRequest = 5,15
MaxRequestSize = 8000
MaxUploadSize = 8
}

Binding {
Port = 443
SSLcertFile = /etc/ssl/localcerts/mainsite_example.pem
MaxKeepAlive = 100
TimeForRequest = 5,15
MaxRequestSize = 8000
MaxUploadSize = 8
}

# BANNING SETTINGS
# Deny service to clients who misbehave.
#
BanOnGarbage = 300
BanOnInvalidURL = 60
BanOnMaxPerIP = 5
BanOnMaxReqSize = 300
BanOnWrongPassword = 6:900
BanOnSQLi = 900
KickOnBan = yes
RebanDuringBan = yes
BanlistMask = deny LOCALHOST, deny LAN, deny WLAN

# COMMON GATEWAY INTERFACE (CGI) SETTINGS
# These settings can be used to run CGI applications.
#
#CGIhandler = /usr/bin/perl:pl
#CGIhandler = /usr/bin/php-cgi:php
#CGIhandler = /usr/bin/python:py
#CGIhandler = /usr/bin/ruby:rb
#CGIhandler = /usr/bin/ssi-cgi:shtml
#CGIextension = cgi
#
FastCGIserver {
FastCGIid = PHP5
ConnectTo = /var/run/php5-fpm.sock
Extension = php, php5
}

# URL TOOLKIT
# Stanzas to handle URL behavior, rewrites, etc.
#
UrlToolkit {
ToolkitID = wordpress
RequestURI exists Return
Match .*\?(.*) Rewrite /index.php?$1
Match .* Rewrite /index.php
}
UrlToolkit {
ToolkitID = mainsite
Match ^/obsolete_page.asp Redirect http://www.mainsite.example/new-page.html
}
UrlToolkit {
ToolkitID = myblog
UseSSL Skip 2
Match ^/wp-login.php(.*) Redirect https://myblog.example/wp-login.php$1
Match /wp-admin/$ Redirect https://myblog.example/wp-admin/$1
}
UrlToolkit {
ToolkitID = trampoline
Match .* Redirect http://www.mainsite.example
}

# DEFAULT WEBSITE
# It is wise to use your IP address as the hostname of the default website
# and give it a blank webpage. By doing so, automated webscanners won't find
# your possible vulnerable website.
#
Hostname = 127.0.0.1
WebsiteRoot = /var/www/default
StartFile = index.html
AccessLogfile = /var/log/hiawatha/access.log
ErrorLogfile = /var/log/hiawatha/error.log
UseToolkit = trampoline

# VIRTUAL HOSTS
# Use a VirtualHost section to declare the websites you want to host.
#

VirtualHost {
Hostname = www.mainsite.example, *.mainsite.example
WebsiteRoot = /srv/www/vhosts/mainsite.example
EnforceFirstHostname = yes
Alias /promotions:/var/www/marketing/campaigns
ShowIndex = no
ExecuteCGI = no
UseToolkit = mainsite
PreventXSS = yes
PreventCSRF = yes
CustomHeader = X-Frame-Options: sameorigin
RandomHeader = 256
}
VirtualHost {
Hostname = myblog.example, *.myblog.example
WebsiteRoot = /srv/www/vhosts/myblog.example
EnforceFirstHostname = yes
SSLcertFile = /etc/ssl/localcerts/myblog_example.pem
ShowIndex = no
StartFile = index.php
TimeForCGI = 30
UseFastCGI = PHP5
UseToolkit = myblog, wordpress
PreventXSS = yes
PreventCSRF = yes
PreventSQLi = yes
CustomHeader = X-Frame-Options: sameorigin
RandomHeader = 64
}


This sample configuration features two vhosts; mainsite.example, which might be a static HTML5 website, and myblog.example, which is an archtypical WordPress blog utilizing PHP. In the example above, both allow TLS and utilize some simple UrlToolkits. You can see that the default server certificate is utilized for mainsite.example, but the blog’s certificate is specified in its vhost stanza (thus requiring SNI support from the browser).

The default website simply calls a UrlToolkit to redirect any stray visitors to www.mainsite.example. There is also some security enforcement and hardening, and the server has been configured for a large amount of simultaneous connections. Obviously your requirements and available server resources should be taken into account while configuring your own web server, but hopefully my example has served as a good overview of an average Hiawatha setup. For more in-depth information, see the Hiawatha manual page.

Conclusion

I’ve been using Hiawatha as my primary web server for about four years, and in that timeframe I’ve never seen a single crash, out of memory error, or other undesirable behavior. It’s also blocked literally millions of attacks and attempted exploits, always been fast and responsive, and to date I have never run into any limitations which might have caused me to regret that decision. There are still some advanced features I haven’t even tried yet, though Hiawatha’s weight has remained light and its performance has only improved as time has marched forward.

When coupled with PHP-FPM or other CGI engine, Hiawatha has no difficulty serving out any number of common frameworks. Lately I’ve also been using it to help protect and provide better scalability for legacy sites which rely on Apache-specific implementations, via Hiawatha’s ReverseProxy functionality. This is an interesting use-case which I may cover in a later article.

Hiawatha is a fast, efficient, and very secure web server which provides a high degree of flexibility and ease of use. It certainly deserves a larger market share than it currently holds, though it has been making some inroads in recent times. If you haven’t tried Hiawatha, you should really give it a spin.

Hiawatha webserver

https://www.hiawatha-webserver.org/

7 thoughts on “Why I use Hiawatha Webserver

  1. I’ve been trying to host my website at home, using an old PC running Lucid Puppy 5 with Hiawatha pre-installed. Looking for tutorials, I stumbled on yours. Thought I should let you know I could not get your slide show to work, browsing with Firefox installed on LinuxMint 17.1. I could use a “for Dummies” tutorial on this, I think.

    Thanks & God bless you.

    Dave

  2. Pingback: Install and Setup PHP5-fpm and MariaDB for Hiawatha Webserver on CentOS 7 | Config my VPS

  3. Pingback: Install and Setup PHP5-fpm and MariaDB for Hiawatha Webserver on CentOS 7 | " SHARE KNOWLEDGE "

  4. Pingback: Install and Setup PHP5-fpm and MariaDB for Hiawatha Webserver on CentOS 7 - ManagedVPS

Leave a Reply

Your email address will not be published. Required fields are marked *