pmeerw's blog

Mon, 04 Feb 2019

Setting up DANE

DANE (RFC 6698) basically allows to publish the hash of server certificate as a TLSA record in DNS, signed with DNSSEC. A client can validate that a server's TLS certificate is owned by the same entity which controls DNSSEC signed zone.

The idea is to add a new DNS record of type TLSA to the zone, in particular a Certificate Usage DANE-EE (3).

25._tcp.mail IN TLSA 3 1 1 2c788de8eaf09f6b1f5a704a5e0718206c668f00dfca8f8112608dc25571553c
In the example, 3 is the usage (DANE-EE), 1 the selector (subject public key), 1 the matching type (SHA-256). This for my MX record,, port 25 (wildcard port number * would also be possible). The hash can be conveniently generated (taken from Viktor Dukhovni's tlsagen script):
openssl x509 -in /etc/letsencrypt/live/ -noout -pubkey | \
    openssl pkey -pubin -outform DER | \
    openssl dgst -sha256 -binary | \
    hexdump -ve '/1 "%02x"'

Since my server certificate is issued by Let's Encrypt, the certificate is renewed every 90 days or so. Because DANE essentially puts the certificate's public key into DNS, the DNS record needs to be updated whenever the key changes. Luckily, recent letsencrypt scripts (since >= 0.25.0, June 2018) support the argument renew --reuse-key, so the same keys are reused. The certificate is renewed, but not the underlying keys. Here is my weekly cron job script /etc/cron.weekly/letsencrypt:

letsencrypt renew --reuse-key --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2"
res=$(find /etc/letsencrypt/live/ -type l -mtime -1)
if [ -n "$res" ]; then
  echo "letsencrypt: new cert"
  systemctl restart apache2
  systemctl restart postfix
  systemctl restart dovecot
  echo "letsencrypt: nothing to do"
Weirdly, the documentation is to be found with certbot -h automation, not certbot -h renew.

To verify, use the DANE SMTP validator (, see the results for

posted at: 00:24 | path: /configuration | permanent link

Sun, 03 Feb 2019

Security checkup for web and email: has a nice & tidy check for IPv6, TLS, HTTPS, DNSSEC, DANE (DNS-based Authentication of Named Entities), DMARC (Domain-based Message Authentication, Reporting & Conformance), DKIM (DomainKeys Identified Mail), SPF (Sender Policy Framework) on web and mail servers.

See the results for web and email.

posted at: 23:44 | path: /configuration | permanent link

Various security updates

  1. Enable HTTP Strict Transport Security (HSTS), easy: simply enable Apache headers module, a2enmod headers, and add Header add Strict-Transport-Security: "max-age=15768000;includeSubdomains"; yeah, finally A+ on SSL Labs!
  2. Permanent redirect from HTTP to HTTPS using Apache rewrite module:
    RewriteEngine on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=permanent,L]
  3. Turn HTTP compression off in Apache: SetEnv no-gzip 1
  4. Enable DANE (RFC 6698) in postfix: check that the DNS resolver on the mail server supports DNSSEC (e.g. use dig and see if the ad flag is present), then set the following in /etc/postfix/
  5. Update postfix cipher suites to disable insecure ciphers in /etc/postfix/
    smtp_tls_ciphers = high
    smtpd_tls_ciphers = high
    smtp_tls_mandatory_ciphers = high
    smtpd_tls_mandatory_ciphers = high
    smtpd_tls_exclude_ciphers = aNULL
    smtp_tls_exclude_ciphers = aNULL

posted at: 23:33 | path: /configuration | permanent link

Thu, 24 Jan 2019

Setting up DNSSEC

Finally, I decided to give DNSSEC a try, the technology should be somewhat mature by now...

So I'm using bind 9.11.5 on Debian buster to secure I loosely followed the Debian DNSSEC HOWTO. DNSViz has been useful for testing.

Bind9 configuration

Create a directory /etc/bind/keys Enable DNSSEC in /etc/bind/named.conf.options and set the key directory:

options {
  // ...
  dnssec-enable yes;
  key-directory "/etc/bind/keys";

Creating keys

The bind9utils package has the dnssec-keygen tool, so run:

cd /etc/bind/keys
dnssec-keygen -a RSASHA256 -b 2048 -3
dnssec-keygen -a RSASHA256 -b 2048 -3 -fk
to obtain the following files:
-rw-r--r-- 1 bind bind  601 Jan 22 22:31
-rw------- 1 bind bind 1776 Jan 22 22:31
-rw-r--r-- 1 bind bind  602 Jan 22 22:32
-rw------- 1 bind bind 1776 Jan 22 22:32
I have set ownership of keys/ to bind:bind, so: chown -R bind:bind /etc/bind/keys/
Configuring the DNS zone

The zone is configured in /etc/bind/named.conf.local:

zone "" {
        type master;
        file "/etc/bind/";
        auto-dnssec maintain;
        inline-signing yes;

Restart the nameserver: service bind9 restart
Use dig @ +dnssec axfr and RRSIG, NSEC records should be displayed for the zone. Zone transfers (AXFR) must be allowed, at least for localhost:

options {
  // ...
  allow-transfer {;

Configuring DNSSEC with the registrar

I'm using Joker; in case the authoritative nameserver is already configured correctly for DNSSEC,'s web-based administration interface already has all the required fields completed: alg: 8, digest: 5C09567DA17552239455C597878F97CCABDDBF6E, digest type: 1 (or 2), keytag: 14644 In order to get these values, the dnssec-dsfromkey tool is helpful: dnssec-dsfromkey /etc/bind/keys/ IN DS 14644 8 1 5C09567DA17552239455C597878F97CCABDDBF6E IN DS 14644 8 2 E2085DD26A5BE04722BCE5DEC62CA739919CCE9B8743800610142B7AF4BB2080
The listing shows the DS records that would be configured in the .at nameserver; it provides us with the keytag (14644), algorithm (8 for RSA/SHA256, see list), digest type (1 for SHA-1, 2 for SHA-256, see list) and the digest value.

AppArmor gets in the way

I had to limit UDP packet sizes to 512 in /etc/bind/named.conf.options, otherwise IPv6 showed transmission problems and delays -- not fully investigated yet, some related info
options {
  // ...
  edns-udp-size 512;
  max-udp-size 512;
Results and verification

DNSViz results for

See also DNSSEC-analyzer results.

posted at: 19:31 | path: /configuration | permanent link

Thu, 24 May 2018

Adding space to a Linux LVM volume

The steps can be done when the disk is online; only creating the partition required a reboot for me.

Growing the filesystem
  1. Create a physical LVM volume: pvcreate /dev/sdaN; check using pvdisplay
    $ pvcreate /dev/sdaN
      Physical volume "/dev/sdaN" successfully created
    $ pvdisplay
       --- Physical volume ---
      PV Name               /dev/sda1
      VG Name               vg-name
      --- Physical volume ---
      PV Name               /dev/sda2
      VG Name               vg-name
      "/dev/sdaN" is a new physical volume of "100.00 GiB"
      --- NEW Physical volume ---
      PV Name               /dev/sdaN
      VG Name
      PV Size               100.00 GiB
      Allocatable           NO
      PE Size               0
      Total PE              0
      Free PE               0
      Allocated PE          0
  2. Extend the volume group: vgextend vg-name /dev/sdaN; check using lvdisplay
    $ vgextend vg-name /dev/sdaN
      Volume group "vg-name" successfully extended
    $ lvdisplay
      --- Logical volume ---
      LV Name                /dev/vg-name/root
      VG Name                vg-name
  3. Extend the logical volume to all free space available: lvextend -l+100%FREE /dev/vg-name/root
    $ lvextend -l+100%FREE /dev/vg-name/root
  4. Resize the file system: resize2fs /dev/mapper/vg--name-root
    $ resize2fs /dev/mapper/vg--name-root
Partition type code for LVM is 8e.

Some more useful commands
lvmdiskscan -l to scan for LVM physical volumes
vgdisplay -v to summarize lot of information about a volume group
lvs to find the logical volumes and there size; also try the --segments argument

posted at: 11:16 | path: /configuration | permanent link

Made with PyBlosxom