macOS: ‘dig’ vs. ‘dscacheutil’ while using split DNS with Viscosity VPN client

If you’re using Viscosity VPN client on Mac, and have enabled the split DNS for the VPN domains, `dig` doesn’t work quite as someone familiar with Linux/*NIX would expect. This is because Apple has replaced the traditional resolver on macOS with something “more advanced”. Granted, it handles the split DNS gracefully, but as a result, using `dig` for the VPN domains without defining a DNS server for a query doesn’t produce any result even though resolution works otherwise in macOS.

This works:

~ dig +short random.ac a
52.4.179.30

But this does not:

~ dig +short internal.ville.sh a

However, this does:

~ dscacheutil -q host -a name internal.ville.sh
name: internal.ville.sh
ip_address: 10.50.50.10

To make things easier, I have created the following `zsh` alias:

alias dnsquery='dscacheutil -q host -a name'

However, I’ve forgotten this a few times when some time has passed since the last encounter with dig on internal domains. And then time goes down the drain trying to figure out if something is wrong with the DNS.. but it’s working all along! So I added a reminder for myself in form of another `zsh` alias:

dig() { echo && echo -e '\033[0;97m\033[41m Remember, this is a Mac! Use "dnsquery" instead! \033[0m' && /usr/bin/dig $@ } #macOS

And so:

~ dig +short internal.ville.sh a

 Remember, this is a Mac! Use "dnsquery" instead!

#oh right! :-)

~ dnsquery internal.ville.sh
name: internal.ville.sh
ip_address: 10.50.50.10

A Simple AWS CLI KMS encrypt/decrypt example

This would have saved me an hour or two, so I’m posting it here for posterity. 🙂 Maybe it will save some time for someone else.

A quick example of how to use the AWS CLI to encrypt a file using a KMS with a key identified by the `key-id`. The output is saved into 76-column wrapped ASCII-armored file, and then decrypt the same back into cleartext. I couldn’t find a way to column-wrap the output from `aws kms encrypt`, so the base64 encoding is first undone, and then re-applied with the [default] column width of 76.

Replace the below fake `key-id` with your own (obviously 🙂 ) that your AWS credentials have access to. For this to work, you have to have awscli installed and configured (run `aws configure` after you’ve installed `awscli`).

** NOTE: On macOS, you have to use capital `-D` with `base64` to decrypt.

First, to encrypt the contents of a file, and then output the decrypted content back into a file, use the following format:

aws kms encrypt --key-id 3c436c82-eabe-4b58-996f-6ca3f808f237 --plaintext fileb://my-secret-key.pem --query CiphertextBlob --output text | base64 -d | base64 -w 76 > encrypted.asc

aws kms decrypt --ciphertext-blob fileb://<(cat encrypted.asc | base64 -d) --output text --query Plaintext | base64 -d > decrypted.txt

Then, to encrypt/decrypt a string without first saving it into a file (who came up with the decryption format?!). This works in `bash`, `zsh`, and alike (`ksh`..?):

aws kms encrypt --key-id 3c436c82-eabe-4b58-996f-6ca3f808f237 --plaintext 'Secret message' --query CiphertextBlob --output text

aws kms decrypt --ciphertext-blob fileb://<(echo 'AQECAHiuImqexTQGWMAtOjKMcH5UIxXuSZ5WSGx3WKO+vsUI3AAAAKIwgZ8GCSqGSIb3DQEHBqCBkTCBjgIBADCBiAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAwT3cwVGtUYHz02irsCARCAW8a4TP7pL+inl7Je7x1xEr84Q4lN11t3dNFvycpMZALe185DYow4i1GLaJnJnB7g6V1ZaiB+b+Diap/5auM/K3bjLmcTq0molBnn2TG3r0uj70lP0FSQP+XwQ+8=' | base64 -d) --output text --query Plaintext | base64 -d

Finally, if you want to enter the encrypted content into a JSON structure, simply leave the `base64` undo/redo out, and change the output type to JSON, like so:

aws kms encrypt --key-id 3c436c82-eabe-4b58-996f-6ca3f808f237 --plaintext fileb://my-secret-key.pem --query CiphertextBlob --output json

Without redirection both the encrypt and decrypt commands output to standard output (as in the first example).

Improving My Git Workflow

Through various projects I’ve been working on in the last couple of years I’ve been digging deeper into Git. While many of Git’s basic operations are pretty straightforward, for someone getting used to Git it soon becomes apparent that some operations aren’t as simple as one might first expect, especially when using Git on the command line rather than with a GUI client.

I’ll expand on the topic later, but I wanted to create this stub article pointing to the GitHub repo I published a few days ago. It contains my annotated Git aliases (many of which I use as a quick reference as I haven’t yet committed all of them to memory), and a collection of helper scripts, many of which I have written myself, while few others, like git-wtf, I have not, but have included them for convenience. Also check out the README in the repo for alias dependencies and for other favorite Git extensions I frequently use.

Besides the enhanced Git command line, gitk with its visual blame tool (accessible from gitk, and also directly from the command line with gui blame when gitk is installed), Atlassian SourceTree, Scooter Software’s BeyondCompare (for diffs and merges), and tig for repository viewing on the command line are now solidly part of my everyday Git toolkit.

Update 2016-12-26: If you like to use a graphical Git client, be sure to check out the awesome GitKraken (Windows/macOS/Linux, free + pro subscription). Tower is now also available for Windows, but with GitKraken having established itself, it’s now too little too late, especially for the Windows users who previously didn’t have a really good GUI Git client (Atlassian SourceTree is ok, but not really stellar).

OpenVPN with FreeRADIUS: How To Use the CN from the User Cert as the Login Name (i.e. the reverse of “username-as-common-name”)

I recently set up handful of OpenVPN servers to provide access to various LAN and AWS VPC resources. Initially I had just the certificate validation configured, but I felt slightly uneasy about not having a password. Especially in the environments where multiple people need access to a resource, in the event one of them no longer should have access (such as when leaving an organization) the only way to block such user would be to add their cert into the CRL. While that should be done anyway when a user’s privilege needs to be revoked, a password would provide a more immediate and easy way to make such changes.

The next step was to install FreeRADIUS which proved to be a very easy task. I’m initially running it with just text-based back-end and will later add MySQL, perhaps with daloRADIUS GUI to make user administration even easier. On Ubuntu/Debian there is a package “openvpn-auth-radius”, which makes it possible to add FreeRADIUS authentication to OpenVPN server with one simple line:

plugin /usr/lib/openvpn/radiusplugin.so /etc/openvpn/endpoint_server_radiusplugin.conf

Of course, the client side also needs the auth-user-pass statement in their OpenVPN client configuration.

But there is a problem: The user cert can be that of Bob while the login username/password is that of Alice, and the login would still be valid. Apparently I’m not the only one who has thought about this. While I didn’t want to hack the pam auth plugin, the post had enough clues to help creating a simple bash script that sets the username based on the common-name from the validated user’s certificate:

#!/bin/bash

# $1 provides the temp file name provided by OpenVPN
# file has two lines: username and password, as entered by the user.
# We get the username from the user cert's CN (available via an envvar).

export PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"

if [ ! -z ${common_name} ]; then
  username=`echo ${common_name}`
else
  username="-"
fi

if [ ! -z $1 ] && [ -f $1 ]; then
  password=`tail -1 $1`
else
  password="-"
fi

radius_server=localhost
# shared secret for localhost (or your RADIUS server) from /etc/freeradius/
shared_secret="XXXXXXXX"

AUTHCHECK=`cat << EOF | /usr/bin/radclient -s ${radius_server} auth ${shared_secret} | grep approved | tr -d 'n' | tail -c 1
User-Name=${username}
User-Password=${password}
EOF`

if [[ $AUTHCHECK = 1 ]]; then
  exit 0
else
  exit 1
fi

To use this script, simply save it to /etc/openvpn/endpoint_server_radius_auth.sh, make it executable, and edit the file to add the shared secret for the RADIUS server from /etc/freeradius/clients. Finally, add the following lines in your OpenVPN server configuration that already authenticates the users by their certificates:

tmp-dir /dev/shm
auth-user-pass-verify /etc/openvpn/endpoint_server_radius_auth.sh via-file

Now the login name for RADIUS authentication is taken from the CommonName (CN) of the user's certificate and, in fact, the username that the user enters when prompted for auth-user-pass username/password is ignored, only the password is significant.

The bottom line of this script: It utilizes RADIUS to provide a server-side password validation for the certificate's CN. A user can always remove the password protection from their private key, so this approach functions as an extra layer of security while making it easier to quickly revoke user's access to a resource.

Note: For this to work, the CommonName set in user certificates obviously must be a valid RADIUS login name. A user can't modify the CN in their certificate (unless they're NSA since they apparently have access to RSA-keys, too 🙁 ), so they're locked to use that specific username.

Also note that I wrote this script on Ubuntu, and did not necessarily observe portability, so you may need to modify the script some for other platforms. It is primarily intended as an example (although it does work), as finding something like this would have saved me a few hours of work.