Setting Up a Secure Guest Wifi Network

May 10th, 2012 - Brendon Rapp

One of the things we decided that we should add to the Jaguar office was wireless Internet for visitors. We wanted visitors to be able to use wifi to get on the Internet with their laptops and smartphones. At the same time, we wanted this guest network to be separate from our office LAN. We didn’t want users of the guest wifi to have any network access to the internal servers and services we’re running inside the Jaguar office. Based on these requirements, I knew that the answer would lie in the use of routers powered by DD-WRT, the very flexible open-source firmware for wifi routers. I ran into many tutorials how to create a separate VLAN on a DD-WRT router. The issue with these tutorials, for our purposes, is that they assumed that the DD-WRT device was acting as a router. That’s a reasonable assumption for home users, but in our case, our DD-WRT device serves purely as an access point. I did, however, want the guest wifi to behave like a router at the access point level. I did not see a clear way to have our wireless access point still act like an access point for our main wifi network, while acting like a router for the guest VLAN. I imagine there may be a way to bend DD-WRT to make one device be an access point for one VLAN and a full-blown router for another, but that configuration was beyond my level of commitment. My solution to this problem was simply to get a second wireless router, install DD-WRT on it, and make that device power the guest wifi.

Configuration & Restrictions

Even though this is our guest wifi, I still insisted on WPA2 encryption. I’m not at all keen on the idea of broadcasting an open wifi network. It’s not too much to ask of a visitor to type in a simple password.

For maximum compatibility, I set the encryption mode to WPA2 Personal Mixed, which allows older devices with only WPA support to still function. I’m not willing to leave a WEP-encrypted network running 24/7, but in the event that we have someone come in with an old machine that can only do WEP, I can quickly add a virtual interface to the router and enable WEP encryption on that, and shut it down when it’s no longer needed, without interfering with the normal guest wifi setup.

For the WPA2 interface, I set the encryption to TKIP+AES, so devices failing to support AES can fall back to TKIP. And I set the 802.11 mode to Mixed, so B,  G, and N clients can all function. Not the best setup for high performance, but when someone walks in waving around an Orinoco Silver card, it should work.

This was one of my most prized possessions in college.

Given that this was to be our “guest” wifi, there were certain restrictions I wanted enforced:

  • The guest wifi was to be on its own subnet
  • The office network subnet was to be unreachable from the guest wifi
  • A certain level of content filtering was to be enforced
  • Some traffic controls to restrict overly taxing our Internet pipe

First Up, Secure the Device Itself

A router’s only as secure as its admin panel. If someone can get into the admin panel, any security settings administered there are rendered moot. My quick checklist for setting up DD-WRT:

  • Define a strong password for the admin panel
  • Change the admin panel username (which is usually “root” by default) to something else
  • Disable remote administration (usually disabled by default)
  • Disable telnet, enable SSH instead
  • Disable passworded SSH access, use public key authentication instead
  • Ensure SPI firewall is enabled (should be by default)
  • Disable unneeded services
  • Disable unused VPN firewall passthroughs

One thing I’ve learned from using DD-WRT is to not forget to set up SSH access. It comes in handy when something goes wrong with the web panel, especially if you’re maintaining the device from two time zones away, like me. I don’t have SSH set up to accept remote connections, however – instead, I get to it by connecting to the VPN and making myself a local LAN node.

(Important note for SSH access: even if you’ve changed the web panel username from “root” to something else, when connecting by SSH, you will still use “root” for the user). All unneeded services are disabled.

Separate Subnet for Guest Wifi

With a traditional home wifi setup, users plug their cable/DSL/etc modem into the router’s WAN port. For us, our office LAN is the guest wifi’s WAN, so we plug a cable from the wall to the guest router’s WAN port. The router gets a “WAN IP” that is an address on our office LAN. In the router’s DHCP server setup, we define a different subnet for the router’s own network. For the sake of this article, we’ll define 10.10.10.x as our office subnet, and 10.10.20.x as the guest wifi subnet.

Blocking Access to Office LAN

In order to restrict guest wifi clients from being able to reach the office LAN, I defined firewall rules for the guest router that will drop any outbound traffic intended for the office LAN’s subnet.

# Block outbound traffic intended for office LAN
iptables -I FORWARD -d 10.10.10.0/24 -J logdrop

With this rule, the router won’t forward any traffic from client machines to the office LAN. It will, however, still route traffic destined to the Internet through the office LAN’s gateway, which is good, because that’s the way to the Internet.

Coming at the same problem from the other direction, I also added firewall rules to certain internal LAN services to block any traffic coming from the guest wifi subnet. The guest router’s own firewall rule should be sufficient on its own, but it never hurts to add another layer of safety.

Content Filtering

We don’t want our guest wifi becoming Porn & Bittorrent Central. Granted, since it’s an encryption-secured access point, there isn’t a great deal of risk of that, but at the same time, we don’t intend on being overly stingy with the WPA2 key. It seems appropriate to perform a bit of filtering. My solution for this need was to use OpenDNS on the guest wifi, and put the OpenDNS service’s content filtering features to use. In addition to filtering out unwanted content, OpenDNS can also filter out things that are security risks. In the DHCP server settings, I set the three Static DNS entries to OpenDNS servers. In order to prevent users bypassing the OpenDNS filtering by trying to set their own DNS servers, I took a hint from the DD-WRT wiki’s OpenDNS page and enabled a couple of firewall rules that intercept attempts to resolve DNS via different servers:

# Intercept DNS queries to external servers, re-route to local DNS
iptables -t nat -A PREROUTING -i br0 -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)

Don’t Hog Our Pipe

One of the reasons P2P services like Bittorrent can be such a network strain is the sheer number of connections they open. In order to help guard against this on our guest wifi, I’ve added a couple of connection limiting rules to the firewall script:

iptables -I FORWARD -p tcp -s 10.10.20.0/24 -m connlimit --connlimit-above 50 -j DROP 
iptables -I FORWARD -p ! tcp -s 10.10.20.0/24 -m connlimit --connlimit-above 25 -j DROP

These rules drop any additional TCP connections a client tries to make above 50, or 25 for non-TCP connections. Those numbers should be high enough to not as to interfere with any non-P2P use, but will prevent a single P2P peer from flooding the device with open connections.

There is much more that can be done to restrict excessive wifi usage, but that is a deep, dark rabbit hole, and well beyond the needs of our own use case.

Up and Running

One could easily take things even further. There are numerous pieces of software for setting up public wifi points. Some are even open source and included in DD-WRT, like Chillispot. DD-WRT also provides features like remote logging and limiting access to certain times of day, which I left for possible future exploration. For now, though, I’m happy with the above setup. DD-WRT’s capability of letting users define iptables rules is a very powerful feature, and a big reason why I insist on using wireless access point that are well-supported by DD-WRT.

Devise emails using incorrect From: address in Rails 3

March 28th, 2012 - Brendon Rapp

We encountered an issue recently with Devise’s password reset emails. The sender address on the emails appeared as “sender@debian” rather than “sender@ourdomain.com”, despite the fact that we had configured Devise to use a specific address:

# config/initializers/devise.rb
Devise.setup do |config|
(...)
  config.mailer_sender = "Sender Name <sender@ourdomain.com>"
(...)
end

Interestingly, we did not have this issue with any other emails sent by the application, only the ones generated by Devise.

The server running this app is a Debian 6 (“squeeze”) box, running Sendmail.

The problem was a setting at the bottom of the Sendmail configuration file (/etc/mail/sendmail.mc).

The final lines of this file, before modification, were:

dnl # Masquerading options
FEATURE(`always_add_domain')dnl
MASQUERADE_AS(`debian')dnl
FEATURE(`allmasquerade')dnl
FEATURE(`masquerade_envelope')dnl

This is the source of the “@debian” domain that was being used instead of the one we set in the application. For a simple fix, we just changed the MASQUERADE_AS setting to match the domain we wished to send from:

dnl # Masquerading options
MASQUERADE_AS(`ourdomain.com')dnl

With that, the Devise mails finally matched our application’s domain.

The Basics of iPhone Security

January 5th, 2012 - Brendon Rapp

The iPhone is the most popular smartphone in the Jaguar office. For me, the bandwagon-jumping point was the iPhone 4, with the 300+ dpi screen and the A4 CPU that made for one of the first smartphones that was sufficiently powerful (IMO) to actually run its OS and apps well.

With many of us relying more on our iPhones for Serious Business, the question of security arises. Apple has implemented some security measures into the iPhone, and continue to make small but steady improvements, as the iPhone sneaks further and further into Corporate America. While the iPhone isn’t quite at BlackBerry level of security yet, there are some important features that everyone should be taking advantage of.

The Bare Minimum Basics

1. Enable Auto-Lock and Passcode Lock
The one step you absolutely, positively must take with your iPhone is enabling the auto-lock and passcode lock functions.

Auto-Lock locks your phone (the same action as pressing the “sleep” button on the top of the phone) after X minutes of inactivity.

Passcode Lock requires users to enter a passcode in order to unlock a locked phone.

The point of these features is to try and ensure that if your phone is lost or stolen, the device will be in a locked and password-protected state by whomever took or found it. This is essential in order to protect your data.

2. Enable Find My iPhone
Find My iPhone gives you the ability to track a lost phone from a computer or from another iOS device. It can help greatly in the recovery of a stolen device.

This used to be a feature one would have to buy from Apple as part of the MobileMe service, but it is now part of the free iCloud service that replaced MobileMe.

Find My iPhone gives you the ability to remotely lock your phone, or even wipe its data. It provides a way to make the iPhone play a sound (even if it’s set to silent) in order to help you locate it when you’re close to the GPS position. And, in the event that the phone is found by an honest person, you can make a message display on the phone to tell the person how they can return the phone to you.

Tracking down a stolen phone using Find My iPhone has been known to make people feel like Batman.

3. Keep iOS Up to Date
iOS is the phone’s operating system. As a complex piece of software, it is often updated in order to fix security issues. It is important to make sure your phone’s software stays up-to-date, so any newly-discovered security holes are closed.

iOS 5 update notification badge

If your phone is running iOS 5.0 or newer, you can do these updates directly from the phone via Wifi. When a new update is available, you’ll see a number badge on the Settings app. Enter the Settings app and go to General > Software Update, and you’ll be able to update.

If you’re on a version of iOS older than 5.0, updates have to be performed by plugging the phone into a computer with iTunes. I highly recommend updating such a phone right away, in order to get current with iOS 5, if for no other reason than to make future security updates easier to install.

4. Backup Your Phone
One of the most important features of the iPhone is the ability to generate backups of the phone’s data, which can be used at a later time to restore the phone.

Some of the security features here involve wiping the phone’s data to prevent data theft in the event of a lost or stolen phone. If you recover the phone, however, how do you get the data back?

The answer is in backups. Before iOS 5, backups were performed entirely by connecting the phone over USB to a computer, and creating the backup via iTunes. Now, users have the option of backing up their phones to iCloud for free, removing the need to tether the phone to a computer. This is a great feature for the large percentage of iPhone users that never plug their phone into their computers.

iCloud provides an easy way to backup iOS devices

iCloud gives you 5GB of free backup space. If this isn’t enough for your phone, you can either buy more space, or selectively exclude applications from your backup (the important stuff – your accounts, settings, etc, are always included, and take up a rather trivial amount of space themselves).

Short of that, one can still connect to their personal computer and iTunes to perform backups. Since iOS 5.0, these backups can be performed over Wifi instead of USB, making it much more convenient.

At any rate, backups are essential, whether it’s through iCloud or your computer’s iTunes installation.

A Step Further

1. Disable “Simple Passcode” on Passcode Lock
By default, Passcode Lock enables the “Simple Passcode” feature, which makes passcodes a 4-digit PIN-number style code.

By disabling this, you can use the full iOS keyboard to define a true password. This is much more secure than a 4-digit code.

2. Set Auto-Lock and Passcode Lock’s “Require Passcode” Times As Short As You Can Stand
It’s important that a would-be thief never get their hands on your phone in an unlocked state. By having the phone auto-lock and require a passcode, you can help ensure that anyone besides you who gets your phone will find it in a locked and passcode-protected state.

However, there is a trade-off between security and usability here. Many people don’t want to have to enter their passcode again when they were just using their phone 30 seconds earlier. At the same time, having the phone wait an hour before requiring a password is too large of a window for someone to steal and begin using the phone.

One thing to understand is how the two timers work. Auto Lock’s timer begins from the moment you stop using your phone. Passcode Lock’s timer begins from the moment the phone locks. So, if your Auto Lock is set to 3 minutes, and Passcode Lock’s “Require Password” timer is set to 5 minutes, it will take a total of 8 minutes from the moment you stop using your phone for the phone to be in a locked & passcode protected state.

As of iOS 5, Auto Lock’s timers options are each minute from 1 to 5 minutes, while Passcode Lock’s are immediate, 1 minute, 5 minutes, 15 minutes, and 1 hour. In the past, there were much longer timers available, but Apple is nudging users towards more secure options.

In my opinion, it should take less than 10 minutes of inactivity for your phone to be passcode locked. So, combining a 5 minute Passcode Lock timer with anywhere from a 1-5 minute timer for Auto Lock will get you there. For the more security conscious, Passcode Lock can be set to 1 minute or Immediately, along with a sufficiently short Auto Lock time.

3. Disable Siri on Lock Screen
This only applies to phones with Siri (as of this writing, the iPhone 4S only, but undoubtably all iPhones to follow). If your phone has Siri, by default it can be used even if the phone is locked. This is a convenience, but it allows a thief to make use of the phone even while it’s locked.

To disable this, flip Siri to “Off” in the Passcode Lock menu:

This will prevent anyone from being able to use Siri without unlocking the phone.

4. Get a Smudge-Resistent Screen Protector
Security researchers have noticed that one can often deduce a lot about a phone’s most recent use based on the finger smudges left behind on screens (see paper: Smudge Attacks on Smartphone Touch Screens).

This is particularly true with simple passcode unlocks (another reason to disable “Simple Passcode” and use a keyboard-types password instead). But in general, smudges are information left behind that an attacker could use to aid in an attack on the phone’s security.

Certain screen protectors are smudge resistent, reducing the information left behind by finger smudges.

OtterBox Defender. Your iPhone won't break even if you bean someone in the head with it.

5. Get a Protective Case
Buying a good protective case is an important safety measure for keeping your iPhone intact. In a situation where you are trying to track down a lost or stolen phone, it also is a benefit in that the relative uniqueness of your case would make the phone more instantly recognizable from all the bare naked iPhones out there.

A thief could always remove the phone from the case, but in the event that the case is left intact, it makes for an easier positive ID. And certain cases, like the OtterBox Defender, take some effort to get off, if you’ve never dealt with them before.

Hardcore Security

1. Enable “Erase My Data” to Wipe Phone After Too Many Failed Login Attempts
A Passcode Lock will help keep thieves from being able to get into a stolen phone, but given sufficient time, a passcode (especially a Simple Passcode) can be broken. The “Erase My Data” feature defends against this, by automatically wiping the phone’s data after 10 failed passcode attempts.

It’s important to note that one cannot make 10 failed attempts all at once. After a few failed attempts, the phone will lock you out from making another attempt for a set “cool-down” period of time. This cool-down period increases in length as you get closer and closer to 10 attempts. So, it is not the case that a prankster can just grab your phone, bang out 10 wrong passcodes, and make it wipe. The only way anyone is getting to 10 failed attempts is if you lose control of your phone for hours.

As mentioned above in the “Backup Your Phone” section, if your phone is wiped clean, you can restore your data from a backup, provided you’ve set up backups either through iCloud or with your computer’s iTunes installation.

2. Disable SMS Preview
By default, the partial text of SMS messages appear in previews on a locked phone. This would allow a thief to read your incoming text messages even if he is unable to unlock the phone.

In iOS 5, this can be disabled in Settings > Notifications > Messages > Show Preview.

If you want to go a step further, and even prevent the message notification (which includes the sender’s name) from appearing entirely, you can turn off “View in Lock Screen” in that same menu.

3. Jailbreak Your Phone for Additional Security Measures
Jailbreaking (the act of modifying your phone’s software to run software other than what has been authorized by Apple) is often spoken of as a security risk. To an extent, this is true, as users who jailbreak give up the safety of having the iPhone refuse to run any unsigned code (programs which have not been approved and digitally signed by Apple).

The flip side of this, however, is that jailbreaking allows users to take advantage of security features that don’t exist for non-jailbroken phones.

The first example of this is exploit fixes. When a new security hole is discovered in iOS, it often takes some time before Apple releases an iOS update that fixes the problem. Often, the jailbreak community fixes the hole themselves, releasing a patch for all jailbreak users to take advantage of much more immediately.

The other big “win” for jailbreakers is the ability to run security applications that aren’t allowed in the traditional iPhone app model. There’s RecognizeMe, which adds facial recognition to the standard Passcode Lock. There are apps like Firewall iP, which add a software firewall, and Lockdown Pro, which allows users to define passwords required to open certain applications, and iProtect, which will lock your SIM card and notify you if a new SIM card is inserted into that phone. Jailbreaking also adds the ability to use VPNs, such as OpenVPN, that aren’t among the standard VPNs supported by iOS natively.

There are a lot of security features that are only possible by breaking out of Apple’s “walled garden” model. Jailbreaking is not for everyone – it’s definitely for the diligent and the technically inclined – but for those of the right mindset, there are some clear security benefits to doing so.

Things NOT To Do

1. DON’T Buy An iPhone “Anti-Virus” Application
Anti-virus applications for smartphones are ineffective at best, outright scams at worst. Although there have been instances of phone-based malware, and there will be more in the future, anti-virus apps have so far proven to be fairly useless at defending against them.

2. DON’T Use A Weak Passcode
If using a Simple Passcode, your passcode shouldn’t be your birth year, or “0000″, or anything overly obvious like that.

Common advice is to use four different digits for your code. However, it may be the case where using 3 digits, with 1 repeat, actually produces a stronger passcode.

3. DON’T Sell or Give Away Your iPhone Without Wiping Your Data First
Too many people get rid of their devices without thinking about what’s left on them. The iPhone provides an easy way to wipe all of your settings and data, so that you can safely sell or give the phone to a new owner.

The menu is in Settings > General > Reset, then “Erase All Content and Settings”

It will ask you if you’re REALLY sure. If you’re no longer keeping the phone, you are.

Conclusion

By taking the steps above, you can significantly improve your iPhone security. Keep your eyes peeled for new security features with each iOS update, as Apple is being pushed for stronger security, thanks in no small part to ever-growing corporate and government use. Personally, I have my fingers crossed for GPG support in Mail, and native OpenVPN support.

Cool Hack: Dyslexic-friendly Font on Kindle

December 12th, 2011 - Brendon Rapp

Amazon’s Kindle devices come with two fonts – one serif and one sans-serif.

For people suffering from dyslexia, however, the precise symmetry of typical computer fonts only exacerbates the reader’s struggles with transposition and character confusion.

Over on Reddit, an intrepid Kindle user has hacked a Kindle and replaced the default font set with a dyslexic-friendly typeface, in order to provide his dyslexic wife with a better reading experience.

His Reddit thread is here: “This is how I made a Dyslexic friendly Kindle for my awesome Dyslexic wife”

According to him, the hack worked exceptionally well. For the hack, he used the font Gill Dyslexic, which reduces symmetry and makes similar-looking characters appear more distinct. In the past, many dyslexics have used the much-maligned Comic Sans font for reading, but the new breed of dyslexic fonts (including Gill Dyslexic and Dyslexie) are now stepping in to serve that need.

A picture of the Kindle displaying text in Gill Dyslexic

Accessibility is a big deal, and too many software and hardware developers are doing a poor job of meeting the needs of users suffering from disabilities and other challenges. This is one reason we strongly support both Free/Open Source Software (FOSS) as well as unlocked, user-modifiable hardware devices. Most of the time, when users want to “hack” one of their devices, it isn’t to steal content – it’s to make their device work for them, in a way the hardware designer failed to provide.

From Mercurial to Git

December 1st, 2011 - Brendon Rapp

In a previous post, I detailed how we converted Subversion repositories into Git repositories.

As I mentioned in that post, we also used Mercurial before moving to Git. In the interest of consolidating everything to one VCS, we needed to convert these as well.

We came across a mention on the Git wiki to a tool called hg-to-git, which, by all appearances, has only been released to the world in the form of a mailing list post: Mercurial to git coverter.

We didn’t anticipate much success with this years-old tool copy-pasted to the mailing list, so we turned our efforts elsewhere.

Most blog posts out there suggest using fast-export. These posts included:

At the time, when we tried running fast-export (on OS X as well as Linux), it invariably failed and spat out an error:

AttributeError: 'httprepository' object has no attribute 'branchtags'

Interestingly, searching Google for this error yielded just one hit, a Github issue, which went unresolved. However, this issue did close with the recommendation to move on to a newer tool, a Mercurial extension called hg-git, which is where we headed next.

Spoiler alert – hg-git is where we finally achieved success.

Installation

The following are the exact steps we took to use hg-git, on a machine running Ubuntu 10.10:

1. Install dependencies

Ensure setuptools and the Python 2.6 header files are installed:

$ sudo aptitude install python-setuptools python2.6-dev

2. Install hg-git

Install hg-git with setuptools

$ sudo easy_install hg-git

3. Enable hg-git as a Mercurial extension

Edit ~/.hgrc and add the lines:

[extensions]
hgext.bookmarks =
hggit =

You can confirm that it is installed correctly by running “hg help” and looking underneath “enabled extensions:” You should see “bookmarks” and “hggit”

Conversion

Converting a repo to Git involves:

1. Create a Git repository to push to

We were using Gitosis to manage our Git installation, so the first step was to create a new repo in gitosis.conf. The details of setting up a Git repo are beyond the scope of this article – if you’re doing this, I assume you have a working Git installation or are using a hosted service, and already know how to generate a new remote repo.

2. Checking out the Mercurial repository

$ hg clone http://path-to-your-repo

3. Make a bookmark to tell Git which branch is “master”

The main branch of a Git repository is called “master”. This isn’t true of Mercurial. So, for the import, we need to add a bookmark of the name “master”, which hg-git will use to identify what the Git “master” branch should be.

In most cases, this will be the Hg default branch, “default”.

$ hg bookmark -r default master

Note: in the case of one Hg repo which had originally been a Subversion repo itself, there was no “default” branch. Instead, the branch name “trunk” had been preserved in whatever conversion process we had done originally. So in that case, we ran…

$ hg bookmark -r trunk master

… which let Git know that “trunk” is what should be made into the master branch

4. Run the push command

$ hg push git+ssh://(git repo location)

Note the git+ssh:// prefix. Normally when using git push over ssh, we just use user@hostname:repo-name.git, and the git+ssh is implied. For the “hg push” command, however, it was necessary to state it explicitly.

And that’s it. Once the push completes, the remote Git repo has everything it needs, and can be interacted with purely through Git from then on.

It was pretty impressive to see a repository get converted from Subversion to Mercurial to Git and maintain its history, branches and tags. We’re happy Git users now, and I’m thankful for how smooth both svn2git and hg-git made that transition.

A Good Drive is Hard to Find

November 29th, 2011 - Brendon Rapp

It’s rare to see the cost of a piece of computing equipment ever go up. Parts and systems are usually at their most expensive the day they’re released, and then proceed to drop sharply until they are no longer made. It’s the unyielding march of technology - Moore’s Law in action.

This past month, however, has seen skyrocketing prices of a critical PC component: the hard drive.

The reason? A large percentage of hard drive production takes place in Thailand, which has been hit by monsoon season flooding.

An aerial view of a flooded Bangkok

The floods, which began in late July, are now slowly receding. Hard drive production has been impacted since then, but it has taken until now for the existing supply chain to dry up and for prices to rise.

According to TechRadar, prices have risen as much as 150% and a shortfall of 70 million drives is projected for the final quarter of 2011.

Many of us now rely less on our own local storage and more on cloud storage, and those services are large consumers of hard drives. Analysts are forecasting problems as we head into 2012 and those services find it more difficult to meet their drive demands.

The flood’s impact on the tech industry is, of course, merely a secondary story to the loss of life and the hardship of those affected. 621 people so far have died as a result of the flooding, and far many more have suffered from the destruction of their homes and communities. If you would like to help, donations can be made directly to the Thai Red Cross (link goes to the Thai Red Cross’s English language page).

The Two Questions

November 23rd, 2011 - Brendon Rapp

Not those two questions

When posting job openings, especially on public forums like Craigslist, we are flooded with responses. These responses tend to fall into three categories:

1. Obvious Spam

Why iPhone scares and beats its competitor?

Broken English, a nonsensical introduction, and a random soup of claimed expertises – all the hallmarks of Obvious Spam.  This is my favorite spam response, which we’ve received multiple times, from a different domain name each time. I still chuckle at, “Why iPhone scares and beats its competitor?”

Despite adding language to my postings to explicitly state that we’re looking to fill a staff position, these spammy responses from freelancers and agencies come in every time. There’s little you can do about them, particularly when posting to somewhere like Craigslist. Simply file them into the Rejects folder and move on.

2. Resume Blasts

Some responses actually come from individuals, but are stock messages that simply get blasted to every job that gets posted in a Craigslist category (or, worse, every job that gets posted, period).

These respondents generally aren’t actually reading what they’re responding to, but rather are attacking their joblessness problem with the shotgun approach.

3. Legitimate Responses

These are the responses you want – applicants who responded specifically to your job, and (hopefully) are sufficiently qualified for consideration.

The Problem

Obvious spam is usually easy enough to spot, but it takes closer inspection to filter out the mass-blasted responses from the ones that actually read your posting, particularly if the mass-blasted response does fall within your posting’s general area (or if the auto-blaster cleverly mined some keywords from the post.)

Hiring is enough of a hassle as it is – time spent on that is time not spent Getting Work Done and off of my task list. After becoming annoyed with the time spent digging through responses to try and find the valid ones, I implemented a very simple test.

The Solution – The Two Questions

At the bottom of my postings, along with the request for a resume, I ask two simple questions:

1) What software tools do you typically use for development?
2) How do you keep up with and learn about new development technologies?

The purpose of the questions is multi-faceted, but the most immediate thing it does is make the first pass of filtering responses a lot easier. I simply skim in search of answers to the questions. If they’re there, the person took the time to actually read what they were responding to, and their response merits being read in full.

If the answers are not there, the person is simply mass replying. Or, equally bad, they responded specifically to this post but could not be bothered to read it (or is incapable of following simple directions.) It’s a very quick and easy filter, which our creative director has taken and adapted for her job postings as well.

If you’re reading this and saying, “Van Halen brown M&Ms contract rider!”, good on you. Subconsciously, that was probably an inspiration, although I didn’t make the connection until after I had started using it.

I chose these questions because they’re simple to answer, but reveal a lot about the respondent. A developer who doesn’t have much to say about their tools likely hasn’t done much rigorous work, or has simply not cared enough to use anything beyond what they’ve been handed. Also, I’m looking for developers who are constantly learning and staying current, rather than someone who has learned one trick and sticks with it. From those responses, I can generally sort out the non-hackers from the ones that merit interviewing.

Not Bad, For a Start

We haven’t yet jumped into crafting cool little challenges for prospective applicants, as companies like Bandcamp and Instagram has done, but maybe that’s the next step. (When I have time. Whenever that is).

For a very simple, no-effort thing to attach to a job posting, however, this technique has really paid off. It’s little extra burden on the applicant (most seem to enjoy it) and it makes the garbage responses easier to filter out at a glance.

Google Apps SMTP without SSL, part 2

November 19th, 2011 - Brendon Rapp

In part 1, I talked about how we were able to use Google’s servers for SMTP without SSL, so that our firewall appliance would be able to send logs and notifications.

The upside to the approach in part 1 is that it required nothing but using a different SMTP server name and port. The downsides, however, are that the messages are being sent over the wire “in the clear” (unencrypted), and that the account being used to send mail doesn’t record the outgoing messages in its Sent Mail folder (which is handy for confirming that messages are being sent, if there is a problem with receiving them).

So, for the next network-enabled device that we encountered that lacked SSL support for SMTP, I took a different route.

On an internal server, I set up stunnel – an SSL tunneling proxy. With it, I was able to make this server act as a go-between for this networked device and Google’s SSL-requiring SMTP server.

Here’s the relevant section of the stunnel.conf file, which creates port 225 on the server and establishes the SSL tunnel to Google’s SMTP server:

# in /etc/stunnel/stunnel.conf
[ssmtp]
accept = 225
connect = smtp.gmail.com:465

On the device doing the sending, I filled in all configuration settings as normal for using Gmail’s SMTP (authentication, etc), but changed the SMTP server address to my tunneling server’s IP address on our internal network, and set the port number to the port I opened with stunnel (225, in the above instance).

I fired up the stunnel daemon on the server, and the SSL-challenged device was able to send mail at will. It was pretty surprising how relatively painless the setup was (the only issue I encountered was the stunnel.conf being very touchy about syntax), and how transparent the solution was once in place. Frankly, I forget that it’s there until I do something else on that server and see the daemon running.

So, there’s another solution for using Gmail/Google Apps’ SMTP service on non-SSL capable devices. This one requires a server to be online and running the stunnel daemon at all times that you want the ability to send mail, but you regain the benefit of having your outgoing mail going over the wire from you to Google through an encrypted connection.

Default VirtualHost in Apache

November 15th, 2011 - Brendon Rapp

We host multiple sites per server. One issue I ran into recently is when I had a DNS address record (“A” record) pointing to our web server, with a name that’s no longer being served by any VirtualHost.

What was happening was that a site on one of our VirtualHosts was appearing when someone attempted to browse to that address! Obviously, we don’t want any of our sites appearing on a different name than the one that’s been defined as its ServerName.

The issue here is how Apache matches requests to server names. Let’s say that www.example.com points to our web server, but there’s no longer a VirtualHost in Apache with that ServerName. When the user browses to www.example.com, DNS turns that name into an IP address – the IP address of our web server. The request goes to our webserver, asking, “hey, give me www.example.com”.

Apache attempts to find a VirtualHost with a ServerName or ServerAlias that matches www.example.com. If it fails to find a match, Apache serves up the first VirtualHost on that port.

An easy way to deal with this is to define a new VirtualHost to deal with these wayward requests, and put it at the front of the line. VHost configs are loaded in the order of their filenames, so simply creating a “000default” file with a Vhost pointing to a landing page does the trick.

Using JSHint to improve JavaScript code quality

November 11th, 2011 - Brendon Rapp

JavaScript can be a harsh mistress. One of the best books on JavaScript is based on the idea of using the language’s good parts and avoiding the plentiful “bad parts”. One startup recently learned this lesson the hard way, when a simple missing ‘var’ statement ground their big launch to a halt.

One tool that can help with this is JSHint. JSHint is a JavaScript code quality tool. It is a community-driven fork of JSLint, which has fallen out of favor due to a growing divergence between the style opinions of its creator and the community at large. If this factoid interests you, see Antov Kovalyov’s blog post, “Why I Forked JSLint to JSHint”.

JSHint will parse JavaScript code and flag various syntax and semantic errors. It will find issues that are technically valid JavaScript but likely to cause problems or reflect poor style.

JSHint actually exists as a website to paste your code into for checking, but copy-pasting code is hardly convenient. There does, however, exist a command-line interface for JSHint, powered by Node.js. We will install this, so that we can run the JSHint tool locally.

These instructions are for Mac OS X with Homebrew, but should be easily adaptable to other platforms.

1. Install Node.js

$ brew install node

2. Install NPM – the Node Package Manager
If we try to install through Homebrew, it tells us:

$ brew install npm
npm can be installed thusly by following the instructions at http://npmjs.org/
To do it in one line, use this command:
curl http://npmjs.org/install.sh | sh

So, let’s do that.

$ curl http://npmjs.org/install.sh | sh

3. Install JSHint using NPM
We’ll use the -g flag to install globally (ie. to /usr/local/bin)

$ npm install jshint -g

OK, now we’ve got JSHint installed. We can run it from the command line like:

$ jshint my-script.js
my-script.js: line 15, col 61, Missing semicolon.
my-script.js: line 31, col 84, Don't make functions within a loop.
my-script.js: line 98, col 25, Bad for in variable 'index'.
my-script.js: line 191, col 23, Expected a conditional expression and instead saw an assignment.
my-script.js: line 208, col 41, Use '===' to compare with '0'.
my-script.js: line 227, col 37, Bad escapement.
my-script.js: line 421, col 2, Mixed spaces and tabs.

This gets us started, but checking script manually from the command line, while better than copy-pasting to a webpage, still isn’t particularly convenient. It would be much nicer if we could hook JSHint into our editor and make it part of our workflow.

Many editors do indeed have ways of doing exactly this:

Vim

jshint.vim allows you to run JSHint from within Vim. It will open the JSHint results in a window split, and selecting the error in the JSHint window will allow you to jump to the corresponding line in your edit buffer.

Syntastic is a plugin that supports various code quality tools, and JSHint is one of the supported tools. Syntastic automatically detects the presence of JSHint on the system, and will Just Work once you enable the plugin’s behavior in your Vim config.

Sublime Text 2

SublimeLinter is a plugin for Sublime Text 2 that facilitates running various “lint”-style code quality tools from Sublime Text. JSHint is one of the supported tools.

TextMate

JsLintMate is a TextMate plugin for running JSHint (or JSLint) from within TextMate. Install and hit Ctrl+Shift+L to trigger JSHint.

Notepad++

Notepad++ doesn’t appear to have a plugin supporting JSHint, but does have a JSLint plugin.

Emacs

My Vim fandom prevent me from recognizing Emacs as a valid editor choice, but Emacs users are people too, and so they get jshint-mode.

Big Fat IDEs

If you prefer IDEs to text editors, there’s a plugin for Visual Studio, and the PhoneGap mobile web development plugin for Eclipse adds JSHint functionality to Eclipse. I couldn’t find much for NetBeans, outside of a blog post (“Integrating JSLint More Tightly into NetBeans”) on using the jslint4java Java wrapper for JSLint.

Whatever your code writing preference, JSHint should be fairly easy to integrate into your workflow. Personally, I am using it with Vim and the Syntastic plugin, and the JSHint output messages popping up whenever I save a JavaScript file that JSHint flags with warnings/errors is incredibly convenient. It is now just another automatic tool in my development toolkit.