Shrew Soft Client Under Ubuntu 10.04

August 31st, 2010

This may not help you. But this is what I did to get it working against our OpenBSD isakmpd VPN server. If you’re not using precisely the same configuration we are, this is going to be dead wrong. If you are using ‘Mutual RSA’ authentication, this might be suitable.

We have a nice CGI at work which takes your client hostname and spits out a zip file containing the SSL certs needed, the VPN.VPN site configuration file for a ShrewSoft client and some helper batch scripts. So that all works for Windows. Assuming that you’ve got all those pieces or the local equivalent, and you got Shrew Soft working from Windows, these are the frobs to turn for doing this on Ubuntu 10.04.

Here’s the catch for doing this on Ubuntu 10.04. You can’t do it with the packaged Shrew Soft client (packages named ike*) because that version doesn’t support the PolicyGeneration option you need to set. So uninstall any that you have installed.

Then go grab version 2.1.6-release or newer (depending upon degree of daring) from

http://www.shrew.net/download/ike

Compile it. This will require you to install the cmake, build-essential, flex, bison and libssl-dev packages. Maybe some others, but those are the big ones. The README.TXT in the ike source is helpful.

Import your VPN.VPN configuration.

Copy the contents of certs into ~/.ike/certs so the agent can find them.

Start  ‘iked’ by running it with sudo. Add the -F switch if you want to keep it foregrounded. (Until you’ve got it working, you want to keep it foregrounded.)

Start ‘ikea’. Edit your imported connection. Make these configuration changes:

  • Name Resolution tab: uncheck Obtain Automatically, add a DNS server/suffix. There’s possibly something wrong with the  handling of DHCP, this should just work. I set a single DNS server and search domain explicitly and that worked well enough.
  • Authentication tab, Remote Identity subtab: change Identification type to Fully Qualified Domain Name, FQDN String is whatever your VPN endpoint thinks its name is. This was ipv4-address in my configuration, the iked log output helped me fix this one. If you see messages from iked about it getting fqdn when it wanted ipv4 or vice-versa, this tab is where you fix expectations.
  • Policy Tab, Policy Generation: shared. This is the connection option which was key and before 2.1.6, unavailable. The docs say this allows it to emulate some kind of wacky Cisco mode. I guess that’s what we need.

You may need to pound on various rp_filter sysctls but I’m not convinced that did anything in my case. If you packet capture and see reply traffic coming to you but never seeming to be received by your running clients, it may well be you need to set some rp_filter sysctl or other to 0.

What Have You Done Lately?

August 26th, 2010

Not blogged, not read novels, not taken pictures, not slept, not baked.

But I did convert two teams from subversion to mercurial.

Oh, and we’re buying a house.

Phoneblogged

June 20th, 2010

image

This is simply a test of my ability to thumb type.

Space Cops

June 12th, 2010

Shannon Prickett,
June 12, 2010
Rating: 2 out of 3

Sketch a Venn diagram. One circle is HARD SF by which I mean scientifically plausible (or almost) fiction. A second circle is SPACE OPERA by which I mean dramatic or melodramatic adventures in the vast spaces between worlds. The third and last circle is POLICE PROCEDURAL by which I mean a story focusing on the actions of law enforcement meant to capture the (sometimes tedious) details of their work. At the space where those three circles overlap is Alastair Reynolds’s book The Prefect.

If you are not into all of those, this book is going to misfire for you, in all likelihood. Fortunately for me, this is my sweet spot. The SF isn’t all that hard compared to some of his other books, but it was sufficiently robust; the opera isn’t all that melodramatic but it did have a larger than life threat, moments of emotional irony and loud bombastic characters; the procedural is mostly field work and demonstrating adaptability. These all seemed to me to be compromises meant to not push the novel too far out of the overlap in any one direction. Best of all, it works.

In a future where a distributed society (humans, uplifted warpigs, post digital sentience) takes voting Very Seriously Indeed, the police agency we follow about in this narrative are the election prefects. They investigate voting irregularities, enforce the will of the people if needed, and defend the polity from disruptions, both internal and external. It’s structured in the way I expect an Alastair Reynolds book to be, with a progressively exposed and escalating threat, likable but flawed protagonists, gradual exposure of underpinnings like an onion being peeled.

Now, I’m reading this in the context of someone who’s read other Alastair Reynolds books but it seems to me that if you have never read his stuff, this book is probably an accessible if meaty jumping on point. This book would lead fans of N!C!I!S! or CSI:MiamYEEEEEEEEAAAAAAAAAH or Law & Order: Criminally Ingenious into Reynolds’s SF universe following the thread of the Great Detective protagonist. Tom Dreyfus, in this book, is Goren, he’s Gibbs, he’s Horatio, he’s Sherlock, he’s the messed up, twisted up inside, too sharp for his own good, driven by circumstance, caught in the spider’s web, hero.

Back by popular request, my book review lists:

    People who might like this book

  • Fans of Police Procedural TV shows
  • SF readers looking for a meaty satisfying entry to an intricate universe
  • People who can’t WAIT to be digitized and give up their bodies to gain awesome super powers
  • People who love democracy. Really really love democracy.
    People who might not like this book

  • People looking for something shorter, like the OED
  • People who are looking for a book exploring the complex inner life of a troubled girl who never goes anywhere or does anything
  • People who are interested in the tactical games played in societies with strict social mores in order to gain or avoid an arranged marriage to a Person of Influence

But Mine Will Be Round Part the 318th

May 28th, 2010

Since I’m finally getting down to grinding through my email I thought “wouldn’t it be cool to see visible evidence of my progress?” Then after I’d procrastinated for quite a while on the munin plugin repository looking at many plugins which were almost but not quite what I wanted, I decided to cement my stalling by writing my own. I even took the time to make it a wildcard plugin, though it is highly tailored to my email setup. (In short, it uses Maildir structure and my mailboxes tend to have a goofy set of period-delimited names where only the suffix is material.)

#!/bin/bash

# mailbox_ by Shannon Prickett 

MAILUSER=${0##*mailbox_}

case $1 in
    config)
        cat << 'EOT'
graph_title Emails By Folder
graph_vlabel Emails
graph_category mail
graph_args --base 1000 -l 0
graph_scale no
graph_info The count of emails in the current and new email folders.
EOT
        ;;
esac

TARGET="/home/${MAILUSER}/Maildir"
for folder in `ls -a ${TARGET}`
do
    if [ -d ${TARGET}/$folder/cur ]; then
        SHORTNAME=$(echo ${folder} | cut -d. -f 3 -)
        if [ -z ${SHORTNAME} ]; then
            SHORTNAME=INBOX
        fi
        case $1 in
            config)
                echo "${SHORTNAME}.label ${SHORTNAME}"
                ;;
            *)
                CURCOUNT=$(ls ${TARGET}/$folder/cur | wc -l)
                NEWCOUNT=$(ls ${TARGET}/$folder/new | wc -l)
                COUNT=$((${CURCOUNT}+${NEWCOUNT}))
                echo "${SHORTNAME}.value ${COUNT}"
                ;;
        esac
    fi
done

UPDATED: now it sums read and unread and has a typo fixed.

Overengineering is Bestengineering

May 27th, 2010

As you may know, I’m a big fan of what I’d consider the JWZ PSA style of data backup for my home systems (none of them are really pretentious enough to even be considered servers). For a while I’ve been continuing to expand on the list of –exclude options I’d been passing to rsync. But no more! At long last my tolerance for rambling rsync options was exhausted.

So of course I turned it into a script. This script.


#!/bin/bash

EXCLUDES=`mktemp --tmpdir=/tmp rsyncex.XXXXXX`
RSYNCFLAGS="-q"

while getopts "v" Option
do
case $Option in
v ) RSYNCFLAGS='-v';;
* ) echo "Only know -v for verbose" ;;
esac
done

(
cat <<'EOL'
*.lock
/proc/*
/sys/*
*/tiger/work/*
*/nagios3/spool/*
tmp/*
/tmp/*
/opt/splunk/var/*
/var/www/munin/*
EOL
) > ${EXCLUDES}

# as an idle job if you can
/usr/bin/ionice -c 3 -t \
/usr/bin/rsync -xa ${RSYNCFLAGS} --links \
--exclude-from=${EXCLUDES} --delete / /mnt/backup

rm ${EXCLUDES}

The points at which you would want to modify it for your own use should be obvious, if not the point of why you would want to use it at all.

Spreadsheet Nerdery

March 22nd, 2010

In the unlikely event you ever need a spreadsheet cell to tell you what level someone’s 3rd or 3rd-and-a-half D&D character is based on their experience points, this should do it (in Google Docs Spreadsheet):

=FLOOR( (SQRT(ABS(-1 - (8 * CELL-CONTAINING-XP/1000) ) ) + 1)/2, 1)

You’re welcome.

Feels Like Yesterday

March 17th, 2010

Shannon Prickett,
March 17, 2010

Rating: 3 out of 3

I’ve read the Roger Zelazny novel Lord of Light numerous times. First, as a pre-teen doggedly going to the end of the science fiction section of my public library and reading the books there, beginning with the alphabetically last author and rewinding to the beginning of the alphabet. In my memory, I read them all at least once, then I started going back to re-read my favorites. Lord of Light would have been one of the first, its poetry stuck in my head.

Over the years since then, I’ve read it again. Sometimes after an abyssmal book, to cleanse the palette. Sometimes when I was facing a big decision in my life and wanted an absorbing distraction. Most recently, I read it because it was the Book of Honor at Potlatch 2010. The panel dedicated to discussing the book introduced one of the reasons it was selected: cultural appropriation. That’s one of those hot phrases in recent discussions about writing. If cultural appropriation exists [and JT Stewart made a good case that it or something rather like it does], this novel is an example of it on two levels.

First, Zelazny was neither a Hindu nor a Buddhist, but the setting is constructed from pieces of the Hindu culture and beliefs and the protagonist deploys a scheme with Buddhist trappings.

Second, within the context of the novel, the reason for the Hindu and Buddhist bits are that the characters have deliberately chosen to mine out the useful levers from those cultures and use them to shape the world.  In the clearest terms, they have appropriated those cultures and deployed the likenesses which will motivate people and control their environments.

That was the first surprise for me in the panel discussion, an angle I hadn’t considered of the story, and one which came in with two tines. The second surprise in the panel discussion was learning that most of the panelists did not like the story. Imagine that, an award winning novel, widely read, and most of the people who showed up to talk about it didn’t care for it. Some conceded that they had liked it when first reading it but upon further reflection or re-reading, they liked it less, and sometimes not at all. One panelist didn’t like it when she first read it, until she read more analysis of it and then the book was improved by those alternate interpretations and readings of it.

Which is a long way of saying that hardly anyone there who got to speak agreed with me, about Lord of Light being a worthy and re-readable book, an interesting book, a lyrical book, in short, a good book. So this positive review score I’m giving it is one I give in the face of bold disagreement by others. Which I’m okay with.

The story of the book is told largely through a very long flashback. The protagonist is summoned, literally reincarnated, his atman or soul stuff into a body. When he’s more at home in the body, he remembers his past before he was discorporated and that is the meat of the book.  Eventually we find out how he was unable to keep body and soul together and then there’s a wrap up where he wins the war he’s been fighting for about a century. The value of this story is not in being ignorant of the storyline, but in the prose it’s presented in, the implications of the actions and, as with all Zelazny stories, the things he doesn’t tell us.

I think that last element is what keeps me coming back to Zelazny’s writings; he doesn’t tell the reader everything, he takes the story halfway and then the reader has to step forward to meet it there. If you are a reader who needs everything explained, you will not like Zelazny. But that kind of challenge slash puzzle slash opportunity is exactly the kind of narrative my mind seizes upon and savors. So it is with this work.  We’re given bursts of lush prose and vast empty spaces of implication and incompleteness.

Not to say it’s a flawless work.  There are points which bothered me the first time and still do.  An example would be how  extracting the stored pattern of Sam’s consciousness from the media in which it was stored removes it from that media. Or how that pattern can claim to have experienced consciousness while in the media. But those can be glossed over and forgiven.

Ordinarily I try to wrap up my reviews with lists of people who might and might not like a given work. This review is different, I’m experimenting with hReview markup in response to an article on why book reviews are hard to search for. If you miss those lists, comment and I’ll revise.

Mesh.AM Radio

December 4th, 2009

While I slept last night I thought of a gadget. Here’s the quick pitch:  imagine the portable music player you travel with seeking out more music of the kind you like from the people around you, automatically.

First, the disclaimers. Maybe this already exists, I haven’t looked. Maybe you already had this idea and I read about it and forgot I read it. If that’s the case, I apologize.  Because of the way ideas come to me they’re often indistinguishable from memories. This almost certainly couldn’t work in our existing legal framework where creativity and sharing is squashed by big cartels buying legislation and courts fearing innovation as I’m imagining it. That said, here’s some more of my thinking about how it might work.

Second, the mechanics.  The key element of it are the software smarts; it can be bolstered by hardware but I think the kinds of actions the device need to make can’t be solved with hardware alone.  So it could be an application on your Android or other smart phone, on your PDA, your laptop or a dedicated piece of hardware running the application.

Dedicated hardware could  provide Local Area Wireless Network options, such as bluetooth, IR, 802.11s (mesh) and whatever else people can find local peers with.  Otherwise, avahi or another zeroconf on a LAWN connected laptop or even devices wired to a LAN could potentially perform the exploration and exchange.

Each potential participant in the exchange needs to share information about what it seeks and what it has.  It needs to make decisions about whether what it’s being offered meets its seek criteria sufficiently well to attempt a transfer.  It needs to detect and deal with Byzantine faults.  It needs to negotiate a transfer rate with multiple simultaneous partners which won’t saturate itself or its peers.

Here’s what I was imagining an exchange playing out like

  • A: Hi, is someone there?
  • B: Hello, A.  I know protocols purple, green and blue.
  • C: Hello, A.  I know protocols purple, blue and yellow.
  • M: Hello, A.  I know protocols red, orange, yellow, green, blue, indigo, purple and many more!
  • A: B,  let’s switch to protocol green. C.  let’s switch to protocol blue. M, let’s switch to protocol red.
  • B:  Pleased to meet you, A. Do you have any Creative Commons licensed music?
  • C: Pleased to meet you, A.
  • M: Pleased to meet you, A.  Do you have any Windows executables with the DRM removed?
  • A: B, yes, I do.  Do you have any public domain ebooks?  Let’s work out an exchange.
  • A: C, do you have this specific list of public domain ebooks I lack? [List is the subset from B which A is interested in, thus allowing it to use something like bit torrent to transfer parts from each of them both to distribute demand and allow comparison of pieces to verify the content is accurate.]
  • A: M, no I don’t and your question makes me nervous. [A then puts M on a ignore-with-timeout list.]

Some of the things I’m trying to show there is that your device may want to use different protocols with different peers, to avoid collision or because some devices are more capable in some modes; that a device is expected to interact in various ways, by making requests, responding to requests, prioritizing tasks.  There’s some thinking about detecting suspicious peers and treating these LAWN gnomes as a tiny cloud where nodes would become eventually consistent, so that B and C and M have all been neighbors long enough that B and C have nothing to say to each other when A arrives, they’ve already reached an equilibrium and have exchanged all the files they care to (until A starts to provide B with new music at which point B might tell C ‘let us resume our earlier negotiations, I have something new to trade’) and neither B nor C is talking to M, having long since moved this obvious commercial software troll on an ignore-no-timeout list.  Oh, and it’s not just music being exchanged, though that’s the sexiest use case.  If your ebook reader built up your library based on books you already had, probably no one would hate that.

Third, a stab at addressing some concerns I raised to myself and then answered. In terms of evaluating if a given music offer matches seek criteria, I’m pretty sure data from last.fm could be very handy. It would perhaps be possible to build a similar dataset and heuristics around ebooks or other mobile data usage.  You’d tend to be a lot more successful in finding acceptable offers in places where you tend to be around people you share tastes with.  Like going to a show by a band makes it more likely you’d find acceptable the music on offer from the devices of the people around you over the offerings you’d find standing in line at a grocery store. It seems impossible to me to avoid copyright infringement even if you hardcode into the device only accepting content which is appropriately licensed because it could doubtlessly be jailbroken or its peers could conspire, but maybe raising the bar on doing so would mitigate some of the risk of inadvertant exposure (since it’s not a protection from being sued into poverty, the risk never goes away entirely).

Puppet for Absolute Beginners

November 19th, 2009

This post is addressed to people who more or less are in the situation I was in two months ago.  Notably:

  1. you manage an environment which is mostly Ubuntu 8.04.mumble LTS
  2. you know enough Ruby to recognize it when you see it
  3. you want to start using Puppet to manage your environment

I wrote this post because you’ll run into problems trying to use the probably otherwise fine examples in the documentation, through a combination of puppet being a moving target and LTS being a static environment.

First, if you get inexplicable errors about certificates while configuring and tweaking and experimenting, shut down the puppetmasterd on the master server, kill any puppet process on the client machine, and remove the contents of /var/lib/puppet/ssl on both systems involved.  This seems especially common if you’re doing any hostname tomfoolery.

Second, here’s what a very basic puppet.conf file might look like:

# This file is managed in //depot/ops/puppet/
[main]
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$vardir/lib/facter
pluginsync=true
certname=mask.play

[puppetmasterd]
templatedir=/var/lib/puppet/templates
server=mask.play

The only real changes from the shipped default are an explicit certname and server value. It might not be obvious what I’ve set them to, here, but that’s a server name (on an internal only TLD). On the client machines you won’t need either of those set and you can squelch some noise by getting rid of the pluginsync= option.  In my environment, because of DNS tomfoolery, I had to explicitly make a record in /etc/hosts for the puppetmasterd’s server on the client systems, telling them to look for puppet at a specific address.

To get started setting up puppet, refer to the Simplest Puppet Recipe page specifically Step four: Run a client.  What you’re wanting to achieve here is an introduction between the puppet client node and the puppetmasterd server.  You’ll see your success or failure in /var/log/daemon.log on both systems.  Now about the rest of that Simplest Puppet Recipe page.

If you read it in conjunction with the Puppet Best Practices page, you may get confused like I got confused, especially if you’re a congruent kind of dumb.  After going round and round, here’s what my puppet tree looks like in SCM and implicitly on the puppetmasterd server:

puppet
puppet/services
puppet/manifests
puppet/plugins
puppet/notes
puppet/clients
puppet/modules
puppet/modules/appserver
puppet/modules/appserver/manifests
puppet/modules/curl
puppet/modules/curl/manifests
puppet/modules/snmpd
puppet/modules/snmpd/manifests
puppet/modules/snmpd/files
puppet/modules/user
puppet/modules/screen
puppet/modules/screen/manifests
puppet/modules/ntp
puppet/modules/ntp/manifests
puppet/modules/ntp/files
puppet/modules/sudo
puppet/modules/sudo/manifests
puppet/modules/sudo/files
puppet/modules/bacula
puppet/modules/bacula/templates
puppet/modules/bacula/manifests
puppet/tools

You can see that most of the action is in puppet/modules.  Specifically, I would have started (if I knew then what I know now) with puppet/modules/sudo.  Notice two subdirectories under that.  The puppet/modules/sudo/files directory has in it the sudoers file we want to deploy to client systems.  The puppet/modules/sudo/manifests directory has in it the init.pp file.  For reference, here’s what my version of their simplest recipe looks like:

# /etc/puppet/modules/sudo/manifests/init.pp

class sudo {
	package { sudo: ensure => latest }

	file {
		"/etc/sudoers":
			owner => "root",
			group => "root",
			mode  => 440,
			source => "puppet:///sudo/sudoers",
			require => Package["sudo"];

		"/usr/bin/sudo":
			owner => "root",
			group => "root",
			mode  => 4755;
    }
}

As I recall, the permissions on Ubuntu 8.04 are different from those in the example and my choice of layout and file placement dictated the source parameter.  Speaking of file placement, the fileserver.conf I use:

[files]
  path /etc/puppet/modules/*/files
  allow *.playsomething.com
  allow *.play

Upon shutdown, puppetmasterd complains bitterly about that asterisk but it seems to otherwise work. I surmise I could well enumerate all the paths explicitly and shut up that bit of noise but it hasn’t seemed worth it, to date. The default fileserver.conf that ships in Ubuntu 8.04 expects you to serve files from /etc/puppet/files but that seems to conflict with the Puppet Best Practices so I went with the fancier place.

So under puppet/manifests are where your rules for which modules get applied to which systems.  Mine has three files, modules.pp, nodes.pp and site.pp.  They look like this:

# /etc/puppet/manifests/modules.pp
# managed from //depot/ops/puppet/manifests/modules.pp

import "sudo"

and

# /etc/puppet/manifests/nodes.pp
# managed at //depot/ops/puppet/manifests/nodes.pp

node basenode {
	include curl
	include ntp
	include screen
	include snmpd
	include sudo
}

node 'exhaust', 'gasket' inherits basenode {
	include bacula
}

node 'manifold', 'header' inherits basenode {
	include appserver
}

and

# /etc/puppet/manifests/site.pp

import "modules"
import "nodes"

filebucket { main: server => 'mask.play' }

File { backup => main }
Exec { path => "/usr/bin:/usr/sbin/:/bin:/sbin" }

Package {
	provider => $operatingsystem ? {
		debian	 	=> aptitude,
		openbsd		=> freebsd,
	}
}

If you can read between the lines there, puppet reads the site.pp file. That tells it, among other things, to read the modules.pp and nodes.pp files. The openbsd operatingsystem part is untested so don’t count on it, but that Ubuntu systems identify as debian is true and somewhat important to know.

The nodes.pp file is where all the action happens.  I’ve got five modules there defined as necessary for all kinds of systems; your environment almost certainly varies.  Then there are two kinds of nodes which inherit from basenode and add another module; each of those child node types names two servers which are that kind of a node, and includes a different module.  In this case, exhaust, gasket, manifold and header are all names of servers.

You can probably generalize from this to get a boost on rolling out Puppet.  Each of the things you want a server or set of similar servers to do is a module in puppet/modules/NAME/ with manifests/init.pp telling puppet all the rules of that module, and files/WHATEVER containing any files which should be pushed as part of enforcing that module.  You may have noticed that my puppet/modules/bacula doesn’t have a files subdirectory, but does have a templates subdirectory.

Here’s what the init.pp for bacula looks like:

# /etc/puppet/modules/bacula/manifests/init.pp

class bacula {

	package { bacula-client: ensure => latest }

    file {
		"/etc/bacula/bacula-fd.conf":
			owner => "root",
			group => "root",
			mode  => 640,
			content => template("bacula/bacula-fd.conf.erb"),
			require => Package["bacula-client"];

		"/usr/sbin/bacula-fd":
			owner => "root",
			group => "root",
			mode  => 755
    }

	exec {
		"/etc/init.d/bacula-fd restart":
			subscribe 	=> File["/etc/bacula/bacula-fd.conf"],
			refreshonly	=> true
	}
}

I’m providing it not because it’s the most awesome use of templates ever but because I found using templates very intimidating as a non-Ruby coder, so I had to do a couple shots of tequila before trying to write one. And here’s the puppet/modules/bacula/templates/bacula-fd.conf.erb file:

# /etc/bacula/bacula-fd.conf
# managed from //depot/ops/puppet/modules/bacula/templates/

Director {
	Name = akadi-dir
    Password = "yrmomsaidimthebestlickintown"
}

FileDaemon {
	Name = <%= hostname %>-fd
    FDport = 9102
	WorkingDirectory = /var/lib/bacula
	Pid Directory = /var/run/bacula
	Maximum Concurrent Jobs = 20
}

Messages {
	Name = Standard
    director = akadi-dir = all, !skipped, !restored
}

It’s a tiny substitution, just customizing the bacula-fd.conf file on the client systems to name themselves distinctly.  The point being I just took a bacula-fd.conf, figuring out the piece which needs to be different on different systems, and substituted a variable to differentiate them.  It’s easy.  There, I just saved you $7 on tequila.

Oh, so the last detail of absolute square one stuff.  Getting the important bits from your SCM workspace to the puppetmasterd workspace.  In our environment, we use a lot of Makefiles to deploy files from SCM so that’s what I did here.  It’s dead-simple but just in case you need a nudge, it looks like this:

# Makefile for puppetmasterd configuration.
# binder@manjusri.org takes the blame for this one

mask.push:
	rsync -av --delete --exclude '*/README' --exclude 'Makefile' .  root@mask.play:/etc/puppet/

It’s just an invocation of rsync which blows away any local crap, leaves the README and Makefile files in the SCM workspace, and copies everything else into the /etc/puppet directory on the puppetmasterd server. Reloading of the daemon is done manually at this point but you could always modify this Makefile to reload your configuration once you push.

OK, that’s it.  That’s everything I think I know about Puppet which I didn’t know two months ago.

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...