Archive for the 'OPSEC' Category


GPG-Encrypting your incoming mail using Postfix and Google Apps

I’ve recently chosen to take more control over my data when it’s stored in the cloud. Some big parts of that data are my email accounts. Like most geeks, I have a few “vanity” domains that I receive email at. Also like most geeks, I host them on Google Apps. So, I’ve decided to encrypt all incoming emails before they get stored on Google’s servers.

I searched around for methods of implementing this, but many used Exim or Procmail. I’m partial to Postfix myself, I like they’re privilege separation model. I was running up blanks, until I stumbled upon This project is a very straightforward filter to GPG encrypt mail if a recipient’s key is locally stored. Getting this operational on Ubuntu was easy.

Creating a mail forwarder

First, I installed Postfix with a blank configuration. Then, to create a basic forwarder configuration I made /etc/postfix/

myhostname = forwarder.DOMAIN.COM
mydomain = localhost
myorigin = $mydomain
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, $mydomain
mynetworks_style = host
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
append_dot_mydomain = no
readme_directory = no
relay_domains = DOMAIN.COM
transport_maps = hash:/etc/postfix/transport

Next I needed to make /etc/postfix/transport:


And due a slight bug in Ubuntu’s blank configuration, I needed to make an aliases db:

echo 'postmaster: root' >> /etc/aliases

Restart Postfix:

service postfix restart

At this point I changed my DNS to point the MX record to this server. I sent a test email to ensure fowarding worked.

Installing the GPG encryption filter

You’ll want to install gpg, then install GPG-Mailgate:

cd /root
hg clone
cd gpg-mailgate

From here I mostly followed the steps from INSTALL, but they’re a bit dated and didn’t quite work for me. Here’s the short version, my apologies for the lazy instructions, make sure you replace the python version below with the version that’s live on your system:

cp -R GnuPG /usr/lib/python2.6/
vi /usr/lib/python2.6/GnuPG/

Above, we need to add “–trust-model always” to the command in line 43. Otherwise GPG throws an error about not trusting the key and fails to encrypt messages.

cp gpg-mailgate.conf.sample /etc/gpg-mailgate.conf
vi /etc/gpg-mailgate.conf

In /etc/gpg-mailgate.conf, modify the domains variable to include all domains you want to encrypt messages for. Then, if you have mail aliases, you’ll probably want to add entries under [keymap] in the format email = longKeyID. Leave keyhome as default.

After this is done, we need to get the public keys we want to use for encryption. We can take advantage of Postfix’s privilege separation here:

adduser -s /bin/false -d /var/gpg -M gpgmap
mkdir -p /var/gpg/.gnupg
chown -R gpgmap /var/gpg
chmod 700 /var/gpg/.gnupg

The next command needs to be repeated for each email address you want to encrypt mails for. If you want an email alias encrypted with a key, use the keymap section of the config file above.

sudo -u gpgmap /usr/bin/gpg --homedir /var/gpg/.gnupg --keyserver hkp:// --search myemail@DOMAIN.COM

Then, we’ll need to tell Postfix to have a filter that calls the external script, and a channel to accept mail from the script after it’s encrypted. The following goes in /etc/postfix/, keep in mind that I’m using a different username than the INSTALL directions do (this part gets a bit wide, you may need to expand your viewing window):

gpg-mailgate    unix    -       n       n       -       -       pipe
        flags= user=gpgmap argv=/usr/local/bin/ inet    n       -       n       -       10      smtpd
        -o content_filter=
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
        -o smtpd_helo_restrictions=
        -o smtpd_client_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks=
        -o smtpd_authorized_xforward_hosts=

And then we tell Postfix to use the filter by running this quick command to add a line to /etc/postfix/

echo 'content_filter = gpg-mailgate' >> /etc/postfix/

Restart Postfix:

service postfix restart

With all that, you should find that a test email sent to the email address you specified ends up in your Google inbox encrypted with your gpg key. This works perfectly with a PGP-capable IMAP client, such as Thunderbird or K-9 Mail on Android.


As an added bonus, I threw together an apparmor profile. If your system uses AppArmor, you can place the following in /etc/apparmor.d/ — keep in mind that you’ll need to match the version of python below with the version used on your system.

#include <tunables/global>

/usr/local/bin/ {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/python>

  /usr/bin/python2.6 ix,
  /usr/include/python2.6/pyconfig.h r,
  /usr/lib/python2.6/GnuPG/__init__.pyc r,
  /usr/local/bin/ r,
  /usr/bin/gpg Cx -> gpg,

  /etc/gpg-mailgate.conf r,
  /etc/default/apport r,
  /tmp/gpg-mailgate.log rw,

  profile gpg {
    #include <abstractions/base>
    #include <abstractions/nameservice>
    /usr/bin/gpg r,

    /var/gpg/.gnupg/* r,
    /var/gpg/.gnupg/.* w,
    /var/gpg/.gnupg/trustdb.gpg w,
    /var/gpg/.gnupg/random_seed wk,

Then just run the following to activate the profile:

aa-enforce /etc/apparmor.d/

I found that I still get one apparmor warning, about it wanting to unlink the GnuPG library, which I thought was odd so I didn’t write a rule for it. If this bothers you, add a ‘d’ beside the ‘r’ for that line. Obviously debugging AppArmor is out of scope for this blog post, but there are plenty of useful resources that are just a Google search away.

Edit: I am not at all confident that this AppArmor profile improves the security of using the gpg-mailgate script. Use at your own risk, etc.

Anyways, there you have it. Now all your mail is encrypted before it hits Google’s server for data mining. There’s probably a double-encryption bug that needs to be worked out, and outgoing mail won’t be stored encrypted, but we can at least regain a little bit of control over the data we store in the cloud.


TextSecure 201

This post is about Whisper SystemsTextSecure app for Android (currently version 0.5.7, available through the market). It’s an encrypted SMS client that supports both local encrypted storage and over-the-wire encryption of messages. Wire encryption is done using a modified version of Off-The-Record (OTR) messaging, in use by Pidgin and Adium chat clients.

This post assumes some knowledge of OTR, and will go through how to take advantage of TextSecure’s security features. While some of these instructions are available through TextSecure’s wiki, I found them to be terse and not quite usable as-is for everyone.

After installing TextSecure, you’ll be prompted to enter a password. This password is used to encrypt your local message database and your keys. It will then generate your keys.

To see your public key, you can go to Settings->View My Identity Key. If you have your address book synchronized with Gmail or Google Apps, highly recommend you create an address book entry for yourself, and go to Settings->Choose Identity, then Settings->Export My Identity Key. This creates an entry in your address book with your public key. The entry is an IM-type entry with key TextSecure-IdentityKey and the value is the base64’d (public) identity key.

For normal operation, you can text as normal. It’s a regular SMS app. However, if your SMS buddy also has TextSecure, this the app will detect it and ask if you’d like to initiate a key exchange. After a successful key exchange, you should see a red lock at the top of your chat window, and a lock beside each sent & received SMS message. This is the equivalent of OTR’s “Unverified” status. It means that the current chat is encrypted, but we’re not sure if there is someone doing a Man-in-the-Middle attack or not.

TextSecure offers a few ways to handle key verification. The simplest is to, from the chat window, select Menu->Secure Session Options->Verify Recipient Identity. This is useful if you have the other person’s identity key in text format. If you are in person, there’s a slightly cooler way to verify: both parties should click Compare, with one of them picking Get My Key Scanned and the other picking Scan their key to compare. This will allow you to scan QR codes to verify. After verification, switch roles so the other person verifies too.

There’s another way to verify identity keys, but it’s slightly more complicated. You’ll recall how we exported our public key into our address book. We can also import from the address book. Go into Google Contacts and find your entry; it should have an entry titled TextSecure-IdentityKey. Copy the base64 text, and send that to the other person through a secure channel: OTR-encrypted chat or PGP-signed mail are good examples of this. Now, taking the other person’s base64’d key, go to their entry in your address book. Click the Add button, and select Instant Messaging. With that new field, pull it down so the left-hand side says Custom, and type in TextSecure-IdentityKey. The right-hand side should be the base64’d text they sent you. Now that you have their key, go back into TextSecure. Go to Settings->Import Contact’s Key and find their address book entry. You’ll be prompted to verify, so compare these numbers against what you’ve got in the message screen. This may seem like a long-way around just to verify, but may be very useful if you use an app such as Bump to transfer address book entries to other people. If someone has given you a base64’d key, and you’re having difficulty importing into the address book, you can manually verify this by issuing a simple *nix command:

echo '<base64 string>' | base64 -d | xxd
echo '<base64 string>' | base64 -d | hexdump -C

(One of my systems had hexdump and not xxd for some reason)

No matter how you verify, you should see a blue lock at the top of the messaging screen when you have a verified key for that person. This is equivalent to Pidgin-OTR’s “Private” designation.

A note for those with multiple devices. You probably don’t want to have multiple identity keys floating around, it gets annoying for verification. My suggestion is to select one of your devices that you want to copy the key from, and use TextSecure’s Export To SD Card feature. Now, on the second (or additional) device, you can copy the exported directory to that device’s sd card, and select Import From SD Card. This will wipe any TextSecure settings on the second device, but will import your private keys, your SMS messages, and your friends’ identity keys. Once these two devices are running, I recommend using the address book for tracking identity keys, so they can be easily imported into both devices.

Finally, a note to my fellow Canadians: Bell Mobility mangles multi-part SMS messages, resulting in broken key exchange messages. TextSecure *will not work* on Bell Mobility.

September 2019
« Jul