Monday, July 10, 2017

The .io Error: A Problem With Bad Optics, But Little Substance

It's been a while since I've posted anything here. Being busy with work and various other projects, nothing has quite risen to the level of gotta write about it to get me writing, until now.

This morning, someone at work drew my attention to a post on The Hacker Blog that they thought warranted some attention. For those who haven't seen it, it purports to describe how the author managed to almost hijack most of the DNS traffic for the .io Top Level Domain. The post has started to receive a bit of attention elsewhere, and while it describes a definite mistake on the part of the Backend Registry Operator for the .io TLD, it definitely does not constitute the catastrophe implied by the article.

The problem with the article stems from the author's misunderstanding of how delegations in DNS actually work, and the part that the behaviour of both recursive and authoritative name servers has to play in the described "hijack." The author assumes that because he's able to register a domain name that matches several of the authoritative name server names for the .io TLD that it is "likely that clients will randomly select our hijacked nameservers over any of the legitimate nameservers..." This is wrong.

The author demonstrates his "hijack" by pasting these results to a DNS query:

; <<>> DiG 9.8.3-P1 <<>> NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8052
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;          IN  NS

;; ANSWER SECTION:       86399   IN  NS       86399   IN  NS

;; Query time: 4 msec
;; SERVER: 2604:5500:16:32f9:6238:e0ff:feb2:e7f8#53(2604:5500:16:32f9:6238:e0ff:feb2:e7f8)
;; WHEN: Wed Jul  5 08:46:44 2017
;; MSG SIZE  rcvd: 84

In order to poison a DNS server, you must understand the normal queries that would typically be sent by that server and be in a position to answer one of them with a crafted response, or be in a position to trigger specific abnormal queries that will elicit your poisoning response. The problem with the example query is that it would never be sent by a typical client, without some sort of abnormal prompting.

Since the author doesn't claim any ability to trigger unusual queries in arbitrary recursive servers, in order to evaluate the attack we should look at typical queries that would be sent by a recursive name server trying to look up an .io domain. To see what would actually happen in his attack, let's see what would happen if someone were to look up the A record for '' (the first .io domain that popped into my head). We'll assume an empty cache in order to give the attacker the greatest advantage, but skip the root priming query for simplicity, and because it wouldn't be relevant here.

The first query that will be sent is to the root. Because recursive servers are normally trying to get the most work done with the least effort, they always send the query for the information they're actually interested in, and deal with whatever response they get (an exception to this is a new option in the lookup algorithm called Query Minimisation, but it would have no effect on this). Therefore, the server does not ask the root for the .io name servers; instead, it asks for the A record for

; <<>> DiG 9.11.1-P1 <<>> +norec IN A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21410
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 13

; EDNS: version: 0, flags:; udp: 1472
;    IN A

io.   172800 IN NS
io.   172800 IN NS
io.   172800 IN NS
io.   172800 IN NS
io.   172800 IN NS
io.   172800 IN NS
io.   172800 IN NS

;; ADDITIONAL SECTION:  172800 IN A  172800 IN A  172800 IN A  172800 IN A  172800 IN A  172800 IN A  172800 IN A  172800 IN AAAA 2a01:8840:9e::17  172800 IN AAAA 2a01:8840:9f::17  172800 IN AAAA 2a01:8840:a0::17  172800 IN AAAA 2001:678:4::1  172800 IN AAAA 2001:678:5::1

;; Query time: 23 msec
;; WHEN: Mon Jul 10 16:06:40 EDT 2017
;; MSG SIZE  rcvd: 422

The root servers respond with a delegation to the .io name servers. So far this meets with the attacker's requirements.

For the second query, the client will select one of the .io name servers in the previous response, and send it the same query.

; <<>> DiG 9.11.1-P1 <<>> +norec IN A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15355
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 4096
;    IN A

;; AUTHORITY SECTION:   86400 IN NS   86400 IN NS   86400 IN NS

;; Query time: 25 msec
;; WHEN: Mon Jul 10 16:08:47 EDT 2017
;; MSG SIZE  rcvd: 102

The name server responds with the list of name servers for the domain. Note the very important difference between this and the example given in the original article. The list of .io name servers are nowhere to be seen. The client will go on and ask one of the Dreamhost name servers the same question:

; <<>> DiG 9.11.1-P1 <<>> +norec IN A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23214
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 2800
;    IN A

;; AUTHORITY SECTION:   14400 IN SOA 2014052400 18794 1800 1814400 14400

;; Query time: 62 msec
;; WHEN: Mon Jul 10 16:11:12 EDT 2017
;; MSG SIZE  rcvd: 99

It turns out there is no A record for, so the client is going to be disappointed. More importantly, it will not be poisoned with the attacker's NS set. The only set of name servers in this query chain to give the list of .io name servers was the root, and the contents of the root zone are unaffected by what you can convince your Registrar to pass up to your Registry, or your Registry to put in their zone.

The key element here is that the name servers for the .io TLD don't respond with their own NS set in their response. The only way you're likely to get that response out of those servers is to specifically ask, and that's a query rarely performed by your typical recursive DNS server. Even then, the author's attack doesn't work.

Let's use a concrete example. Here's a nearly-empty zone I just created for the TLD "myTLD".

$TTL 3600
@               IN  SOA ns1.localhost.myTLD. hostmaster.localhost.myTLD. (
                        2017071000  ; serial
                        12h         ; refresh
                        15m         ; retry
                        2w          ; expiry
                        1h )        ; negative TTL

                IN  NS  ns1.localhost.myTLD.
                IN  NS  ns2.localhost.myTLD.
                IN  NS  ns3.localhost.myTLD.

ns1.localhost   IN  A
ns2.localhost   IN  A
ns3.localhost   IN  A

example         IN  NS  ns1.example.myTLD.
example         IN  NS  ns2.example.myTLD.
ns1.example     IN  A
ns2.example     IN  A

The zone contains only those things necessary to make it a valid zone, plus one delegation for example.myTLD. The Hacker Blog author's attack was to add a delegation for one of the name servers. Here's what that would look like in the above zone:

ns1.localhost   IN  NS
ns1.localhost   IN  NS

Note that this creates a conflict in the zone. There is both a delegation and an A record for ns1.localhost.myTLD. In all authoritative DNS servers this converts that A record from an authoritative record in the zone to an "occluded name." In simple terms, the A record is hidden by the presence of a delegation at the same point in the tree.

Querying this zone for the A record for www.example.myTLD has the same results as for in the above tests, but what happens if we query this TLD name server for its own NS set?

; <<>> DiG 9.11.1-P1 <<>> -p 5053 @localhost +norec IN NS myTLD.
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5117
;; flags: qr aa; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 3

; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 17c0de220c7de23977eeeabd5963eb3576021df81bbff58f (good)
;myTLD.    IN NS

myTLD.   3600 IN NS ns1.localhost.myTLD.
myTLD.   3600 IN NS ns2.localhost.myTLD.
myTLD.   3600 IN NS ns3.localhost.myTLD.

ns2.localhost.myTLD. 3600 IN A
ns3.localhost.myTLD. 3600 IN A

;; Query time: 0 msec
;; WHEN: Mon Jul 10 17:01:41 EDT 2017
;; MSG SIZE  rcvd: 158

The occluded A record is not returned in the result, but neither is anything from the attacker's delegation. To get that, you have to ask specifically for that domain name:

; <<>> DiG 9.11.1-P1 <<>> -p 5053 @localhost +norec IN A ns1.localhost.myTLD.
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15774
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 2dcb47dea6b96a9c075f84a15963ebcf3878b68057c0ef7c (good)
;ns1.localhost.myTLD.  IN A

ns1.localhost.myTLD. 3600 IN NS
ns1.localhost.myTLD. 3600 IN NS

;; Query time: 0 msec
;; WHEN: Mon Jul 10 17:04:15 EDT 2017
;; MSG SIZE  rcvd: 132

And again, this is not a query that is normally going to be sent by any recursive name server trying to look up 'www.example.myTLD.' That client just wouldn't care. What the author succeeds in doing is to add a delegation to the .io zone. What he needs to do, to redirect any traffic at all, is to get an address into the .io zone. This is not going to happen with the method he's used.

In theory, getting an address for one of the TLDs nameservers into the TLD zone might be possible if he can register a host record with his registrar, but success assumes several things:
That the .io TLD uses host records at all:
Unbound by the same restrictions as the gTLDs, some ccTLDs don't bother with all of the bells and whistles of the EPP standards. I don't know about .io specifically, but there are some ccTLDs that do not allow the registration of host records.
That the same restrictions are absent for host records as were for delegations:
Assuming the Registry for .io uses host records, they may have a different set of criteria for allowing or disallowing the registration of host records than they do delegations. For example, it's unlikely you can register a host record that is not a subdomain of a domain you already have the delegation for, and it's not unreasonable to expect that the registry might require the host record to actually be a subdomain, and not be equal to the domain name.
That the registry doesn't have safeguards in its publishing that prevent duplicate records for its name server set:
Depending on how the Registry publishes its zone, it's possible (even likely) that the minimal set of records (the SOA, the apex NS set, and glue for the apex NS set) are handled differently during zone generation than delegations and their glue. The former is likely a static set, and the latter would typically come out of a database. Most Registries have safeguards in place to check the validity of a newly generated zone, and would be wise to include checks of the former "minimal set" in those tests.

Saturday, February 27, 2016

Installing FreeNAS 9.3 Over the Network

As users of new Skylake (LGA1151) systems are discovering, Intel has completely removed EHCI support from the new architecture. XHCI (USB 3.0) is supposed to be completely backwards compatible to USB 2.0, but the lack of EHCI support has some less than pleasant effects on trying to boot from USB using any OS that is expecting USB 2.0 support. Specifically, this means that GRUB 2 cannot currently boot an OS on XHCI-only systems, which makes installing FreeNAS a bit of a pain.

The symptom of this problem is that on XHCI systems the boot process will proceed up to the point where it tries to mount the root filesystem, and then it will die with an "error 19".
Trying to mount root from cd9660:/dev/iso9660/FreeNAS_INSTALL []...
mountroot: waiting for device /dev/iso9660/FreeNAS_INSTALL ...
Mounting from cd9660:/dev/iso9660/FreeNAS_INSTALL failed with error 19.

This is actually a problem that affects all XHCI systems, but if your system supports both EHCI and XHCI, you can disable XHCI in the BIOS to make USB booting work. Skylake systems, however, have no EHCI support at all, not even on the USB 2.0 motherboard headers, so this workaround isn't available.

Some people have found success with PCI cards that add EHCI USB ports, but you have to use caution with this approach since many (most?) PCI USB cards don't provide bootable USB ports. I didn't want to have to go pick up extra hardware just to install the OS, so I've opted for another approach: load the installer over the network via PXE.

The FreeNAS developers use PXE booting when testing new builds, and there is a guide for doing this with FreeNAS 9.2. However, the guide is two years old and I found it to be missing several steps when trying to apply it to a current version of FreeNAS. It's even worse when trying to use current versions of the FreeNAS developers' tools, as they're completely missing large sections of setup instruction (they're clearly not intended for use outside the project).

So, I'm publishing an update to the guide here. Eventually this will be out of date too, but hopefully it will save someone time down the road.

If you want to follow this guide you will need:
  1. a FreeBSD server which will be your PXE and DHCP server
  2. a machine you want to install FreeNAS on (presumably you already have this, since you're reading this guide)

Set up the BIOS

You'll want to modify your system BIOS boot order on the NAS host to make sure that PXE (or Network) boot is enabled, and will be attempted before any other valid boot option (e.g. if there's an OS on any disk in your system, that disk should be ordered after the PXE boot). Exactly how you do this is going to be specific to your BIOS.

Setting up the DHCP Server

Install the isc-dhcp43-server package, and use a config file that looks mostly like the following.  Update it for the subnet you use on your network:  "next-server" should be the IP address of your PXE server.
subnet netmask {
    option subnet-mask;
    option routers;
    option broadcast-address;
    option domain-name-servers;
    option domain-name "";

    filename "boot/pxeboot";
    option root-path "/tftpboot/installer/";

Prepare the Installer

You need a copy of the FreeNAS installer ISO coped out onto the PXE server's filesystem. The following pair of commands will get the current version I'm using:
mkdir -p /tftpboot/installer
fetch -o - | bsdtar -x -f - -C /tftpboot/installer/

Set up NFS

First, permit the installer you just set up to be exported, and start up NFS.
echo '/tftpboot -ro -alldirs' >> /etc/exports
echo 'nfs_server_enable="YES"' >> /etc/rc.conf
service nfsd start
Next, instruct the installer to mount its root filesystem from the NFS export you just setup. Be sure to set the hostname of your pxeserver (or its IP address) correctly in the fstab entry.
mkdir /tftpboot/installer/etc
echo 'pxeserver:/tftpboot/installer   /   nfs   ro   0 0' >> /tftpboot/installer/etc/fstab

Setting up TFTP

Modify the tftp lines in /etc/inetd.conf to look like the following:
tftp  dgram  udp   wait  root  /usr/libexec/tftpd  tftpd -l -s /tftpboot/installer
tftp  dgram  udp6  wait  root  /usr/libexec/tftpd  tftpd -l -s /tftpboot/installer
Finally, enable inetd and test your tftp server:
echo 'inetd_enable="YES"' >> /etc/rc.conf
service inetd start
tftp localhost
tftp> get boot/pxeboot
Received 231424 bytes during 0.0 seconds in 454 blocks


That's it. You should now be able to boot the installer over the network, and install FreeNAS on a disk installed in your NAS server.  Don't forget to consult the FreeBSD handbook section on diskless booting if you need help troubleshooting anything.  After installing, you may need to alter the boot order again to ensure that your freshly installed OS is booted before PXE.

Good luck!

Friday, October 11, 2013

Society's Bullies Hide Behind Secrecy

This week I had the privilege of being present at a discussion with Ladar Levison at a meeting of the North American Network Operators' Group (NANOG), his first public appearance since the court documents related to his fight with the FBI were made public.

For those not familiar with the case, Levison is the owner of Lavabit, a web-based email service designed to be secure against eavesdropping, even by himself. On August 8th this year he suddenly closed the service, posting an oblique message on the front page of the Lavabit website. The message explained only that he had closed the service because he had been left with a choice to "become complicit in crimes against the American people or walk away from nearly ten years of hard work by shutting down Lavabit."

There has been much speculation over the last couple of months that he had closed the service over a subpoena related to Edward Snowden's use of the service, and that an attached gag order similar to a National Security Letter (which were found to be unconstitutional in 2004) prevented him from speaking out about it.

Much of that speculation was confirmed last week when the courts unsealed the documents relating to Levison's appeal of a July 16th court order, which required him to turn over cryptographic keys that would allow the FBI to spy on all of the service's traffic, not just the information specific to Snowden's use of the service, which was specified in the original warrant. Wired Magazine published an article last week with most of the known details of the case, so I won't go into much more detail about that.

What I'd like to highlight is the danger to information security, consumer confidence, and the technological economy as a whole, should Levison lose his fight with the FBI.  The keys being requested by the FBI would allow them access not only to all of the information related to the individual targeted by their warrant, but also every other customer's data, and the data of the business itself.   This is highly reminiscent of recent revelations regarding the NSA and the scope of their data collection.  If that sort of wide net is supported by the courts, the fight for any kind of personal privacy will be lost, and consumers will never be able to trust any company with ties to the United States with any data at all.

This isn't just a problem in the United States.  Many of our online services eventually have dependencies on US companies.  In Canada, a huge percentage of our network traffic crosses into the US in order to cross the continent rather than remaining in Canada when moving between cities.  In other countries consumers rely on some of the more obvious US-based services (Facebook, Twitter, Google) but also many other services have less obvious dependencies, such as with services hosted by US-based data centres or on so-called "cloud" services with ties to the US.

As Andrew Sullivan comments during the Q&A, overreaching orders such as these are an attack on the network, as surely as any criminal trying to break a network's security.  Our personal privacy and the security technologies that guarantee it face attacks by those who want easy access to everyone's information, under the pretence of protecting the very people whose privacy is being violated.  It is vitally important that other business owners, like Levison, step up and fight orders such as these, so that a real public debate can happen over whether we still feel personal privacy and personal freedoms still trump the government's desire to have it easy.

At this point it is impossible to know whether any similar services have been compromised in the way the FBI has attempted with Lavabit.  I applaud the principled stance Levison is taking against this intrusion, and hope that, should I ever be in a similar position, I would have the strength to endure the long fight necessary to see it through.

Wednesday, July 3, 2013

Using Subversion With the Kobold2D Game Engine and Xcode

I've been messing about with some basic MacOS and iOS game development lately, and at the moment I'm working with the Kobold2D game engine, which is (mostly) a refinement of cocos2d.  I've found however that in Kobold's quest to make initial setup of a project easier, it sidesteps some of the normal setup that Xcode does when you add a project or file.  Some of this, such as Project Summary info like the Application Category and Bundle Identifier is easily fixed after the fact.  Version control setup, on the other hand, is marginally more complicated than normal (at least with Subversion).

With a bit of trial and error I think I've got a working procedure to get a new Kobold project to play nicely with Subversion.  Here are my assumptions for these instructions; the more you deviate from these the less this will be relevant, and I'll leave variations as an exercise for the reader:
  1. You're running Xcode 4.6 (I'm testing with 4.6.3)
  2. You've got Kobold2D 2.1.0
  3. You already have a repository set up and waiting at version 0 (zero)
  4. We're creating a pong clone called  -- oddly enough -- "pong"
Any text here in fixed width is intended to be cut and pasted directly into your Terminal if you desire.  However, I won't be held responsible if anything goes awry... I'm trusting that you're using your head and paying attention before you run any of these commands.

Create a Kobold2D Project

Run the Kobold2d Project Starter app.  Select the appropriate template (I'm going with Physics-Box2D) and set the project name to 'pong'.  You can also set your own Workspace name here if you want.  Make sure you uncheck "Auto-Open Workspace" because we don't want to have that open quite yet.  Click on the "Create Project from Template" button.

Import the Project into Subversion

In Terminal, set ~/Kobold2D/Kobold2D-2.1.0 as your current directory
cd ~/Kobold2D/Kobold2D-2.1.0
Make a new directory structure with the usual 'trunk', 'branches', 'tags' directory structure in it
mkdir -p pong-import/{trunk,branches,tags}
 Move your new 'pong' project into the new trunk directory
mv pong pong-import/trunk/
Change directory into pong-import and import the project and directory structure into your repository
cd pong-import; svn import . -m "Initial import"
Now delete this directory structure
cd ..; rm -Rf pong-import
That's it for the Terminal.

Add The Repository to Xcode

This is the only step that's exactly as it would usually be.  Go to the Xcode Organizer (menu Window -> Organizer) and select the Repositories tab.   Click on the + in the bottom left corner of the window and select Add Repository.   Follow the prompts to name the repository, give it the URI to the repository, add your authentication credentials, etc..  For the purposes of the example, let's say the URI for your repository is "".

Check Out a Working Copy

While still in the Xcode Organizer Repositories tab, click on the expander arrow to the left of your 'pong' repository.  It should show four folders:  'Root' in purple, and your 'Trunk', 'Branches' and 'Tags' directories in yellow.  Select 'Root' and then click on "Checkout" in the button bar across the bottom of the Organizer.

This will open a standard Save dialogue.  Browse your way to ~/Kobold2D/Kobold2D-2.1.0/, type 'pong' into the Save As field, and click on Checkout.

Clean Up Your Workspace

Return to your Kobold-2.1.0 folder in the Finder.  Open the "Kobold2D.xcworkspace" workspace, or your custom workspace if you created one.

You'll see your pong project listed, but it'll be in red.  That's because the files aren't where the automatically-created workspace expects to find them.   Right click on that and select Delete.

Then, right-click again and select Add Files to "Kobold2D" (or whatever the name of your workspace is).  Browse to ~/Kobold2D/Kobold2D-2.1.0/pong/trunk/pong, select 'pong.xcodeproj' and click on Add.

You're Done!

You should now have a functioning Kobold2D project with all of the usual Xcode internal Subversion support available.  You should be able to pick a random file from your 'pong' project files, right click it and go to Source Control -> Update Selected Files and cause Xcode to check if there are updates available for that file.  

Good luck, and good gaming.

Thursday, May 16, 2013

Patronage in the Modern Era

Jack Conte, probably best known for popularizing the VideoSong music format with his catchy, clever songs, has launched a new service that might change the way artists of all kinds bring home the bacon.

For years now, the issue of easily copied and distributed data has been plaguing artists and other copyright holders.  The arrival data and media sharing systems like BitTorrent and YouTube have been alternately heralded as the death of the music industry as we know it, and as field-levelling tools that would allow new artists of all kinds to connect with their fans.

Either way, many people in film and music have been struggling with the problem of creating new funding models that don't rely on every fan paying a fixed fee for a CD or DVD, and that allow for fans to freely share media (because they're doing that anyway) while still letting the artists pay the rent.

I've often thought one potential solution, however amusing it may sound, is to return to the centuries old practice of patronage.  In Medieval and Renaissance Europe, and earlier in Japan and other Southeast Asian countries, it was common for a wealthy individual to support an artist (or two) allowing them to produce plays, music, books, poetry, or paintings that wouldn't otherwise generate an income for the artist.  The model worked because artists could create art for art's sake without having to worry about whether it could be easily sold, the the patron received recognition for supporting a vital part of society.

Conte seems to agree that this could work again, and has built a service to make it possible.  Patreon allows fans to pledge an amount of money they choose, to be paid to their favourite artists every time the artist produces a piece of content.  It's crowd-sourced patronage that Conte likens to an ongoing Kickstarter for smaller projects, and several artists are already using it to get funding that would have been difficult or impossible to get before.

Thursday, July 19, 2012

Big Pretty Sky Sparks

A long long time ago, in a public school not too far from where I live now, what little we know about how lightning works was explained to me.  Apparently we still don't know a lot about how it works, but it seems we're a lot better at observing it than we used to be: I never actually got to see this particular behaviour of lightning in action before today.  My brother sent me a link to this video this morning.. it's a brilliant high-speed capture of a negative stepped ladder coming down from the clouds.  One branch makes contact with the ground and creates the path for a major return stroke.  This 33 second video covers about 0.13 seconds.

Friday, September 9, 2011

The One Where I Talk About A BBS Game

20 years ago I was, along with many of my friends, spending quite a lot of time on computer Bulletin Board Systems (BBSs). Most of us had already been doing this for many years, and there were people out there who'd been doing it even longer. The BBS scene at the time was pretty sophisticated we thought.. it was becoming possible to do some really great things!

One of the things that I thought was really great was playing computer games against other people in different places. This idea was still pretty novel, as computer networking, the way we think of it today, simply wasn't possible with most home computers – what few even existed. Most BBSes only had a single phone line for people to connect, and so out of necessity virtually every BBS game was turn-based, usually allowing a single turn per day. So, every day, I had time set aside to dial in, see what had transpired since the previous day, and take my turns.

One of my favourite games, and one of the few that I remember in any detail, was Esterian Conquest. It was a multi-player take on some of the early empire-building 4X games, set in a small two-dimensional galaxy, where each player had to build a fleet of ships, and go forth and conquer by force or diplomacy. Don't let the simple idea fool you though.. EC was a beast of a game, with simple rules that allowed for a plethora of complex results. Early on, my nightly turn would take but a few minutes to think about and execute, but later in the game I could literally spend hours pouring over reports from my fleets, hand-drawing maps on graph paper based on the information they contained, and then planning out and tediously punching in new orders for all of my fleets and planets.

About four years ago, while cleaning out boxes that had been in storage for ages, I came across a folder containing papers from the last game of EC I ever played. There were printouts of reports covered in pencil notes about possible actions to take, maps with quick calculations of how long it would take my fleets to reach some hot-spot in the game galaxy, and sheet after sheet of new orders.
Fleet 66 join fleet 47
Fleet 32 reduce speed to 5
Fleet 73 move to star at (12,41)
Everything about the game came back, and I started to wonder if it could somehow be resurrected. I had heard years before that the source code to EC had been lost in an all-too-unfortunate hard drive crash, but digging around in more boxes I did manage to find a floppy disk with the copy I had for the BBS I'd briefly run myself. Sadly, it proved to be more work than I had time for to get a computer running that could both run modern networking and connect that to an old DOS game. So I decided that instead, I'd just write my own.

I spent the next few months mapping out the game I'd like to create.. what I thought at the time was probably the first ever Turn-based Strategy MMO. I started writing documentation: how would I like the game to work? After chatting about the idea with a friend of mine, he gave me a photo-copy of an old table-top game he'd played called Stonova for ideas (it was based on Chris Wilkes' "Nova"). I worked out plans; I taught myself the math I'd need for three dimensional navigation (I wanted my game to take place in a realistic three-dimensional galaxy). But, when I really got down to it the game I had in mind would have required programming skills, particularly in the area of graphics, that I just didn't have the time to acquire. The idea was grand, but it was beyond me at the time. So I put the idea away for a while.

A couple of days ago, for no particular reason I can recall, I started thinking about this again. My original idea had been too grand for my meagre programming skills. But what if I scaled it down? In the last few years it's been proven that web-based games can work, and do attract players. So what if I ditched the desktop game idea, and went with the much easier to program web-based game? Games like Travian certainly seem to attract players, and as the basic concepts go it isn't all that different from what I had in mind.

My game will be simpler than EC in places, and more involved in others.

In EC it was possible to send your ships to any point in the galaxy, and along the way they would send back reports if they came within sensor range of any other passing ship. You could interrupt their orders mid-trip and have them pursue whom they spotted, or run away, or slow down and quietly follow at the edge of sensor range. I think I will simplify that a lot, and very likely only allow travel to other stars, not the spaces between them. Fleets will report on other fleets they find in their current star system, but I think I will drop the requirement to calculate intersecting flight paths, and handle changes in destination mid-flight.

EC had a small number of fixed ship types that you could build, and assemble into fleets. I think I'd like to have a bit more range in this area, so I'm going to design a technology research system that will allow players to concentrate on improving certain aspects of their ships. Are you a fan of big weapons? What happens when you go up against your opponent who has put all their research into heavily armoured ships? Or, maybe you just want to build really fast ships that can run away easily when threatened.

EC had no system of trade that I can recall. My game will allow players to trade resources, and might even have some sort of in-game cash economy. Perhaps you won't build warships at all, but will instead build big, fast transport ships and survive by supplying everyone with what they need... and paying tribute for "protection" where necessary.

So, I've started working on the idea again. I have no idea what will come of it, or whether I'll even finish. I haven't even got a name for it yet.. but I'm curious to see what I can come up with.