So, the other week I told you about the improvements to my access logging tool, which will now keep a user by user track of account activity.

This tool also makes a call to a GeoIP lookup hook, but until now remained unanswered. So, I wrote a quick tool that implements this GeoIP lookup hook using PHP’s built in geoip functions.

Once installed and configured (and the appropriate GeoIP database set up), this plugin will respond to any geoip/lookup event requests by looking up ['ip' => '....'] and returning the a country.

If installed along side LoginSyslog, you should start seeing the country listed along side the IP address!

» Visit the project on Github...

I’ve previously documented how I’ve previously used Known to track system events generated by various pieces of hardware and various processes within my (and my client) infrastructure.

Like many, I use a UPS to keep my servers from uncontrolled shutdowns, and potential data loss, during the thankfully rare (but still more common than I’d like) power outages.

Both my UPS’ are made by APC, and are monitored by a small demon called apcupsd. This demon monitors the UPS and will report on its status, from obvious things like “lost power” and “power returned”, but also potentially more important things like “battery needs replacing”.

While some events do trigger an email, other messages are written to the console using the wall command, so are less useful on headless systems. Thankfully, modifying the script is fairly straightforward.

Setting up your script

First, set your script as you did for nagios. Create an account from within your Known install, and then grab its API key, then put it in a wrapping script.

#!/bin/bash

PATH=/path/to/BashKnown:"${PATH}"

status.sh https://my.status.server apc *YOURAPICODE* >/dev/null

exit 0

I need to Pee

The next step is to modify /etc/apccontrol to call your wrapper script.

I wanted to maintain the existing ‘post to wall’ functionality as well as posting to my status page. To do this, you need to replace the definition for WALL at the top of the script, and split the pipe between two executables.

To do this you need a command called pee, which is the pipe version of tee, and is available in the moreutils package on debian based systems. So, apt-get install moreutils.

Change:

WALL=wall

To:

WALL="pee 'wall' '/path/to/wrapperscript.sh'"

Testing

To test, you can run apccontrol directly, although obviously you should be careful which command you run, as some commands fire other scripts.

I tested by firing:

./apccontrol commfailure

Happy hacking!

I’m increasingly of the opinion, as you might have guessed from reading past articles on my blog, that if you can encrypt a thing, you must encrypt a thing, if it’s sent over the internet especially  after adding Google Analytics to WordPress.

So, since more crypto use is always a good thing, I wanted to find a way to encrypt email sent from my WordPress blog. Specifically, I wanted to encrypt my “hire me” contact form, which is emailed to me and quite often contains sensitive information. Sometimes clients are quite forthcoming in their initial messages, so I think it’s professional to protect that.

Although the contact form is the primary use case, this code should work for any email (with only one recipient) sent via wordpress’ internal code, providing the address has a valid (non expired encrypting) public key on file. Adding a key is, in this code, a manual process, however it’d be trivial to extend the code to chat to a key server.

So, anyway, you need to find the functions.php for your theme (I wanted to do this quickly, so I didn’t write a plugin), and put in the following code.

You’ll also need to install the gnupg extension for php. If you’re on debian, this should just be a matter of apt-get install php5-gnupg.

/**
Recursively find a non-expired encryption key for a given address.
*/
function find_encryption_key($keys) {

    $fingerprint = null;
    foreach ($keys as $k) {
        
        if ((!$k['expired'])  && ($k['can_encrypt']) && (!$fingerprint) && (isset($k['fingerprint']))) {
            $fingerprint = $k['fingerprint'];
        }
        
        if (!$fingerprint && isset($k['subkeys'])) {
            $fingerprint = find_encryption_key($k['subkeys']);
        }
    }
    
    return $fingerprint;
}

/**
Encrypt $message for delivery to $address
*/
function encryptto($message, $address) {
    
    $gpg = new gnupg();
    
    if (is_array($address)) {
        $address = $address[0];
    }
    
    // Find keys
    $keys = $gpg->keyinfo($address);
    if ($keys) {
        $fingerprint = find_encryption_key($keys);

        $gpg->addencryptkey($fingerprint);
        
        return $gpg->encrypt($message);
    }
    
    return false;
}

// Attempt to send encrypted email.
add_filter( 'wp_mail', function ($args) {
    $new_wp_mail = array(
        'to'          => $args['to'],
        'subject'     => $args['subject'],
        'message'     => $args['message'],
        'headers'     => $args['headers'],
        'attachments' => $args['attachments'],
    );
    
    if ($encrypt = encryptto($args['message'], $args['to'])) {
        $new_wp_mail['message'] = $encrypt;
    }
    
    return $new_wp_mail;
}, 1);

This code will try and find a key for the to address and attempt PGP encryption.

It’s not perfect, for example, if encryption fails for whatever reason, the message will be sent in the clear. I did it this way since not everyone’s public key will be on file, but I still wanted the email sent, so this is probably a good thing.

Also, for jetpack contact forms & comments at least, the code will fire the clear message text to Akismet, if you have the plugin installed. The latest version of Akismet will default to sending the message over TLS, so this isn’t the end of the world if you’re worried about passive monitoring.

Anyway, the more encrypted traffic on the net the better. Have fun!