Archive for August, 2009

iPhone VPN

2

One of the coolest features of the iPhone is the way it uses the best data network that it can find. If you’re at home or at work, or even at a coffee shop, it will use the local wifi network. But if you’re out of range of any suitable wifi networks, it will use AT&T’s “3G” (UMTS) network. And if it can’t find a UMTS network, it’ll fall back to EDGE. Phone companies call this hybrid approach “ABC”, or “always best connection”.

Now that I have an internet device in my pocket, I find myself using public (or otherwise open) wifi connections quite a bit. And this carries with it some unintended consequences. That is… everything I type and everything I read is transmitted in the clear, unencrypted.

I try to make a habit of encrypting my data traffic whenever possible. My mail server is set up to only allow SSL connections. So no matter where I check my mail from, I am forced to use an encrypted connection. Similarly, banks and commerce web sites usually force you to switch to HTTPS before you start entering information. But there are a lot of applications on the iPhone that do not use encryption at all.

You might ask yourself why bother to encrypt your Twitter connection, since what you type is going to be blasted out to the world anyway. But the point is…

If you encrypt everything, then nothing is left to chance.

So I decided to explore a VPN option on the iPhone. It supports three flavors of VPN: L2TP, PPTP and IPSec. I was disappointed (but not surprised) that “openvpn” was not an option, since I already use this excellent open source SSL-based VPN package.

So I decided to give PPTP a try.

Setting up the PPTP server

On my Ubuntu 8.04 LTS server, I installed a PPTP server called, appropriately enough, “pptpd“. Configuration was very easy. Most of the setup was done for me after I did the standard apt-get install pptpd. I simply needed to pick a private subnet that would be used for my VPN clients, and an IP address in that subnet to use for the server. I chose the 172.16.4.0/16 subnet and 172.16.4.1 for the server (these addresses are part of a private network address space, defined by RFC 1918, just like 192.168.x.x and 10.x.x.x addresses).

My /etc/pptp.conf configuration file for the pptp daemon looks like this:

option /etc/ppp/pptpd-options
logwtmp
localip 172.16.4.1
remoteip 172.16.4.2-250

I also needed to tell the daemon to give out some DNS addresses when a client connects, so in the /etc/ppp/pptpd-options file, I added the two “ms-dns” lines below:

name pptpd
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
ms-dns 208.67.222.222  # resolver1.opendns.com
ms-dns 208.67.220.220  # resolver2.opendns.com
proxyarp
nodefaultroute
lock
nobsdcomp

Finally, I needed to add an entry into the /etc/ppp/chap-secrets file that would contain my password. Mine looks like this:

alan pptpd MyHardToGuessPassword *

At this point, the PPTP server was completely configured, so I restarted it with service pptpd restart.

Setting up the iPhone

On the iPhone, I needed to set up a VPN client. This is very easy. On the settings screen, go to general / network / VPN and “Add VPN Configuration…”. Then just fill in the blanks.

  • choose “PPTP”
  • enter a description
  • your server’s IP address
  • the username (from above)
  • RSA SecurID=OFF
  • the password (from above)
  • encryption level = Auto
  • “Send All Traffic” = ON
  • Proxy = OFF

Click on “Save” and you will see a switch in the network tab and also in the main settings tab to turn the VPN on and off.

For now, I am leaving it off unless I am on a public network. I am not sure, but I think that keeping the VPN alive might use a lot of battery. So I do not use it unless I need it.

Networking

For me to get this VPN on the internet, I had to do two more things: punch a hole in my firewall for the PPTP traffic, and forward traffic from my VPN out to the rest of the world.

For my server, both of these tasks were handed by the same tool: shorewall.

I added a “masquerade” rule to /etc/shorewall/masq to NAT all of the traffic from 172.16.4.x out through my main network interface.

eth0         172.16.4.0/24    # OpenVPN and PPTP

And then I added two rules to /etc/shorewall/rules to allow the PPTP traffic in.

ACCEPT  net  fw   tcp  1723  # PPTP
ACCEPT  net  fw   gre        # PPTP

When shorewall starts, it will generate the iptables rules that are used by the kernel to filter packets. If you’re using hand-written iptables rules, then you will need some rules that look something like this:

# accept "gre" protocol traffic (PPTP tunnel traffic)
iptables -A INPUT -p gre -j ACCEPT
iptables -A OUTPUT -p gre -j ACCEPT
# accept PPTP control traffic to TCP port 1723
# (my server IP is 11.22.33.44)
iptables -A INPUT -p tcp --sport 1723 -s 11.22.33.44 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 1723 -d 11.22.33.44 -j ACCEPT
# masquerade/NAT internet traffic out of interface eth0
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# turn on packet forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward

Conclusion

Now, when I am in a coffee shop, I can turn on the VPN easily by flipping the switch in the iPhone’s main settings screen. It will make a TCP connection to my server, negotiate a few things, and then send all further network traffic through an encrypted tunnel directly to my server, which relays it out to the internet.

You can test this by going to a web site like http://www.whatismyip.com/. If the VPN is working, it will show your server’s IP address. If not, it’ll show the coffee shop’s IP address.

Once I am using the VPN, anyone in the coffee shop who happens to be sniffing traffic on the wireless network will only see a single connection from my iPhone to my server, but the contents of this connection will be scrambled.

Custom ring tones for the iPhone

1

I spent five years working for Ericsson, devoting all of my professional energy towards making cellular phones better. I developed device drivers, application software, “middleware”, protocol stacks, and device prototypes. Not a day went by where I did not think about cellular phones in some way. It was not just a job, but a total gadget lifestyle.

Even in areas where I was not actively assigned to work, I still found ways to influence our products. Two particular examples come to mind.

In mid-2000, I was invited by our vice president (one of the two top managers in our NC office) to attend an all-day brainstorming session to discuss phones for kids and pre-teens: what it would mean for the kids, for the phone companies, for the parents, and for the content providers. I was a bit shocked when I entered the room — the attendee list was much smaller than I had expected, and I turned out to be the only software developer there. But the session went well, and I shared my (year 2000-era) thoughts on how Ericsson could never write even a small fraction of the applications that our customers would want, and so we would need to include some sort of API or virtual machine. At the time, Java looked promising. Fast forward to today, and see the success of Apple’s app store.

The second story, if you’ll indulge me (it is my blog, after all), is when I made friends with the King of Rings in Sweden. He was responsible for all ring tones that we delivered world-wide. I knew that he was also a Palm PDA user, so I showed him a Palm app that contained some really cool alert tones, and we discussed what made them really good alarm sounds: they did not blend in as background noise, they did not sound like voices or singing, they contained some pure tones of different pitches which would cut through the noise of everyday life. In short, they were alerts, not just sounds. That guy was very cool, and he had a very fun job.

It should be no surprise after hearing my Palm stories, that today I carry an iPhone. It’s everything the Palm aspired to be ten years ago, and a lot more than the Palm never imagined. It should also not be a surprise that I would find it important to install some good non-music ring tones for my iPhone. I was pleased to find that it is pretty easy to put custom ring tones on this device without writing a check to Apple or to AT&T. I dig free, and I really dig open.

On iTunes (we’ll forget about open for a second), I subscribed to a podcast that publishes ring tones. The one that I picked was the MacMost iPhone Ring Tones podcast. Every so often, it dumps a pile of ring tones (m4r files) onto your iPhone.

Some of them were cool, some were trash, and others needed a little bit of work. For example, one of them was a woman’s voice that said “ring ring, ring ring, your iPhone is ringing”. I liked the first half, but I thought the last part was tacky. So I decided to edit that one.

On my Linux machine, I downloaded “X Convert File Audio” (xcfa) and “audacity“. I copied the ring tone from iTunes to my desktop. I changed the file extension from “m4r” to “m4a”, since they really are the same thing, but Apple uses the “r” to distinguish ring tones from regular music files. Then I ran xcfa to convert the file to a common “wav” format. The GUI is a little crude (and some of the text is in French), but it works well enough for a quick conversion. Audacity understands wav files, and so I was able to edit the “your iPhone is ringing” out of my sample, and I cut and pasted until I had a 30-second clip (which worked better than a shorter clip for some reason). Audacity has all of the features you’d want, so you could add echo or reverb or whatever you like. I saved my sound as a wav file, using a new name (and also filling in that new name in the “properties” dialog box that popped up). Then I ran xcfa again to convert the file back to “m4a” format, and renamed it back to “m4r”. Finally, I imported the file back into iTunes.

So that was pretty simple: (1) export from iTunes (2) m4r to m4a (3) m4a to wav (4) edit (5) wav to m4a (6) m4a to m4r (7) import into iTunes.

If you wanted to start with a sound or a song instead of an existing ring tone, you would simply convert it to “wav” format and then continue at step (4).

If you’ll excuse me, my iPhone just farted.

Cell phone voice mail “hack” (customization)

3

This weekend, I was playing with ring tones, and so I called my iPhone several times to test them out. I started wondering how long it took before my unanswered calls were redirected to voice mail. So I timed it.

By default, it appears that AT&T sets that delay to 25 seconds.

When I worked at Ericsson (1998-2003), I collected a bag of tricks that I used to customize certain features of my phone and my Cingular account. It turns out that some of these tricks still work today. One of those tricks was to set that voice mail delay to a longer value by using the GSM “star” codes.

The wise folks that created the GSM cellular standard understood that some people might have an older phone, but that they might want to use newer network features.

For example, remember the “bag phone” that people used in the early 1990’s? Or the Motorola “brick”? Those had simple calculator-style displays. The did not have a “voice mail” menu… all they could display was numbers! However, the guy at the phone store could program a brick phone to forward unanswered calls to voice mail after a certain delay. Or he could turn on call forwarding. In fact, he is actually telling the BASE STATION to forward unanswered calls, since that’s the piece of equipment that handles that job. After all, the phone itself might be turned off, or have a dead battery, or it might be in Africa somewhere.

It turns out that most features of the GSM network can be accessed using a series of digits dialed into the keypad. The sequence for call forward on no answer is **61*(target number)*11*(seconds)#.

If you typed that sequence into the old Motorola “brick”, a message would be sent to the base station to say “forward my phone calls to the following number if I do not answer within a certain number of seconds”. That same star code works on a modern phone as well.

This is also how “smart” phones work — the user interface runs on a PDA-like device, and star codes are sent over a serial line to the “GSM modem module”, a completely separate phone-on-a-chip that does nothing but handle the phone calls.

Here’s what it looked like when I customized my voice mail delay from my iPhone. First, I dialed the star code to see what my current voice mail setting was. That code is *#61#.

fwd-verify.jpg

I wrote down the voice mail number — this is the number for AT&T’s voice mail system. Then I dialed **61*+1xxxyyyzzzz*11*10# to see if it would change my “call forward on no answer” delay to 10 seconds.

fwd-dial.jpg

And I got this confirmation screen.

fwd-success.jpg

Then I called my iPhone. Sure enough, after 10 seconds, my call was routed to voice mail.

Of course, 10 seconds is too short — I used that number as a test. So I repeated the process to set the delay to a more reasonable 30 seconds.

A couple of important points:

  • This is not hacking. This is a documented feature of GSM cellular networks, and it is exactly what happens behind the scenes when you enter a phone number in the “voice mail” menu of a cellular phone. The only difference is that the menu uses a hard-coded delay value, whereas you can set your own delay if you enter the command manually.
  • This process should work on any GSM phone, not just on the iPhone.

Born in the USA

4

We can all thank Bruce Springsteen for planting the idea in our heads that a person has to be born in the United States in order to be eligible to become president.

Article II of the US Constitution clearly states the requirements, that a president must be “a natural born Citizen”. Nowhere does it state that the person must be born in the United States. It is true that most people who are born in the US are granted citizenship at birth. It is also true that people who are born outside of the US, from one or more US citizen parents, can also be granted US citizenship at birth.

When my daughter was born in Singapore, many of my friends made the comment that “she can never become president”. However, shortly after her birth, the US Consulate in Singapore presented us with a “Consular Report of Birth of a Citizen of the United States of America”, or Form FS-240. This form clearly declares that my daughter was born a US Citizen, and it is recognized by the US government as proof.

I bring this up because of the current scuttlebutt, claiming that Barack Obama was not born in the United States, and therefore can not legitimately act as president. I am not going to get into that argument.

But I do want to clarify that being born in the US is not a requirement for citizenship, and it is not a requirement for becoming president.

I can only hope that Audrey has this same problem in 30 years.

Do not pass? Go? Do not collect $200?

1

On my morning commute to work, I travel along a five-lane highway (two lanes in each direction, plus a shared turn lane). There is a bus stop in front of a large apartment complex, and the bus picks up a huge bunch of kids there.

Every morning, this south-bound bus stops in front of the apartment complex, and several dozen kids get on, taking their sweet time (as kids do). All of the south-bound cars are blocked while the bus is stopped.

At this time, I am usually wondering why that bus does not pull into the apartment complex’s driveway. After all, they are blocking a major roadway during a busy morning commute time.

But it gets worse… not only are all of the SOUTH-bound cars stopped. But the NORTH-bound cars are stopped as well!

North Carolina law does not require the drivers in the opposing lane to stop. But most drivers are not that familiar with the details of the traffic laws. And I suppose that when faced with this choice — either err on the side of stopping when not necessary, or err on the side of passing a stopped school bus — most people would take the more conservative option.

The North Carolina Driver’s Handbook can be downloaded from the DMV’s web site.

On page 43, you’ll see this picture:

passing_a_bus.png

And this is the explanation:

Roadway of four lanes or more with a center turning lane: When school bus stops for passengers, only traffic following the bus must stop.

Of course, it also goes on to say:

Children waiting for the bus or leaving the bus might dart out into traffic. Even when the school bus is not in sight, children at a bus stop sometimes will run into the street unexpectedly. Always be careful around school buses and school bus stops.

So, as always, common sense does apply.

I have considered what I might do if I happened to be the first north-bound car to approach as that school bus stopped in the south-bound lane. Would I keep going (with caution, of course)? Or would I stop, just because my fellow citizens might sneer at me for “breaking the law” and for driving with a reckless disregard for out children’s safety?

THINK of the CHILDREN!

How would a police officer react if he were driving right behind me?

I am not saying that stopping for the bus is a bad thing. But I am amused to see how people react when the rules are ambiguous, or when they are incompatible with what seems like a universal blanket rule (Thou shalt stop). Would you want to be the one who follows the letter of the law, but who appears to be a scofflaw?

Compromised?

3

This morning, when I scanned my email, I ran across a report from rkhunter, a tool that runs on my web server that periodically checks to see if system files have changed, or if users have been added, what processes are listening on ports, and a litany of other tests to detect whether a system might be infected. I get these reports fairly often, usually the day after I do an upgrade, or after I add a new user.

However, today’s email was a little bit alarming. It said that several files had been changed recently. And these files all seemed to do with the same sort of things: running stuff behind the scenes, showing library dependencies, elevating privileges. Basically, these were tools that you would want to modify if you wanted to cover your own tracks.

Warning: The file properties have changed:
         File: /bin/sh
         Current hash: 23603f77da4ca37705146fd8a4ed951c8b037156
         Stored hash : 91654fd25d317bd13a65e10d777ac021f4a1a4f6
Warning: The file properties have changed:
         File: /bin/dash
         Current hash: 23603f77da4ca37705146fd8a4ed951c8b037156
         Stored hash : 91654fd25d317bd13a65e10d777ac021f4a1a4f6
         Current inode: 180336    Stored inode: 180255
         Current file modification time: 1236603791
         Stored file modification time : 1213978027
Warning: The file properties have changed:
         File: /usr/bin/dpkg
         Current hash: 4e05d20a4f828c31eb5f6dd9cc5f04d1d6202d0a
         Stored hash : 09a5bbd0398cc9f02b52440e1241cd942e784a15
         Current inode: 248598    Stored inode: 246001
         Current size: 375340    Stored size: 371244
         Current file modification time: 1236595869
         Stored file modification time : 1220443410
Warning: The file properties have changed:
         File: /usr/bin/dpkg-query
         Current hash: ff8098920430d399933ee24245748983a0661869
         Stored hash : 4a1c1226cbe9dd2ddbec7b5652f1fa8aa0b15f09
         Current inode: 248600    Stored inode: 246003
         Current file modification time: 1236595869
         Stored file modification time : 1220443410
Warning: The file properties have changed:
         File: /usr/bin/file
         Current hash: 4ab93b21aaabb405f4bd2e90f16ee5e952aa746b
         Stored hash : 80dc1735091a4309d23e49ce542c58ddd16163dc
         Current inode: 245969    Stored inode: 246049
         Current file modification time: 1244193699
         Stored file modification time : 1215771733
Warning: The file properties have changed:
         File: /usr/bin/ldd
         Current inode: 248852    Stored inode: 246132
         Current file modification time: 1233224578
         Stored file modification time : 1222684817
Warning: The file properties have changed:
         File: /usr/bin/perl
         Current hash: 00d703e925eca6de0c8fc9bd9d4505db4b81ce33
         Stored hash : efb4a1a3d02798718b7f2bbfea6787dd0de79968
         Current inode: 245962    Stored inode: 246591
         Current file modification time: 1246045733
         Stored file modification time : 1216891204
Warning: The file properties have changed:
         File: /usr/bin/sudo
         Current hash: e649919d4bbc6ac78e38497ca94dc387cc2811a7
         Stored hash : 49e97774326fc9eb5f7cb680477c1d56f4e28921
         Current inode: 246543    Stored inode: 246747
         Current file modification time: 1234840625
         Stored file modification time : 1220275024
Warning: The file properties have changed:
         File: /usr/sbin/cron
         Current hash: 5efdffc9796731168fb7acc8688c5a02e0da42dd
         Stored hash : 04924b72b749e8179bb5839bac1a296c7acf93c4
         Current inode: 245910    Stored inode: 248315
         Current file modification time: 1242164811
         Stored file modification time : 1220989568

One or more warnings have been found while checking the system.
Please check the log file (/var/log/rkhunter.log)

I scanned /var/log/dpkg.log, to see if I had recently done an update, and I did not see anything. That little paranoid part of my brain started to wake up (those that know me might clarify that when I say “little”, I really mean “big”).

So briefly, someone had changed the following files on my server. How could I tell if they were the “real” ones or not?

  • /usr/sbin/cron
  • /usr/bin/sudo
  • /usr/bin/perl
  • /usr/bin/ldd
  • /usr/bin/file
  • /usr/bin/dpkg-query
  • /usr/bin/dpkg
  • /bin/dash
  • /bin/sh

What bothered me about this combination was that dpkg was in that list, so I could not use any of the apt/dpkg tools to verify the integrity of my packages against what is published on the Ubuntu mirrors.

So I had to take matters into my own hands. I went to the Ubuntu packages site and searched for the first package, ‘cron’. From there, I could click on the ‘i386’ link to download a local copy of the cron_3.0pl1-100ubuntu2.1_i386.deb file onto my laptop (not onto the suspect server). I extracted the contents using dpkg -x cron_3.0pl1-100ubuntu2.1_i386.deb .. From there, it was pretty easy to compare MD5 checksums of the files.

$ ls
cron_3.0pl1-100ubuntu2.1_i386.deb
$ dpkg -x cron_3.0pl1-100ubuntu2.1_i386.deb .
$ ls
cron_3.0pl1-100ubuntu2.1_i386.deb  etc  usr  var
$ md5sum usr/sbin/cron
c1d78d8a9a99b52df8ecba41517ab013  usr/sbin/cron
$

This checksum matched the one on my server. So that means my binary files were legitimate (this does not explain how they got updated without leaving a trail in the logs, but that is another issue).

Lather, rinse, and repeat for all of the suspected files.

I hope this little story helps someone else defuse that panicky feeling that sets in when your intrusion detection system sends you an unpleasant email.

The toys that feed my obsession

1

I have always been a bit of a gadget freak, with a real interest in personal computing devices. I discovered early on just how useful it could be to have a lot of information at your fingertips.

Way back in 1992, when most people were running Windows 3.1 and Novell networks were cool, I bought a Zeos Pocket PC, a small DOS-based PC about the size of a VHS videotape that ran off of 2 AA batteries. It had Microsoft Works built into ROM, and 384k of battery-backed RAM to store my files. That was a sweet little PC, and I used it to store lots of convenient stuff, from my stock portfolio to my personal address book and calendar. You really can store a lot of data in 384k — if it’s all text.

In 1996, my wife (trend setter that she is) bought a Palm Pilot. The built-in apps were very clean and polished, and there were thousands of third-party apps that could be downloaded. I followed right behind her with one of my own. Moving from DOS to PalmOS was a bit of a shock — it was like suddenly moving into a nice neighborhood where someone else cleaned your house (but sometimes you could not find where they stored your stuff). I quickly grew to love that platform, even writing a few simple apps of my own. Over the years, we upgraded Palm devices several times.

The next year, I started working for Ericsson. This was in the early days of digital cellular (in the US), and I was excited about trying hand-held devices that were also wireless. But Ericsson never managed to fill this void with one single device. Instead, I carried a “Bat Man utility belt” of gadgets: a Palm PDA, an Ericsson GSM phone, and an Ericsson IrDA adaptor. Bluetooth was still under development at the time… still called MC Link, but eventually I upgraded my utility belt.

At one point, I got fed up with PDA’s. In the battle for pocket space, the phone always won over the PDA. And most of the time, I was either at home or at work, so I almost always had a PC nearby. I also started to worry about security — what if I lost my PDA, what would a thief know about me? So I gradually weaned myself from all of my “must have” Palm applications and I moved my portable data to the hot new thing… a thumb drive. I encrypted the whole darned thing, plugged it in at work or at home, backed it up often, and never worried about losing it. The only time that I found myself missing the PDA was when I needed my calendar. So once in a while, I would print it out and keep it in my pocket… on paper… old school.

It made sense to start moving some of my data to the web. There are nice web apps for doing calendars and address books and lots of stuff like that. Some use Google. I chose to host it on my own server, where I knew it was safe from prying (and marketing) eyes.

When it was time to get a new cell phone, my wife secretly bought me an LG vx9900 “enV” phone. It was one of the first phones that flipped open to reveal a QWERTY keypad. It had a pretty good WAP web browser that allowed quick retrieval of some type of info: weather forecast and radar, geocache hints, and my personal stuff (address book, etc) that I had moved to the web already.

In the summer of 2007, known around my house as “the summer of toys”, I found myself with a new mandate: I wanted portable internet access while we went to China in the fall. Looking back at my great experiences with Palm devices, I bought a used Palm Tungsten C on eBay. This is one of the few Palm PDA’s that sported an 802.11 wifi link. However, after a few weeks of pre-China tinkering, I decided that the screen was too small (in pixels), the email access stunk, and the browser was only suitable for the absolute simplest of web pages. I relegated it to my geocaching bag, where its only job was to occasionally look up geocache hints. Within a month, I had cracked the screen. C’est la vie.

About a week before we were to leave for China, I spotted a clearance sale on Woot where they were dumping the Nokia 770 as Nokia geared up for their new model. I snatched one up, and it performed flawlessly on our trip, accessing the internet wherever we were (using either free or “borrowed” wifi). I accessed email through a web mail app on my server at home, and we looked up dozens of things online, from local attractions to pharmaceutical advice. I did not have to worry about virus-laden PC’s in internet cafe’s and hotels (or at my in-laws’ house) and I did not have to navigate through a Chinese version of Windows XP. Best of all, since the N770 runs Linux under the hood, there are a lot of nice tricks that you can do, like running a VPN, or syncing via SSH over wifi.

The next year, I attended a hacker conference. Like a flashback to the Zeos Pocket PC 1992, I encountered a guy using the Asus Eee PC. Within a week, I had one of my own, and it became my primary computer for the next year. I immediately wiped the solid state disk and installed Ubuntu. The flash disk is pretty modest, so I did not store any of my stuff on it, preferring instead to keep that on my encrypted flash drive. Being small enough to keep in a bookbag meant that it went everywhere I went. And on the rare occasions when I needed more screen real estate, I simply plugged into a VGA monitor.

This month, I enter a new chapter in my long series of relationships with small machines. I bought an Apple iPhone 3G S. I am extremely excited about this device. Like the Palm, it has a ton of third-party applications. Like the Nokia 770, its browser is good enough to make it an effective “vacation PC”. Like the Nokia 770, It uses either the open wifi of your generous neighbors, or the cellular network. But unlike the “Ericsson Bat Man utility belt”, this device does it all in one, very small and sexy unit.

To summarize:

  • 1992 Zeos Pocket PC – PC? yes… pocket? that’s a stretch
  • 1996 Palm Pilot – a very nice PDA with a lot of third party apps
  • 1999 the Ericsson “Bat Man utility belt” – no one ever called Bat Man a geek
  • 2004 thumb drive – where most of my stuff lives
  • 2005 the web – where a lot of my stuff lives
  • 2007 LG vx9900 “enV” phone – a nice phone with a simple browser
  • 2007 Palm Tungsten C – not really worth it
  • 2007 Nokia 770 – the web in your pocket
  • 2008 Asus Eee PC – big enough to be a full PC, small enough to carry everywhere
  • 2009 Apple iPhone 3G S – we shall see
Go to Top