runit

During the last ten years many initd alternatives have appeared. Some are very “SysV-like” like initng. Others are way more radical in their design both more modern and complex (systemd / upstart).

But what if you need a simple and lightweight alternative with supervision capability ?

Then runit is a very good choice, and you can use it to replace or complement initd.

Install runit

aptitude install runit

Add a service to supervise

The core of runit is the /etc/sv directory. This directory contains a subdirectory for each process that runit should manage. Let say we want to add a varnish service:

# vi /etc/sv/varnish/run
#!/bin/sh
exec 2>&1
. /etc/default/varnish 
rm -f /var/lib/varnish/$INSTANCE/*
exec varnishd -F $DAEMON_OPTS

Simple and neat. Note that the process shouldn’t be launch in background / daemonized mode. If necessary add the appropriate option. Then:

# chmod +x run
mkdir supervise
chmod 755 supervise

Now don’t forget to add a diversion to the official initscript and then enable the supervision:

ln -s  /etc/sv/varnish /etc/service/varnish

The sv command

sv status gu-monprojet
sv check gu-monprojet
sv up gu-monprojet
sv down gu-monprojet
sv restart gu-monprojet

As you can see commands are very straightforwards.

Note that sv can be use to send pretty much every unix signal (HUP, USR1, USR2, etc…).

Logging process output

Under runit process logging is dead simple: let your process send it data to STDOUT and svlogd will do the rest. This program collect your process’s data and save it into a system-standard location. It will take care of rotating log file if necessary by itself.

To add a log to a process create a log script:

# vi /etc/sv/varnish/log
#!/bin/sh
exec svlogd -tt /var/log/varnishd

Replace initd

To replace initd by runit, just follow the official documentation.

NSE scripts

The most powerful feature of nmap is its script engine. This allow you to use it in a semi-automatic mode, performing complex task, such as vulnerability detection, backdoor detection and even vulnerability exploitation.

You can find a list of NSE scripts here, and write your own in LUA.

Currently my two favorite are :

[Varnish] Stripping tracking cookies

Tracking tool, like google analytics, set cookies that are only used by their client side javascript. Theses cookies are no interest for your server, and depending your configuration their can event prevent cache usage. So it’s better to simply strip them.

To do that, add into the vcl_recv this block:

# Remove Google Analytics, Piwik and other tracking cookies
if (req.http.Cookie) {
   set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
   set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_pk_(ses|id)[\.a-z0-9]*)=[^;]*", "");
   set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__utm.=[^;]+;? *", "\1");
}
# Remove cookies when empty
if (req.http.Cookie == "") {
   remove req.http.Cookie;
}

Further Reading and sources

[Varnish] Testing ESI support

Since version 2.1 varnish support, at least partially, the ESI protocol. ESI is very useful to improve the cache hit ratio because it allow the splitting of uncachable dynamic pages into an ‘heavy’ static page and one or several ‘light’ dynamic page bloc.

Enable ESI support

For Varnish 2.x add into the vcl_recv:

esi;

For Varnish 3.x the syntax is:

set beresp.do_esi = true;

Testing ESI

To test ESI support, you need to create two files. The first will be a simple HTML ‘template’ file. We will call it frontpage.html:

<html>
<head>
<title>ESI Test Page</title>
</head>
<body>
<p><esi:include src="/backpage.php"/></p>
</body>
</html>

Next we need a file to generate the ‘dynamic’ content. A very simple PHP script like this we be enough:

<?php
echo "ESI is correctly interpreted";
?>

If ESI support is correctly enabled, calling the first page will result into calling the second file as well, displaying the proper “ESI is correctly interpreted” string.

Override the TERM environment variable

The TERM environment variable is used by your terminal emulator to indicate which type of control string it supports. For the most part you should not override this variable, but there is a narrow set of circumstances where the default value can be incorrect or at least not optimal.

For example in most distributions the default value for a console terminal is linux and for a graphical terminal xterm. That’s fine, but don’t allow you to enjoy vim or screen 256 color mode in graphical mode.

A traditional xterm only supports 16 colors and this value is specify into the terminfo database.
As you can image, changing the xterm entry would have made users of the newer versions happy but also broken the configuration for others. Instead a new value xterm-256color was declared. That may seems fine but when you log in remotely to machines with an older terminal database, the value isn’t recognized.

In this case the only viable solution left is to override the TERM value in order to unset the 256 color mode. You can do it by adding something like that to the .bash_profile on the remote machine:

if echo $TERM | grep -q -- '-256color'; then
    export TERM=`echo -n $TERM | sed 's/-256color//'`
fi

GoAccess

GoAccess is a real-time ncurse weblog analyzer and interactive viewer. Contrary to Awstats and other similar product, GoAccess doesn’t keep any “history”, but in exchange it’s way more faster. Having ‘on the fly’ HTTP statistics is extremely useful when load suddenly increase on a front webserver.

For analyzing a given log file use the -f option, like this:

goaccess -f /var/log/apache/access.log

If you don’t use standard NCSA or common log format, you can specify the log format with --log-format=. For a more permanent solution you can redefine the log-format value inside the /etc/goaccess.conf setting file.

You can also generate an html report like this:

goaccess -f /var/log/apache/access.log -a -o report.html

[Redhat] Lock package versions

In Redhat/CentOS 6 it’s possible to selectively pin a particular package version to keep it from updating. For that we will use the versionlock plugin:

yum install yum-plugin-versionlock

To add a package to the lock list:

yum versionlock add <package_name>
Loaded plugins: security, versionlock
Adding versionlock on: 0:<package_name>-<package_version>
versionlock added: 1

To remove an entry from lock list:

yum versionlock delete 0:<package_name>-<package_version>
Loaded plugins: security, versionlock
Deleting versionlock for: 0:<package_name>-<package_version>
versionlock added: 1

To check the lock list content:

yum versionlock list
Loaded plugins: security, versionlock
0:<package_name>-<package_version>
...
versionlock list done

[Varnish] Purge objects from command line

Purge all content

For Varnish 2.x:

varnishadm -S /etc/varnish/secret -T :6082 'purge.url .*'

For Varnish 3.x:

varnishadm -S /etc/varnish/secret -T :6082 'ban.url .'

Purge objects from a specific URL

For Varnish 2.x:

varnishadm -S /etc/varnish/secret -T :6082 'purge.url /foobar'

For Varnish 3.x:

varnishadm -S /etc/varnish/secret -T :6082 'ban.url == /foobar'

Note that ban accepts regex pattern. By modifying the expression you can create more specific bans. For example, to purge for all CSS files only for a specific domain:

varnishadm -S /etc/varnish/secret -T :6082 'ban req.http.host ~ www.mydomain.com && req.url ~ .css'

Further Reading and sources

Introduction to fail2ban

While connecting to your server through SSH is secure, the SSH daemon itself is a service that must be exposed to the internet to function properly. Therefore it become a target for brute force attacks by bots. The good practice is always to filter access by IP, but what to do if you can’t ? Port-knocking and fail2ban will be my personal answer. Let talk about the latter.

What is fail2ban ?

fail2ban is a service that create iptable rules on-the-fly after a number of unsuccessful login attempts. This will allow your server to respond to illegitimate access attempts without intervention from you.

Configure fail2ban

The main setting file is /etc/fail2ban/jail.conf
The most important variables to adjust are maxretry which sets the number of tries a client can attempt and findtime which define the opportunity window and obviously bantime.

To specify which service fail2ban should check add a block like this:

[ssh]
enabled = true
port    = ssh,sftp
filter  = sshd
logpath  = /var/log/auth.log

If you wan to customize the regex pattern, you can look inside the /etc/fail2ban/filter.d directory. Don’t forget to reload the daemon and test your configuration.

Further Reading and sources

[Apache] CORS header

What is CORS ?

CORS or cross-origin resource sharing is a mechanism that allows resources on a web page to be requested from a different domain than the page origin. To do that the CORS mecanism use a specific header: Access-Control-Allow-Origin.

For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example XMLHttpRequest and Fetch follow the same-origin policy. This header allow you to customize this behavior.

Authorize a domain

Just add to your apache configuration:

Header set Access-Control-Allow-Origin "https://www.domain.com"

Authorize multiple domains

Access-Control-Allow-Origin can take only one value. You could use the value * but that ugly and defeat the whole purpose of filtering request domain origin.

But with a little trickery you can do that:

SetEnvIfNoCase Origin "https?://(domain\.com|staging\.domain\.com)(:\d+)?$" ACAO=$0
Header set Access-Control-Allow-Origin %{ACAO}e env=ACAO

This regex use the content of the Origin header and define a matching Access-Control-Allow-Origin value. Here we authorize both the http and https versions of domain.com and staging.domain.com to load ressources from our domain.

Further Reading and sources