DNSSEC Zone Key Tool (ZKT) support for included files

DNSSEC Zone Key Tool is a powerful tool suite for managing DNSSEC zones. It automatically creates/deprecates keys, resigns the zone at fixed intervals and also resigns zones if they where modified.

Detection of modified zones is done by looking at the last-modified date of the files (zone.db, dnskeys.db and zone.db.signed) – if zone.db or dnskeys.db are newer than zone.db.signed a resign is necessary. However, zkt-tools do not support/check the last-modification date of included files (with the “$INCLUDE” directive). This patch adds support for this, so that all included files are also checked whether they were modified since the last signing of the zone.

Upstream report: https://sourceforge.net/p/zkt/patches/2/, https://github.com/hzuleger/ZKT/pull/10

Postfix and “eMail made in Germany”

If you use Postfix as your MTA, one can (and should) enable transport encryption for outgoing connections using “smtp_tls_security_level=may” (or “smtp_use_tls=yes”, deprecated since Postfix 2.3). However, this does not enforce that…

  • encryption is always used for every site (supporting it). Enforcing this by setting “smtp_tls_security_level=encrypt” also is not an option because there are lots of sites which do not support transport encryption (like @me.com). I.e. if someone can perform a MitM attack, the attacker can “hide” the STARTTLS announcement of the server and thus the mail goes over the wire unencrypted.
  • the remote server which supports encryption is the “right” one (e.g., in case of DNS hijacking or MitM attacks). The problem is, that one cannot set “smtp_tls_security_level=verify” because there are lots of sites which have self-signed certificates or certificates where the domain name of the certificate does not match the MX server hostname or the mail-address domain name.

In order to enforce transport encryption for specific sites and avoid the problems described above one can use “smtp_tls_policy_maps” to specify that encryption is mandatory and that the “right” server is used. Insert “smtp_tls_policy_maps = hash:/etc/postfix/tls_policy” to /etc/postfix/main.cf, use the example content from below (or a the latest version) and run “postmap /etc/postfix/tls_policy” and reload postfix. It is also required that “smtp_tls_CApath” is set correctly so that the certificates can be checked against “trusted” root certificates; on Debian it can be set to “smtp_tls_CApath = /etc/ssl/certs/” and the package “ca-certificates” is required.

The main problem with this solution is, that you need to manually create a list of servers. I checked my logs and created this list for the most-used destination domains (I created a repository on GitHub in case someone wants to contribute: https://github.com/csware/postfix-tls-policy):

/etc/postfix/tls_policy:
# members of email made in germany
t-online.de secure match=.t-online.de
gmx.net secure match=.gmx.net
gmx.de secure match=.gmx.net
gmx.at secure match=.gmx.net
web.de secure match=.web.de
freenet.de secure match=.freenet.de
email.de secure match=.web.de
# other mail providers
gmail.com secure match=.google.com
googlemail.com secure match=.google.com
google.com secure match=.google.com
kabelmail.de secure match=.xworks.net
#hotmail,outlook: not all mx-servers support starttls
#hotmail.com secure match=.hotmail.com:.outlook.com
#outlook.com secure match=.hotmail.com:.outlook.com
#hotmail.de secure match=.hotmail.com:.outlook.com
#me.com does not support starttls at all
aol.com secure match=.aol.com
yahoo.com secure match=.yahoodns.net
yahoo.de secure match=.yahoodns.net
arcor.de secure match=.arcor.de
# universities
.hu-berlin.de secure match=.hu-berlin.de
.tu-clausthal.de secure match=.mx.srv.dfn.de:.tu-clausthal.de
# states of germany
#.bayern.de: mx has selfsigned cert
.bayern.de encrypt
.berlin.de secure match=.berlin.de
.hessen.de secure match=.hessen.de
.niedersachsen.de secure match=.niedersachsen.de

Update 2014-05-24: I’m running Postfix > 2.11.0 (and I’ve a DNSSEC capable dns server) so I’ve set “smtp_tls_security_level=dane” which is a bit better than “may”, because DANE/TLSA enabled sites are more secure and authenticated.

Debian Squeeze->Wheezy dist-upgrade and VMware tools

If you run Debian 6 (Squeeze) under an VMware Hypervisor (ESXi 5.0+) with VMware Tools installed and you want to upgrade to Debian 7 (Wheezy) make sure you uninstall VMware tools in advance.

Several machines did not boot up after the upgrade with the 3.2.x kernel and hanged forever just after “Switching to guest configuration”. I always create snapshots in advance of major upgrades. So there was no data loss, however, the whole upgrade process had to be restarted…

Hint: Starting with Debian 7 open-vm-tools are included in the official Debian repository: This package is an open source replacement for VMware tools and fits perfectly into the Debian system (e.g. post kernel update triggers). IIRC the open-vm-tools package is also included in the official Ubuntu repository (12.04 LTS has a recent version) – there is also an old version in 10.04 LTS included, however, I never tested that. VMware hypervisor detects it as a “third party”/”manually maintained” VMware tools package and provides the usual options.

Update 2013-09-25: I’m using open-vm-tools since May and had no problems so far.

Apache httpd: Use php-cgi without mod_php

The PHP site describes how to use PHP as a Apache httpd module, however that’s not always the desired option (e.g. if you want to use different PHP versions at the same time).

In order to enable PHP in CGI mode we use the action module of Apache httpd. On Debian-based systems you have to enable it using a2enmod actions.

One can enable php-cgi for the whole installation via the global httpd.conf, for vhosts or for specific files/folders using .htaccess-files. The configuration looks as follows:
# CUSTOM: Add PHP parsing (via CGI) handler and action for .php files
ScriptAlias /local-bin/php-cgi /usr/bin/php-cgi
AddHandler application/x-httpd-php .php
Action application/x-httpd-php /local-bin/php-cgi

Maybe you also need to allow access to /usr/bin by adding:

<Directory "/usr/bin">
Order allow,deny
Allow from all
</Directory>

Some other howtos suggest to use a directory as ScriptAlias (e.g. ScriptAlias /local-bin /usr/bin) which might be a security problem, since all tools in /usr/bin can be executed via the web (e.g. http://example.com/local-bin/whoami). Directly using php-cgi prevents this – also php-cgi contains a security check so that I cannot be executed directly.

Update 2013-05-20: Debian 7 has support for this by default (a2enmod php5_cgi, you might need to install php5-cgi).

AWStats on Debian: Incomplete statistics caused by logrotate

AWStats on Debian might generate incomplete statistics. The script update.sh is executed regularly (once every 10 minutes via cron /etc/cron.d/awstats; you should really consider changing this to a bigger interval) in order to update/calculate the statistics (stored in /var/lib/awstats).

I changed the cron-file so that this script is executed once a day. However, the default installation of AWStats only considers /var/log/apache2/access.log (or some other log file) and does not cope with logrotate. So, if logrotate runs /var/log/apache2/access.log is rotated to /var/log/apache2/access.log.1(.gz) and on the next run AWStats only considers the content of the new rotated file. This issue becomes bigger when you increate the update.sh interval – in the default setup you can only loose up 10 minutes.

I reported this to Debian (Debian bug #706491) and proposed a possible solution: Do not use the logfile e.g. /var/log/apache2/access.log in the AWStats config files (e.g. /etc/awstats/awstats.conf: LogFile entry) directly, but use a wrapper script.

My script getlogs.pl can be used as follows: Do not use LogFile=”/var/log/apache2/access.log” in awstats.conf, but LogFile=”getlogs.pl /var/log/apache2/access.log”. If called with exactly one parameter (the logfile) it uses both access.log.1(.gz) (if exists) and access.log. My script can also be executed with “all” as the second parameter, then all existing rotated access.log*-files are used (in the right order and unpacked automatically). This might be useful if you want to build all statistics from scratch or you have bigger update.sh intervals than logrotate intervals. If the second parameter is missing, you can also use the USELOGFILES environent variable. This might be handy if you want to change it’s value more easily w/o editing all awstats.*.conf-files.

Alternative way: Run AWStats as a post-rotate script in logrotate.

AWStats on Debian: Incomplete statistics on new month

When you install AWStats on Debian, buildstatic.sh is executed regularly (once every day via cron /etc/cron.d/awstats) in order to build static statistics pages for the current month (in /var/cache/awstats). However, (on my system) this script is executed every day @3:10am. So in each new month the statistics of the last day of the last month are incomplete. I reported this to Debian with a patch included (Debian bug #706487).

AWStats: GeoIP support for IPv6

AWStats is a widely used tool for creating website usage statistics. For gathering country stats you have two options in AWStats:

  • using reverse dns lookup on the IP addresses
  • use a Geo-IP database

Without the usage of plugins only IPv4 is supported. IPv6 support is only available with a plugin, however, only for performing reverse IPv6 lookups and not for the GeoIP plugin.

In order to fill this gap I created a patch (upstream report). This patch add a new plugin (geoip6) and adds support for GeoIP lookups for both IPv4 and IPv6.

If you want to use my patch you need the Maxmind Geo(Lite) Country IPv6 database (the IPv4 database seems to be included) and the Geo-IP perl package in version >= 1.40 (libgeo-ip-perl in Debian 6; 1.40 is available in Squeeze backports). DNSLookups should be disabled.

Update 2014-02-08: This patch was included into the official development branch.

Windows 7: Restore “System Image Recovery” from usb key

For safety reasons I regularly create a “System Image Recovery” in Windows 7. Then, last week, my SSD crashed (luckily two days after I took a new backup). I plugged in a new hard-drive (a bigger one) and wanted to restore the image.

I was able to boot from my USB key. Windows detected the new hard-drive and could load the system image. However, Windows 7 refused to restore the image:

The system image restore failed. Error: Error details: The parameter is incorrect.(0x80070057)

(on German Windows: “Interner Fehler: Falscher Parameter. (0x80070057)”).

Google showed me that a lot of other people seem to have the same problem – without providing me any solution. It took me round about 2 hours to find a solution: The only way to circumvent this error seems to load the image from network and disconnect *ALL* hard-drives (despite the one you want to restore the image onto) and USB keys (even the USB key from which was booted) just before clicking on “Restore”.

Samba: Logging logins and logouts to MySQL database

I run samba 3 as the PDC on a network. I needed to log which users logged on and off on which machines in my network. Using the build in utmp = yes option was no option since UTMP was rotated using logrotate (so logouts were not always recorded correctly).

So I created a patch which enables Samba to log to a MySQL database. New configuration options are mysqlsessionlogging (boolean to enable logging), mysqlsessionloggingserver (MySQL server address), mysqlsessionloggingusername (MySQL username), mysqlsessionloggingpassword (MySQL password), mysqlsessionloggingport (MySQL port), mysqlsessionloggingdb (MySQL database) and mysqlsessionloggingtable (MySQL table; SQL statement to create the table is included in the patch).

Update 2013-05-02: I use the patch since 2009 (starting with samba 3.0) in a production environment.

mod_auth_pgsql: Support for salted md5 password hashes

Recently I created a patch against the Apache httpd authentication module mod_auth_pgsql 2.0.3 for adding support for salted md5 password hashes. In a scenario I wanted to authenticate users against the PostgreSQL user database. However, mod_auth_pgsql only could handle crypted, md5 and base64 encoded passwords. There was no support for salted MD5 passwords (username+password concatenated) like in pg_shadow-table.

Just apply the patch mod_auth_pgsql-pgsql-saltedmd5.patch and use
Auth_PG_encrypted ON
Auth_PG_hash_type MD5PGSQL

as new configuration parameters.

Update 2013-05-01: Patch accepted upstream.