SSH gateway shenanigans

I love OpenSSH. Part of its awesomeness is its ability to function as a gateway. I’m going to describe how I (ab)use SSH to connect to my virtual machines. Now, on a basic level, this is pretty easy to do, you can simply port forward different ports to different virtual machines. However, I don’t want to mess about with non-standard ports. Or you could give each of your virtual machines a seperate IP address, but then, we’re running out of IPv4 addresses and many ISPs stubbornly refuse to use IPv6. Quite the pickle!

ProxyCommand to the rescue!

ProxyCommand in ~/.ssh/config pretty much does what it says on the tin: it proxies … commands!

Host fancyvm
        User foo
        HostName fancyvm
        ProxyCommand ssh foo@physical.box nc %h %p -w 3600 2> /dev/null 

This allows you to connect to fancyvm by first connecting to physical.box. This works like a charm, but it has a couple of very important drawbacks:

  1. If you’re using passwords, you have to enter them twice
  2. If you’re using password protected key files without an agent, you have to enter that one twice as well
  3. If you want to change passwords, you have to do it twice
  4. It requires configuration on each client you connect from

Almighty command

Another option is the “command=” option in ~/.ssh/authorized_keys on the physical box:

command="bash -c 'ssh foo@fancyvm ${SSH_ORIGINAL_COMMAND:-}'" ssh-rsa [your public key goes here]

Prefixing your key with command=“foo” will ensure that “foo” is executed whenever you connect using that key. In this case, it will automagically connect you to fancyvm when you log in to physical.box using your SSH key. This has a small amount of setup overhead on the server side but it’s generally the way I do things. The only real drawback here is that’s impossible to change your public key, which isn’t too bad, as long as you keep it secure.

The Actual Shenanigans

The command option is wonderful, but some users can’t or won’t use SSH key authentication. That’s a bit trickier, and here’s the solution I’ve come up with – but if you have a better one, please do share!

We need three things:

  1. A nasty ForceCommand script on the physical box
  2. A user on the physical box (with a passwordless ssh key pair)
  3. A user on the VM, with the above user’s public key in ~/.ssh/authorized_keys

This will grant us the magic ability to log in to the VM by logging in to the physical box. We only have to log in once (because the second part of the login is done automagically by means of the key files). A bit of trickery will also allow us to change the gateway password, which was impossible with any of our previous approaches.

Let’s start with a change in the sshd_config file:

Match User foo
        ForceCommand /usr/local/bin/vmlogin foo fancyvm "$SSH_ORIGINAL_COMMAND"

This will force the execution of our magic script whenever the user connects. And don’t worry, things like scp will work just fine.

And then there’s the magic script, /usr/local/bin/vmlogin:

#!/bin/bash

user=$1
host=$2
command="${3:-}"

if [ "$command" = "passwd" ] ; then
        bash -c "passwd"
        exit 0
fi
command="'$command'"
bash -c "ssh -e none $user@$host $command"

Update 2016

The above script no longer works with SFTP on CentOS 7 with Debian guests. Not sure why, and I’m too lazy to find out. So here’s a script that works around the problem.

#!/bin/bash

user=$1
host=$2
command="${3:-}"

if [ "$command" = "passwd" ] ; then
        bash -c "passwd"
        exit 0
fi

# SFTP has been fucking up. This ought to fix it.
if [ "$command" = "/usr/libexec/openssh/sftp-server" ] || [ "$command" = "internal-sftp" ] ; then
        bash -c "ssh -s -e none $user@$host sftp"
        exit 0
fi

command="'$command'"
bash -c "ssh -e none $user@$host $command"

And there you have it, that’s all the magic you really need. Everything works exactly as if you were connecting to just another machine. The only tricky bit is changing the gateway password: you have to explicitly provide the passwd command when connecting, like so ssh foo@physical.box passwd


On Ruby & PHP

So I quit my job. That was a relatively big change for me, after spending 3 years sat on the same chair working with the same team. But I felt it was time for a change. The new job is quite a bit different from the old one. One rather obvious difference is the programming language .. I’ve gone back to my proverbial roots and am now churning out PHP on a daily basis. And because I’m such a programming nut, I’m working on some after-hours Ruby projects as well.

PHP and Ruby are both obviously very different from Java - and very different from each other. Sometimes in good ways, sometimes in bad ways. Syntax wise, PHP and Java are very similar. The dollar sign on my keyboard is definitely seeing a lot more action now, but other than that not many dramatic finger changes are required. PHP doesn’t have have a bunch of things I like, like final method arguments, multi-threading or a half decent collection of standard classes. What it does have is excellent documentation and easy & interesting meta-programming. That, and it’s obviously much more tailored for the web than Java. For the first time in 3 years I don’t actually need a whole armada of frameworks just to get something simple done. Still .. I miss my (Concurrent)HashMap, ArrayList, and most importantly my trusted BigDecimal.

And then there’s Ruby .. Even after a couple of months of Ruby, I have very mixed feelings about it. The documentation sucks. Don’t argue with me, it really does suck big fucking donkey balls. RDoc (especially online) is to JavaDoc what Spam is to nice and tasty Prosciutto. Then there’s the lack of backwards compatibility (granted, Java may take this a bit too far, but still).

And then … there’s the syntax. This is where my feelings are mixed, rather than plain negative. There’s too much choice. You can mix and match a bunch of styles, do..end, curly braces, semicolons or no semicolons, method arguments with or without parentheses, and the list probably goes on. This leads to code that’s hard to read (and thus hard to maintain), especially when different people stick to different styles. On the other hand, it also leads to nice syntactic sugar. Clever use of methods can make it look like you’re defining your own keywords, which is very nice for creating your own DSLs. It’s also rather nice to have Operator Overloading, and being able to treat everything like an object also has its benefits.

Still .. my feelings remain mixed. And in spite of everything, I feel like Java is still the best choice for Serious Work. Not only because of the amazing documentation, the excellent standard library or even the massive community, but also for the amazing JVM, its security model and its thriving ecosystem.

Java ain’t dead, folks.


On naming interfaces

Just about every programming book or OOP example I look at has the annoying habit of prefixing interface names with an I. Yes, IInterface, ICar, IWallet, IMoney, IIAmStupid. It’s one of my pet peeves, I admit, but every time I come across code like this I find myself suppressing murderous tendencies.

Why oh why would you do this? “To clearly indicate that it’s an interface”. Why the hell do I need to know that it’s an interface in the first place? If I want to use your library, I really don’t give a toss whether I’m talking to an interface or a concrete class. If I do want to know (because I’m extending or initialising it) then I’m quite capable of figuring out for myself whether I’m dealing with an interface, abstract class or concrete class. The only thing this random I does is make it harder to look for suitable classes. I want to search for Car, or Wallet, or Money. Not to mention that I don’t want to type that extra letter every single time I’m assigning an instance to a variable.

Seriously, how ugly is this

IFoo foo = IFooFactory.createIFoo();

The irony here is that I used “I” 32 times in this post. But for crying out loud, pick a meaningful name, not some silly prefixed monstrosity.


The Agile Samurai - mini book review

The Pragmatic Programmers have published quite a few books over the years. My bookshelf contains nearly a dozen of them. The latest addition being The Agile Samurai: How Agile Masters Deliver Great Software.

A samurai with their sword on the wrong hip

It’s essentially a high level overview of agile practices, with a focus on the why and the how. Unlike some other books on Agile, this one tries to remain pretty neutral when it comes to methodologies. XP, Scrum, Kanban are all briefly mentioned, but the author managed to boil Agile down to its essentials: common sense, being goal oriented and having a willingness to improve.


Test design - equivalence classes

During a recent job interview, I was asked to write some code – I know, shocking! The idea was that several test cases had been defined, and that I was to implement a relative simple class that would make the tests pass. The problem was pretty simple, so I won’t bore you with it.

What was shocking, however, was how poorly designed the tests were. Boundary cases were largely untested, and it seemed like someone spent an inordinate amount of time writing useless tests. When I brought this up during the interview, the person who wrote the tests seemed surprised that they weren’t very good, because he got nearly 100% code coverage on the implementation he created.