Stopping DNS leakage with pfSense

I’ve recently changed my core router over from OpenWRT to pfSense.  I was pretty happy with OpenWRT, but I wanted something more powerful since it was running in a VM anyway.

A few days ago, CloudFlare announced their new 1.1.1.1 service.  This is a public DNS service very much like Google’s 8.8.8.8 DNS service, with a notable difference.  It supports TLS.

Why should you care?  Because DNS requests are normally not encrypted, and therefore visible to your ISP to record, use for research / marketing purposes, or even (in the case of some nefarious actors) manipulate or change.  Running DNS over TLS prevents that, by encrypting your DNS traffic so that it can’t be manipulated or collected.

In this post, we’ll be configuring pfSense to do three things – provide a local standard unencrypted port 53 DNS resolver which uses CloudFlare’s 1.1.1.1 encrypted service on the WAN end, and then set up a NAT redirect so any attempts on the internal network to use port 53 DNS servers outside the network instead are intercepted and resolved by the internal resolver.  Lastly, it will also make sure that it blocks any outbound requests to port 53 just to be sure.

NOTE:  There’s one piece here I haven’t figured out yet.  How to pin a cert for the DNS endpoints listed here, so it’s not perfect.  When I figure that out, I’ll edit this post.

Let’s get started.

Configuring the pfSense Local Resolver

In pfSense, go to Services -> DNS Resolver, then put the following block into Custom Options:

server:
ssl-upstream: yes
do-tcp: yes
forward-zone:
    name: "." 
    forward-addr: 1.1.1.1@853
    forward-addr: 1.0.0.1@853
    forward-addr: 2606:4700:4700::1111@853
    forward-addr: 2606:4700:4700::1001@853

You will also need to make sure that the DNS Query Forwarding option is NOT selected, otherwise the above settings will conflict.  It’s OK to set the resolver to listen on all interfaces, since the firewall rules on the WAN will prevent Internet hosts from using your resolver anyway.  Follow the prompts, then test it with something like;

dig www.google.com @yourrouter.local

You should see a resolve against your router’s local DNS resolver that works.  If you really want, use Diagnostics -> Packet Capture, and capture port 853 to verify that requests are being triggered.

Redirect all DNS requests to outside DNS servers to pfSense

Follow the article you can find here.  You will need to do this once for each of your interfaces (in my case, LAN, DMZ, and VPN).  Obviously don’t configure this for the WAN interface.  This then causes any requests to addresses that are not on your internal network to be resolved through the local pfSense resolver (which goes out to port 853 anyway).

To test this, try and dig something against an IP that you know is not internal and is not a DNS server.  It should work, since the request will be NATted.  Something like;

dig www.google.com @1.2.3.4

Assuming that’s all fine, you should now be able to configure a broad block rule to bar all outbound port 53.

Block all outbound non-encrypted DNS

This shouldn’t really be required if the NAT rule is working, but we’ll do it anyway to be sure we’re stopping any DNS leaks.

In pfSense, go to Firewall -> Rules, and for the WAN interface, define a new rule at the top of the list.  This rule should use these settings;

Action: Block
Interface: WAN
Address Family: IPv4+IPv6
Protocol: TCP/UDP
Source: any
Destination: any
Destination Port: DNS (53)
Description: Block outbound insecure DNS

After doing this, verify that you can still resolve against the local resolver (your router’s IP), and that you can still resolve against what seems to be external resolvers (eg, 8.8.8.8).  You should also check that when you do so that nothing passes on the WAN interface on port 53.

If that all passes, you’re done.   It’s up to you if you use the ‘Block’ target or the ‘Reject’ target.  Block causes a simple timeout if something hits 53 (which shouldn’t happen anyway), Reject causes an immediate fail.

Resources

Ubuntu replaces /bin/sh with Dash

Trap for young players.  Ubuntu replaces the default interpreter for /bin/sh from Bash to Dash.  This was done for performance reasons, but certain scripts really don’t like this.  You can easily change it back with;

sudo dpkg-reconfigure dash

Information about this can be found here.  This was done quite a long time ago, apparently, but for whatever reason scripts that ultimately wind up calling the PHP 7.1 interpreter while under Dash break badly under some circumstances (resulting in PHP segfaulting).

 

 

Homemade HOTAS Desk Mount

I decided to make up a desk mount for my HOTAS, so that I could position the stick in a more natural location without having to gorilla-arm it.  The design is very straightforward – it’s a drill vice with a couple of pieces of steel bracket and soft-grip vice jaws to avoid marking the desk.  Total cost under $30.

If you want to replicate this, the spacing of the holes for the Warthog stick are 60mm apart, and are M4 metric screws.  Remember to leave enough clearance so you can push the stick the whole way forwards and not catch your fingers on the vice anywhere.

Darktable for Windows using Vagrant

I have an Olympus TG5 camera, which has RAW support for Darktable, but only in the very latest (currently unreleased!) 2.3.0 version.  Since I have Windows, I’ll have to build Darktable directly from source to be able to manipulate it.  Here’s how you can do that.

First, I assume you have Cygwin/X running.  You’ll also need Vagrant installed, along with VirtualBox.  With all that in place, doing the rest is pretty straightforward.  Create a folder, and throw this Vagrantfile into it;

# -*- mode: ruby -*-
# vi: set ft=ruby :

VMBOX = "bento/ubuntu-16.04"
VMHOSTNAME = "darktable"
VMRAM = "1024"
VMCPU = 2

VAGRANT_COMMAND = ARGV[0]

Vagrant.configure("2") do |config|
  # Configure the hostname for the default machine
  config.vm.hostname = VMHOSTNAME

  # Configure the VirtualBox provider
  config.vm.provider "virtualbox" do |vb, override|
    # The default ubuntu/xenial64 image has issues with vbguest additions
    override.vm.box = VMBOX

    # 1gb RAM, 2 vCPU
    vb.memory = VMRAM
    vb.cpus = VMCPU

    # Configure vbguest auto update options
    override.vbguest.auto_update = false
    override.vbguest.no_install = false
    override.vbguest.no_remote = true
  end

  # Mount this folder as RW in the guest, use this for transferring between host and guest
  config.vm.synced_folder "shared", "/srv/shared", :mount_options => ["rw"]

  # Build the server from a provisioning script (which will build Darktable for us)
  config.vm.provision "shell", inline: <<-SHELL
    # Install essential and optional dependencies
    apt-get update
    apt-get install -y gcc g++ cmake intltool xsltproc libgtk-3-dev libxml2-utils libxml2-dev liblensfun-dev librsvg2-dev libsqlite3-dev libcurl4-gnutls-dev libjpeg-dev libtiff5-dev liblcms2-dev libjson-glib-dev libexiv2-dev libpugixml-dev
    apt-get install -y libgphoto2-dev libsoup2.4-dev libopenexr-dev libwebp-dev libflickcurl-dev libopenjpeg-dev libsecret-1-dev libgraphicsmagick1-dev libcolord-dev libcolord-gtk-dev libcups2-dev libsdl1.2-dev libsdl-image1.2-dev libgl1-mesa-dev libosmgpsmap-1.0-dev

    # Install usermanual and manpage dependencies
    apt-get install -y default-jdk gnome-doc-utils libsaxon-java fop imagemagick docbook-xml docbook-xsl
    apt-get install -y po4a

    # Install this for Cygwin/X to work properly
    apt-get install -y xauth

    # Pull the master repo
    git clone https://github.com/darktable-org/darktable.git
    cd darktable
    git checkout master

    # Pull the submodules
    git submodule init
    git submodule update

    # Build Darktable
    ./build.sh --prefix /opt/darktable

    # Build documentation
    cd build
    make darktable-usermanual
    make darktable-lua-api
    cd ..

    # Install Darktable
    cmake --build "/home/vagrant/darktable/build" --target install -- -j2

    # Copy documentation into shared area
    cp build/doc/usermanual/*.pdf /srv/shared/
  SHELL

  # This piece here is run when we use 'vagrant ssh' to configure the SSH client appropriately
  if VAGRANT_COMMAND == "ssh"
    config.ssh.forward_x11 = true
  end

end

Make a shared folder in that folder, and vagrant up followed by vagrant ssh.

Assuming everything is configured correctly, you can then start Darktable with;

/opt/darktable/bin/darktable

And off you go.  You can add some more mounts into the VM as required to share your picture library or whatever with it so you can manipulate it with Darktable.

Rumble Functionality with XB1 Wireless on Steam Link

If you have the newer (model 1708) XBox One Wireless Controller, you can get it to work with a Steam Link on native Bluetooth pretty easily.  But if it’s straight out of the box, the rumble motor won’t work on the controller.

In order to make it work, you’ll need a PC with Windows 10 and the Anniversary Update installed.  Go to the Windows Store and install ‘Xbox Accessories’ by Microsoft.

Then, plug in your XB1 controller with a USB cable into your PC (shut down Steam first).  The PC will then prompt you to update firmware on the controller.  Do so.  You’ll then have to repair it with the Steam Link, but once that’s done rumble functionality should work.

Threading a X-Tek Pure Buckle the Right Way

In case this is useful for anyone besides me, here is the correct way to thread the waist buckle onto a Scubapro X-Tek Pure Harness;

My sincere apologies for the Microsoft Paint drawing.  The long end of the red line represents the end of the webbing that is attached to the rest of the harness, and the short end is the end that you have in your hand.  The rest should be self-explanatory.  Threading it this way results in the buckle pulling tight properly when buckled in, and also means the other end of the webbing can slide over the buckle properly when putting it on.

You don’t want to know how many times I put it on wrong before I figured this out.  I swear that thing exists in n-dimensional space or something.

Converting a bunch of OGG music to MP3, preserving metadata

Quick one.  If you have a heap of OGG music that you want to convert to MP3 format, and also want to conserve the metadata that’s in the music, run this from Ubuntu;

for name in *.ogg; do ffmpeg -i "$name" -ab 128k -map_metadata 0:s:0 "${name/.ogg/.mp3}"; done

Done and dusted!

Adding an RTC to your Raspberry Pi

I use a RPi 3 as a secondary DNS and DHCP server, and time synchronization is important for that.  Due to some technicalities with how my network is set up, this means that I need a real-time clock on the RPi so that it can have at least some idea of the correct time when it powers up instead of being absolutely dependant on NTP for that.

Enter the DS3231 RTC (available on eBay for a few bucks).  The Pi Hut has an excellent tutorial on setting this up for a RPi, which I’m going to summarize here.

Configure I2C on the RPi

From a root shell (I’m assuming you’re using Raspbian like me);

apt-get install python-smbus
 apt-get install i2c-tools

Then, edit your /boot/config.txt and add the following down the bottom;

dtparam=i2c_arm=on
dtoverlay=i2c-rtc,ds3231

Edit your /etc/modules and add the following line;

i2c-dev

Now reboot.  If you do an i2cdetect -y 1 you should see the DS3231 listed as device 0x68.  If you do, great.

Configure Raspbian to use the RTC

After rebooting, the new device should be up, but you won’t be using it yet.  Remove the fake hardware clock with;

apt-get --purge remove fake-hwclock

Now you should be able do hwclock -r to read the clock, and then hwclock-w to write the current time to it.

And lastly, to make it pull time from the RTC on boot, put the following into /etc/rc.local before the exit 0;

hwclock -s

And you can then add a cronjob in /etc/cron.weekly to run hwclock -w once a week.

Done!

Backing up KVM Virtual Machines with Duplicity + Backblaze

As part of my home DR strategy, I’ve started pushing images of all my virtual machines (as well as my other data) across to Backblaze using Duplicity.  If you want to do the same, here’s how you can do it.

First up, you will need a GnuPG keypair.  We’re going to be writing encrypted backups.  Store copies of those keys somewhere offsite and safe, since you will absolutely need those to do a restore.

Secondly, you’ll need a Backblaze account.  Get one, then generate an API key.  This will be comprised of an account ID and an application key.  You will then need to create a bucket to store your backups in.  Make the bucket private.

Now that’s done, I’m assuming here that you have your /var/lib/libvirt library where your VMs are stored on its own LV.  If this isn’t the case, make it so.  This is so you can take a LV snapshot of the volume (for consistency) and then replicate that to Backblaze.

#!/bin/bash

# Parameters used by the below, customize this
BUCKET="b2://ACCOUNTID:APPLICATIONKEY@BUCKETNAME"
TARGET="$BUCKET/YOURFOLDERNAME"
GPGKEYID="YOURGPGKEYIDHERE"
LVNAME=YOURLV
VGPATH=/dev/YOURVG

# Some other parameters
SUFFIX=`date +%s`
SNAPNAME=libvirtbackup-$SUFFIX
SOURCE=/mnt/$SNAPNAME

# Prep and create the LV snap
umount $SOURCE > /dev/null 2>&1
lvremove -f $VGPATH/$SNAPNAME > /dev/null 2>&1
lvcreate --size 10G --snapshot --name $SNAPNAME $VGPATH/$LVNAME || exit 1

# Prep and mount the snap
mkdir $SOURCE || exit 1
mount -o ro,nouuid $VGPATH/$SNAPNAME $SOURCE || exit 1

# Replicate via Duplicity
duplicity \
 --full-if-older-than 3M \
 --encrypt-key $GPGKEYID \
 --allow-source-mismatch \
 $SOURCE $TARGET

# Unmount and remove the LV snap
umount $SOURCE
lvremove -f $VGPATH/$SNAPNAME
rmdir $SOURCE

# Configure incremental/full counts
duplicity remove-all-but-n-full 4 $TARGET
duplicity remove-all-inc-of-but-n-full 1 $TARGET

Configure the parameters above to suit your environment.  You can use gpg --list-keys to get the 8-digit hexadecimal key ID of the key you’re going to encrypt with.  The folder name in your bucket you use is arbitrary, but you should only use one folder for one Duplicity target.  The 10G LV snap size can be adjusted to suit your environment, but it must be large enough to hold all changes made while the backup is running.  I picked 10Gb, because that seems OK in my environment.

Obviously this means I need to have 10Gb free in the VG that the libvirt LV lives in.

Retention here will run incrementals each time it’s run, do a full every 3 months, ditch any incrementals for any fulls except the latest one, and keep up to 4 fulls.  With a weekly backup, this will amount to a 12 month recovery window, with a 3-monthly resolution after 3 months, and a weekly resolution less than 3 months.  Tune to suit.  Drop that script in /etc/cron.daily or /etc/cron.weekly to run as required.

Important.  Make sure you can do a restore.  Look at the documentation for duplicity restore for help.

Splunkd High CPU after leap second addition?

Had my alerting system yell at me about high CPU load on my Splunk Free VM;

A bit of examination revealed that it was indeed at abnormally high load average (around 10), although there didn’t appear to be anything wrong.  Then a quick look at dmesg dropped the penny;

Jan 1 10:29:59 splunk kernel: Clock: inserting leap second 23:59:60 UTC

Err.  The high CPU load average started at 10:30am, right when the leap second was added.

A restart of all the services resolved the issue.  Load average is back down to its normal levels.