The Mobile Wi-fi Access Point

Do-it-yourself cheap, easy Internet... everywhere!

By Nathan True (mobileap@fartysss.co.uk@natjavoFlayingspayneutercontrolpetpopulationetrue.com)

Prologue

I recently got a new cell phone as part of my contract renewal with my cell provider. I was pleased to learn that for a two-year service agreement I could purchase a Nokia 3220 for around $40. Knowing that I could use a data cable to connect my laptop to my phone and get mobile Internet at any time, I jumped at the chance. I could even use any of their prepaid phone plans to stay connected on the cheap. Also, considering they use GPRS connections they're pretty compatible cross country, as most networks from Afghan Wireless to AT&T have GPRS data plans available.

Imagine - never having to deal with real life again, because wherever I am the Internet is there with me. Of course, mobile Internet has less anti-social uses. Modern businesspeople can seldom spend much time away from the Internet, what with Internet-centric businesses being all the rage nowadays.

A quick eBay search yielded a number of sources for data cables to my new phone. I figured nine dollars for a Nokia CA-42 cable was totally worth it - and boy howdy was it ever!

After two days of rapt anticipation, I received my cable and immediately used it to fill the conspicuous gap between the bottom of my phone and a USB port on my laptop. In the ensuing frenzy, drivers were installed and Nokia Connection Managers were set up. A quick search of the Internet revealed the correct settings for the WAP gateway and username/password for my particular wireless carrier.

The Problem

Mashing the "Connect" button with a silent fervor, my pupils dilated as I noticed the screen on my phone light up. Also, my hand contorted to an ostensibly painful pose, but I didn't notice until I saw the picture. The words "Creating GPRS Connection" flashed along with a suspiciously eager-looking progress bar. That was that - I was connected to the Internet.

But all was not well.

Over a couple of days playing around with my connection, disconnecting, reconnecting, and trying various services and websites, I noticed there were several issues to reconcile:

Mulling over the problem for a week or two, my eyes drifted slowly toward the stack of three Motorola WR850G routers in my room.

The Solution

Each of these routers (which can be had for around $30 apiece) was running the OpenWRT Linux embedded operating system. Their infinite reconfigurability has made them the focus of a few of my projects in the past. (Check out their Table of Hardware - your 802.11g router may be capable of running OpenWrt!)

Wouldn't it be great if I could just plug my phone into one of these routers, and have it automatically connect to the phone and serve its sweet, sweet Internet over a Wi-fi connection? Better still, have it transparently proxy all connections so that nearly all Internet programs will function properly? Maybe even prioritize certain types of traffic, or encrypt everything so my wireless carrier can't spy on what Slashdot stories I like to read? All of those things would be just great. And all of those things are exactly those things which I set out to do (and/or enable you to do!) in this project.

A Few Details

Now wait just a minute. I said my phone cable was a USB cable. Shouldn't it not have been compatible with a USB-less cheap router such as the Motorola WR850G?

For an ordinary person it wouldn't have been. But with my super-hero powers I knew it would work. How, you ask? When the device was installed in Windows, it came up as a serial port (COM4, for example). This meant that inside the large blue USB connector there lay a USB to serial converter chip amongst some other possibly necessary hardware. Knowing as I do that the WR850G contains two serial ports, I set on destroying the USB connector on my phone cable in search of the proper signal lines to intercept.

Sounding out the serial connector

Being encased first in brittle epoxy and then again in soft plastic, I shaved away at the connector with my Xacto ripoff knife until I was able to expose the entire circuit board, here shown on the left. I was surprised to find five wires extending from the board to the phone end of the cable. Experience taught me that one of these wires would be a signal ground, a sort of reference for the other signals to work against. Two more of them would be each one transmit line and one receive line. The other two remained a mystery to me, and are still a mystery to this day.

After experimenting a little with a small piezoelectric speaker, I identified the correct signal lines and shunted them off to the WR850G's serial port. The other pins I had to leave connected to the board because they made some strange signal that made the phone recognize it as a data cable, I suppose. I opted not to try and replace the hardware and instead placed it inside the WR850G case with a trickle of power.

Little did I know that that was the easy part. In case you're wondering, the actual solder points for the WR850G's second serial port are on the underside of the PCB. I'm not trying to fake you out. Or am I?

The Down and Dirty, Baby

I must warn you, from here on I will discuss the bitter details of my implementation. They may only be of value to those who wish to duplicate my work. However, I will be dotting it with interesting pictures, so there's something for everyone! Don't miss the links to other crap that I do on the bottom of the page.

Serial port setup

The WR850G's second serial port does not naturally come with an IRQ number, which makes passing any amount of high-speed traffic through it nearly impossible. This is rectified by downloading and installing the setserial package, which can set the IRQ for a specific serial port. The specific file I used to set up the serial port was:

File: /etc/init.d/S15serial rwx
#!/bin/sh
setserial /dev/tts/1 irq 3

Linux dial-up networking

The Internet was a huge help on this one. Searching for things like "linux dial-up" quickly educated me on how to create a connection with a serial modem (which is what compatible phones 'look like' at the serial port) on Linux. I needed to use pppd and chat to establish the connection (pppd comes with OpenWRT, and chat is usually found in the chat package). Sounds easy enough - but it was difficult to get all of the directives and scripts just right to have a semi-foolproof connection. What I wanted was for the user to be able to connect the phone at any time, disconnect it, reconnect it, basically abuse the AP any way they wanted and the AP would always provide them with Internet as much as it could. Here's what I ended up with:

File: /etc/ppp/peers/gprs rw-
nocrtscts
noauth
user ""
lock
defaultroute
usepeerdns
asyncmap 0xa0000
xonxoff
lcp-echo-interval 5
lcp-echo-failure 2
maxconnect 1800
idle 300
bsdcomp 10, 10
deflate 10, 10
predictor1
tts/1
115200
connect 'chat -f /etc/ppp/chatscript'
.
Don't use RTS or CTS lines (they don't hook to the phone)
Don't authenticate (the phone performs the authentication)
No username (this might change for different wireless providers)
Create a lock file (not strictly necessary)
Set the default Internet route to the dial-up interface (ppp0)
Get DNS servers and put them in /etc/resolv.conf
Make sure not to accidentally use XON/XOFF characters
Use XON/XOFF flow control
Ping the phone every 5 seconds
We're disconnected if two pings don't return
Stay connected for max 30 minutes
Close an idle connection after 5 minutes
Try BSD compression if possible
Try Deflate compression if possible
Try Predictor1 compression if possible
Use serial port 2 (/dev/tts/1)
Connect to the phone at 115200 baud
Use /etc/ppp/chatscript to connect

File: /etc/ppp/chatscript rw-
TIMEOUT 10
ECHO ON
ABORT '\nBUSY\n'
ABORT '\nNO ANSWER\n'
''       +++ATH0
OK       ATZ&K4
OK       AT+CGDCONT=,,"wap.fruitbar.com"
OK       ATD*99#
CONNECT  ''
ECHO     OFF
.
Only wait 10 seconds for each response
Useful for debugging, prints what the modem says
Abort if we see "BUSY" on its own line
Likewise for "NO ANSWER"
First, say "disconnect and hang up"
If that worked, say "reset and use XON/XOFF"
Set up GPRS ("user","pass","wap gateway")
Dial the GSM GPRS magic number
Wait until the modem says "CONNECT"
Turn off echo for some reason

There you have it - alone, these scripts can be invoked with "pppd call gprs", and while debugging you can use "pppd call gprs nodetach debug" to view extra debugging information as it connects.

The gprsd connection daemon script

I could have stopped there. At that point all I had to do was ssh into the router, type "pppd call gprs" into the prompt after connecting my phone, and I'd be ready to set up proxying and such. But that wasn't what I wanted. I wanted to have a daemon always trying to connect or reconnect, and some way of reporting the status of the connection to the user. I then constructed a simple shell script that moves between several states:

When it reaches the end, it moves back to the initial state. Also, at each step the file /tmp/gprs-status is updated with the current state. Have a look:

File: /usr/sbin/gprsd rwx
#!/bin/sh
#Function returns 1 if pppd is running
ppprunning () {
 if [ `ps | grep pppd | grep -cv grep` -eq 0 ]
  then return 0
  else return 1
 fi
 }
#Function inverts ppprunning, for convenience
pppnotrunning () {
 if ppprunning
  then return 0
  else return 1
 fi
 }
#Function reports status to console and to file
status () {
 echo gprsd: $*
 echo $* > /tmp/gprs-status
 }

#Insert the relevant PPP modules in the right order
insmod slhc
insmod ppp_generic
insmod ppp_async

#Loop forever
while test 1
do
 #Kill old pppd
 if killall -HUP pppd 2>/dev/null
  then status Killing pppd in preparation for reconnect
   sleep 2
   while killall pppd 2>/dev/null
   do
    sleep 1
   done
   sleep 2
  fi

 status Waiting for a cell phone to connect
 until chat -f /etc/ppp/phonecheck %lt; /dev/tts/1 > /dev/tts/1
  do
  echo Beep > /dev/null
  done
 mkdir /var/lock 2>/dev/null 1>/dev/null
 status Opening the connection
 pppd call gprs
 until [ `ifconfig ppp0 2>&1 | grep -c RUNNING` -eq 1 ]
 do
  sleep 1
  if pppnotrunning
   then
    status GPRS connection failed
    break
  fi
 done

 status Setting up tunnel to the Internet
 socksify
 status Connected
 while [ `ifconfig ppp0 2>&1 | grep -c RUNNING` -eq 1 ]
 do
  sleep 1
 done
 status Restarting
done

File: /etc/ppp/phonecheck rw-
TIMEOUT 1
''	+++ATH0
OK	''

The transparent proxy

The transparent proxy was a serious hassle to get working right, mostly because I tend to forget how to use iptables. The basic concept is that any connection toward the Internet that is on a blocked port will be redirected to a local port, where a "transparent proxy" is listening. The proxy client will read the original destination from the connection, and open a new connection to the proxy on a non-blocked port, instructing the proxy server to connect to the original destination.

That all sounds easy enough. And it would have been, for a Linux expert. I busted my humps getting this script to work. But now you can enjoy its benefits! I originally used transocks as the transparent proxy client, but its fork-based server could only handle something like 12 connections before filling up the poor router's RAM. I found a more obscure transparent socks proxy program called mtsp that worked using select and took way less memory. This is what I ended up using.

File: /usr/sbin/socksify rwx
#!/bin/sh
#Restart the transparent proxy, guard against memory leaks and such
killall mtsp
mtsp -l 1211 -S (my proxy server IP) -s (my proxy server port) &

#Restart dnsmasq to have it use the new DNS servers
killall dnsmasq
/etc/init.d/S50dnsmasq

#Fill these with your local network info; AUX_NET is just a second local net
LOCAL_NET=192.168.1.0/24
AUX_NET=192.168.0.1/24
LOCAL_IP=192.168.1.1

#Clear the nat table (normal firewall rules still apply)
iptables -t nat -F
#Function to both call iptables and to print out what it would run
ipt () {
 echo iptables $*
 iptables $*
 }

#Delete and recreate the SOCKSIFY chain
ipt -t nat -X SOCKSIFY
ipt -t nat -N SOCKSIFY
#Exceptions - don't socksify these because the ports are open
#Note - it's CRITICAL that one of these be the one the SOCKS proxy is on
 #Secure POP3
 ipt -t nat -A SOCKSIFY  -p tcp --dport 995 -j RETURN
 #SMTP
 ipt -t nat -A SOCKSIFY  -p tcp --dport 25 -j RETURN
 #POP3
 ipt -t nat -A SOCKSIFY  -p tcp --dport 110 -j RETURN
 #Secure IMAP
 ipt -t nat -A SOCKSIFY  -p tcp --dport 993 -j RETURN
 #IMAP
 ipt -t nat -A SOCKSIFY  -p tcp --dport 143 -j RETURN
 #Secure SMTP
 ipt -t nat -A SOCKSIFY  -p tcp --dport 465 -j RETURN
#Local traffic
 ipt -t nat -A SOCKSIFY  -p tcp --dst $LOCAL_NET -j RETURN
 ipt -t nat -A SOCKSIFY  -p tcp --dst $AUX_NET -j RETURN

#Past all the exceptions, redirect it to the proxy
ipt -t nat -A SOCKSIFY -p tcp -j DNAT --to-destination $LOCAL_IP:1211

#Socksify traffic routing through this host:
ipt -t nat -A PREROUTING -p tcp -i br0 -j SOCKSIFY

#Socksify traffic originating from this host
ipt -t nat -A OUTPUT -p tcp -j SOCKSIFY

Bringing it all together

Alright, so I have:

  1. A way to connect to the Internet via my mobile phone
  2. A way to maintain that connection at all costs
  3. A way to proxy all the traffic from clients onto the connection
Just some standard configuration left, to have the router pipe out an unencrypted network and start gprsd when the router boots. Now I have unlimited, cheap, slow internet everywhere I go! I'm happy with it.

Exercises for the reader

There are a lot of things you could do with this platform. How might one:

Conclusion

Well there you have it. Another inarguably awesome hack from the natetrue.com labs. Be sure to check out some of the other crap I've done, because there's a bunch of it.

Where to go from here

Copyright © 2005 by Nathan True. All rights reserved.