Security first with the Hiawatha web server

Small but Safe

Switching On the Anti-Hacker Configuration

The great virtual host website is working. Now I have to protect it from attack. Because I want to set up my servers according to the "defense in depth" standard, I choose to switch on almost all anti-hack preventions settings. My default stance is that Joomla will surely have vulnerabilities I do not know about (but others do). You might find this extreme security focus too much of a good thing, because defense in depth sometimes worsens performance, and features like SQL prevention can potentially block legitimate traffic.

You can choose not to use some or all of the prevention clauses in the following configuration: think about it and choose. The same argument is true for which TLS version to allow: Allowing TLS 1.0 could make your visitors vulnerable to sniffing attacks. My recommendation is to use the settings as reflected below, but please do make your own choices.

The configuration in Listing 3 includes settings that will help you:

Listing 3

Config File Settings

ServerId = www-data
ConnectionsTotal = 1000
ConnectionsPerIP = 25
SystemLogfile = /var/log/hiawatha/system.log
GarbageLogfile = /var/log/hiawatha/garbage.log
ExploitLogfile = /var/log/exploit_attempts.log   # xss sqli etc
DHsize = 4096                   # default 2048, for tls
RandomHeader = 250              # anti decryption on https listening
set local_net =  #define your local networks you do not want to block
# Deny service to clients who misbehave.
#anti hacker trying evil things
PreventCSRF = yes  # ignoring all cookies sent by a browser when following an external link
PreventSQLi = yes  #no 100% guarantee, resource intensive!
PreventXSS = yes   # replacing a less-then, greater-then, quote or double-quote in the URL with an underscore
BanlistMask = deny local_net        ## this network will not be banned
RequestLimitMask = deny local_net   ## this network can upload all they want
BanOnDeniedBody = 120
BanOnGarbage = 600              #seconds
BanOnInvalidURL = 0             #seconds #risky if > 0
BanOnMaxReqSize = 600           #seconds
BanOnSQLi = 600                 #seconds
BanOnWrongPassword = 3:120      #seconds
MinTLSversion = 1.1             #drop attempts to fool webserver to be insecure. You might want 1.0
#anti dos
BanOnFlooding = 10/1:15
KickOnBan = yes                 # close all connections for an IP that is banned
#MaxUrlLength = 500             #default 1000. Longer -> 404
ReconnectDelay = 3              #how long connection wil stay open after no traffic
RebanDuringBan = yes            # keep them banned if they retry
#anti ddos: usable when under attack
#BanOnMaxPerIP = 60                     #seconds
#ChallengeClient = 200, httpheader, 60  #after 200 connects send a coockie
BanOnTimeout = 10                       #ban if no request comes after X seconds, only syn etc
#ListenBacklog = 128                    #default 16
  • Avoid being hit by SQL attacks.
  • Avoid being hit by cross-site scripting (XXS).
  • Avoid being hit by hacking attacks by people trying loads of random or very long URLs.
  • Avoid being hit by DOS attacks where one or a few hosts tries to slow your service down with (lots of) (very slow) connections.

Alas, distributed DOS attacks (DDOS attacks) are sometimes more than you can beat with just one clever Hiawatha server. The configuration in Listing 3 might help but is not sufficient protection. See the Hiawatha documentation for more on other steps you can take to defend your system from attacks.

Of course, you should monitor your logfiles to ensure you don't block things you do not want to block:

tail -f /var/log/hiawatha/exploit_attempts.log

Also, it is a good idea to check your stats for clues on how you can improve CPU or memory usage. The top command provides a wealth of knowledge on the state of your system.

For low-traffic websites, you should expect no problems. If you have a lot of traffic, you might need to pay attention to the effect these security settings have on performance. If the load is high, the settings in Listing  4 might help. I would always recommend the caching settings. After altering your config file, restart the web server to check for errors.

Listing 4

Performance Settings

CacheRProxyExtensions = css, gif, html, jpg, js, png, txt
CacheSize = 25 #mb
CacheMaxFilesize = 128  #kb
##load tinkering
#ListenBacklog = 128    #default 16
#MaxServerLoad = 0.7    #drop on high load (eeks)
#SocketSendTimeout = 10 #default is 3 Sets the SO_SNDTIMEO value for all client connection sockets
#ThreadPoolSize = 50    #default 25
#ThreadKillRate = 10    #default 1

Installing Joomla

Joomla is a popular open source CMS you can run on top of Hiawatha. (Before you install Joomla, or make any other major change to your system, consider taking a snapshot of the virtual machine so you can easily revert back if you have problems.)

To add Joomla to the website, I need to make the following changes to the Hiawatha config file:

  • Add a section to use a fastcgi daemon installed on the TurnKey Linux VM. Make sure all other CGI options are deleted or not active.
  • Add a URL toolkit section to catch and deny evil hacker attempts and to reroute all non-existing requests to the root page of the website
  • Adjust the virtual host configuration to include the necessary URL toolkit and fastcgi config settings

Open the Hiawatha config file and add the settings in Listing 5.

Listing 5

Getting Ready for Joomla

#yes fastcgi, bit adjusted (php-fastcgi.sock)
FastCGIserver {
        FastCGIid = PHP5
        ConnectTo = /var/lib/hiawatha/php-fastcgi.sock
        Extension = php
#url toolkit for joomla
UrlToolkit {
    ToolkitID = joomla
    Match base64_encode[^(]*\([^)]*\) DenyAccess
    Match (<|%3C)([^s]*s)+cript.*(>|%3E) DenyAccess
    Match GLOBALS(=|\[|\%[0-9A-Z]{0,2}) DenyAccess
    Match _REQUEST(=|\[|\%[0-9A-Z]{0,2}) DenyAccess
    Match ^/index\.php Return
    RequestURI exists Return
    Match .* Rewrite /index.php
VirtualHost {
        Hostname =, *
        WebsiteRoot = /var/www/thisagreatwebsite
        StartFile = index.php   #php, not html of course
        ErrorHandler = 404:/index.html
        TimeForCGI = 5
        UseFastCGI = PHP5
        UseToolkit = joomla

Next, you need to change one line in the fastcgi config file (/etc/default/php-fastcgi) so it uses a socket in the Hiawatha directories. Change the following line:


to say:


Download the latest stable version of Joomla from the project website  [4]. At the time of writing, the current version was 3.4.5. Copy the link download location and download and unzip it:

cd /var/www/thisisagreatwebsite

Now make a configuration.php file and adjust file rights properly, so the web server can make and change files as needed:

touch  configuration.php
find -type d -exec chmod 1774 {} +
find -exec chown www-data:www-data {} +

The preceding commands ensure that the Joomla installation can add files and folders by using the sticky bit on directories [5].

Carry on with the Joomla install through your web browser. Go to , and you should be redirected to the standard Joomla install script at . Fill in all the details, like the password, the name of the website, and so on. Please refer to the Joomla documentation [6] for detailed information.

After installing Joomla, you need to change some details in the /etc/php5/cgi/php.ini file so it will work right with Hiawatha. Find the following settings and change them to the following values:

cgi.fix_pathinfo = 0
# Enable GZip content encoding
zlib.output_compression = On
zlib.output_compression_level = 6

Reboot and see if the website you just installed shows up at .

The Joomla logging is usually in /var/www/thisisagreatwebsite/logs/. Typical troubleshooting commands are:

tail -f /var/www/thisisagreatwebsite/logs/acces.log
tail -f /var/www/thisisagreatwebsite/logs/error.log

My Joomla website did not work properly under TLS because the baseref was wrong (HTTP instead of HTTPS). I found a fix online, which was to change the file joomla/libraries/joomla/document/html/renderer/head.php.

Find the next bit of code at around line  65 and comment it out, as follows:

// Generate base tag
/** $base = $document->getBase();
if (!empty($base))
$buffer .= $tab . '<base href="' . $document->getBase() . '" />' . $lnEnd;
} **/

Adding Firewall Rules

If your Hiawatha web server is connected to the Internet, it makes sense to make sure an outside user can only connect through ports 80 and 443. On the inside interface, you can leave other ports open, such as ports for SSH (22), webmin, and so forth.

On the Debian-based TurnKey Linux, you can add iptables rules that load after every reboot. Before you begin, make a snapshot or backup in VMware or your hypervisor, in case you accidentally lock yourself out.

Create (or open) the file network/if-pre-up.d/iptablesload in a text editor and add the iptables scripting rules shown in Listing 6. Then, make sure the file is executable:

Listing 6

Firewall Rules

01 #!/bin/bash
02 #iptables script reverse-proxy version 1.0 dec 2015 By Hans-Cees Speel.
03 EXTDEV=eth1  #external device
04 LANDEV=eth0
06 echo -n "flushing all chains"
07     /sbin/iptables -F -t filter
08     /sbin/iptables -F -t nat
09     /sbin/iptables -F -t mangle
10     /sbin/iptables -X -t filter
11     /sbin/iptables -X -t nat
12     /sbin/iptables -X -t mangle
13     /sbin/iptables --flush  FORWARD
14     /sbin/iptables --flush  INPUT
15     /sbin/iptables --flush  OUTPUT
17 #exit
19 #policies for the chains
20     /sbin/iptables --policy FORWARD DROP
21     /sbin/iptables --policy INPUT DROP
22     /sbin/iptables --policy OUTPUT DROP
24 #new chains. Statefull and scrub icmp
25     /sbin/iptables --new-chain StatefulInputFilter
26     /sbin/iptables --new-chain icmpInOut
28 ###INPUT chain
29 #icmp scrubbed via icmpInOut, local loop is accepted #multicast is dropped, rest to stateful chain
30     /sbin/iptables --append INPUT --protocol icmp --jump icmpInOut
31     /sbin/iptables --append INPUT -i lo -j ACCEPT
32     /sbin/iptables --append INPUT -s    -j DROP
33     /sbin/iptables --append INPUT -d    -j DROP
34     /sbin/iptables --append INPUT -j StatefulInputFilter
36 #accept outgoing traffic, drop forward traffic
37 /sbin/iptables --append OUTPUT --jump ACCEPT
38 /sbin/iptables --append FORWARD -j DROP
40 #StatefulInputFilter chain for incoming syns # Allow established connections, accept Lan, accept 80,443 internet
41 /sbin/iptables --append StatefulInputFilter  -m state --state ESTABLISHED,RELATED -j ACCEPT
42 /sbin/iptables --append StatefulInputFilter -m state --state NEW ! -i  $EXTDEV -j ACCEPT
43 /sbin/iptables --append StatefulInputFilter -p tcp -m multiport --dport 80,443 -m state --state NEW -j ACCEPT
44 /sbin/iptables --append StatefulInputFilter --jump DROP
46 #chain icmpInOut This chain is used for icmp and lets only certain kinds in.
47 /sbin/iptables --append icmpInOut --proto icmp --icmp-type redirect -o $LANDEV --jump ACCEPT
48 /sbin/iptables --append icmpInOut --proto icmp --icmp-type echo-request --jump ACCEPT
49 /sbin/iptables --append icmpInOut --proto icmp --icmp-type echo-reply --jump ACCEPT
50 /sbin/iptables --append icmpInOut --proto icmp --icmp-type destination-unreachable --jump ACCEPT
51 /sbin/iptables --append icmpInOut --proto icmp --icmp-type source-quench --jump ACCEPT
52 /sbin/iptables --append icmpInOut --proto icmp --icmp-type time-exceeded --jump ACCEPT
53 /sbin/iptables --append icmpInOut --proto icmp --icmp-type parameter-problem --jump ACCEPT
54 /sbin/iptables --append icmpInOut --jump DROP
56 #enable tcp synflood protection by using coockies ddos defense
57 echo 1 > /proc/sys/net/ipv4/tcp_syncookies
58 /usr/bin/logger Iptables script hcs implemented
59 ############# you might also consider installing fail2ban
chmod +x network/if-pre-up.d/ \
  iptablesload # make it executable reboot

After the reboot, check if the iptables rules have loaded with iptables -L.

The iptable rules in Listing 6 assume your outside interface is eth1. You can check if this is so with the command ifconfig. If your outside interface is eth0, adjust the firewall rules accordingly. (If you have only one interface, I suggest you add another interface for security reasons.)

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Getting a free TLS certificate from Let's Encrypt
    A free TLS certificate from Let's Encrypt means you can add encryption to your network for no cost, so you don't have any more excuses for failing to encrypt.
  • Port Knocking
    To ensure that the data on your computers remains accessible only by you and those with whom you want to share, we look at the advantages of combining TCP Wrappers and port knocking.
comments powered by Disqus