Helping ordinary people create extraordinary websites!
GET OUR NEWSLETTER
Your Email:
 

Building a Wireless Access Point on Linux

By Peter Seebach
2005-04-12


Project Plan

This plan is broken into phases; at the end of each phase, there are concrete, testable, results. Each phase should be manageable within an hour or so of playing around.

The phases are:

• Initial setup: We get the embedded system to boot and to offer a console login prompt.
• Network setup: We get the network up and running, so the machine can actually be used as a functioning access point.
• Tweaking: We start on the long road to changing and adapting our machine's functionality.

Initial setup
Obtain an embedded system. I used the Soekris Net4521, but other systems, such as the Technologic TS-5500, are probably about the same experience. If you're desperate, you can probably use an old laptop! The important part, for now, is a PCMCIA slot and a disk you can format and configure from another machine. Embedded systems mostly use CF disks as their primary drives.

You'll also need a host system. A laptop running Linux will work, as will a desktop running Linux with a supported CF drive. Being perverse at heart, I used an already-installed embedded system with a USB CF drive, but it really doesn't make any difference.

I used a 128MB CF card for this project. That may seem huge -- and it is -- but it's always nice to have some spare room. The distribution in question (Pebble Linux) fits reasonably well even in a 64MB card. This spare room will be used later to install extra toys.

Once your hardware is together, boot your host system. Plug in a card reader with your 128MB CF card in it. The card should show up as sda; test this by running:

fdisk /dev/sda

You should see a prompt.

Now, partition the disk. Enter p to print the partition table. If your card hasn't been used for this before, it will probably show a single DOS partition. Delete it by entering d, and enter the partition number when prompted. Create a new partition, with the n command; the default range should be fine. Mark the partition as active by entering a, and enter the partition number when prompted. Now, enter w. You have now partitioned the drive to have a single Linux partition on it.

If you're using a PCMCIA-to-CF adapter in a laptop, your card will probably show up using the hd driver rather than sd. That's fine; just use the right name for it.

Next, format the disk. The command to do this is mke2fs /dev/sda1. Once it's formatted, mount it.

Now, extract the Pebble distribution. Pebble's installer assumes you'll have unpacked on another disk and will then copy over to the new disk. If you don't have another disk handy on your target system, you'll have to edit the installer; you can just extract the archive on your target disk, then update the scripts locally on it. If you're using a disk other than one of the suggested ones, you need to make a new lilo.conf file for your target drive; just copy the lilo.conf for hdc, and replace the device name. If you're determined to do things by hand, you need to run lilo, make ssh host keys, and set a root password. You also probably need to configure in some extra kernel modules; likely sets for a couple of systems are provided in /etc/modules.*. For instance, /etc/modules.net4521 is the set of modules to use with a Soekris Net4521 system.

One tricky thing here is that the disk you're targeting will likely be a different disk in the target system. The provided lilo configuration files reflect this; they specify a disk, but then specify "bios 0x80" to warn lilo that the disk will be the primary disk on the new system. Similarly, in your new fstab you'll want to make sure you refer to the right disk; in the typical embedded system, that will be /dev/hda1, not /dev/sda1. Finally, make sure you set up the right console port in inittab; for the Soekris box, the default console speed is 19200kbps, rather than the 9600 Pebble Linux shipped with.

Once this is all in place, you should have a CF card that will simply boot and come up on your target system. Once you have a login prompt, login and look around. There are some useful scripts provided with Pebble Linux to let you remount the root filesystem as either read-only or read/write. The default is to come up read-only -- very nice for a system that you may want to unplug a lot.

If you're on a network with DHCP, you'll probably find that your system has already come up with an IP address on its primary ethernet port. (On the Soekris Net4521, I plugged a cable into eth0.) This will save us some work in the next step.

Network setup
What we really want, for an access point, is a simple bridge; packets from one network show up on the other network, nothing special. The box isn't a router or a DHCP server or anything, it's just a bridge. It could, of course, be set up as a DHCP server or any of a dozen other things, but this is the easy way. A bridge will simply send packets from the wire to the wireless and back. That way, the wireless device looks for all intents as though it's simply attached to the physical network.

Pebble Linux is based on Debian, so that means playing around with /etc/network/interfaces. A quick Google search yields a sample set of commands to play with:

Listing 1. Building bridges


iface br0 inet dhcp
bridge_ports eth0 wlan0
pre-up ifconfig eth0 0.0.0.0 up
pre-up ifconfig wlan0 0.0.0.0 up
pre-up iwconfig wlan0 mode master
pre-up brctl addbr br0
pre-up brctl addif eth0
pre-up brctl addif wlan0
post-down ifconfig eth0 0.0.0.0 down
post-down ifconfig wlan0 0.0.0.0 down
post-down brctl delif br0 eth0
post-down brctl delif br0 wlan0
post-down brctl delbr br0
This looks intimidating, but it's really not bad at all. The interface itself is a bridge (br0), using dhcp for configuration, bridging between eth0 (the first ethernet) and wlan0 (our wireless card). We have a set of commands to run before the interface comes up (pre-up), and another set to run after it comes down (post-down).

In this case, we want to bring up the two interfaces we'll be bridging, put our wireless card in "master" mode (making it an access point), then build a bridge interface and attach those two interfaces to it. Once that's done, the dhcp qualifier makes our box obtain itself an IP address through dhcp. That's actually optional; the bridge doesn't need to have its own IP address, since it will transparently forward packets from one interface to the other. However, if it has its own IP address, we can use the access point itself over the network; this is less secure, but more fun to use for a demo.

When we shut the interface down, we turn off the ethernet ports, remove them from the bridge, and remove the bridge interface. We had to create the bridge interface before adding the ethernet ports to it, so now we remove them before deleting the bridge interface.

This procedure assumes the interfaces aren't being configured by any other mechanism, so we want to comment out other lines referring to wlan0 or eth0, although we do use /etc/pcmcia/hostap_cs.conf to set the ESSID (base station name) for our wireless card. We could do this in the pre-up script for br0, except that, on my particular card, if you set the ESSID and WEP key too closely together, the card hangs for a while. (What WEP key? The one we'll add in a little bit.)

You might think you could just put "auto br0" in /etc/network/interfaces and have the interface configured automatically. Unfortunately, if your wireless card is a PCMCIA card, its interface won't be available when network interfaces are normally started. So, we'll do it later during boot. Create a file in /etc/rc2.d called "S99local." In it, put the following lines:

#!/bin/sh
ifup --force -v br0

Both options are, in fact, optional. The interface shouldn't be up right now, so we shouldn't need the --force option. The -v is just there so we can see the commands that are being run during configuration.

Now, save your changes and reboot. If everything went according to plan, you should now be able to attach to the wireless network we just made, network ID "test," run a DHCP client, and get DHCP service from your regular DHCP server. (If you don't have one, a static IP address in the netblock that your wired network uses will work just fine.)

Of course, there's a glaring flaw here: We're not using a WEP (Wired Equivalent Privacy) key. In theory, WEP is supposed to make your network secure; in practice, it will only slow down intruders a little bit. Lacking one isn't that big a deal if you don't mind random passers-by using your network. But, just in case you do care, you'll want to set a WEP key. We do that by changing the iwconfig line in the setup for br0 in /etc/network/interfaces to this:

pre-up iwconfig wlan0 mode master key s:blahblahblah1

This specifies a key as a 13-character (104-bit) string. Some network cards may not be able to support a 104-bit key; in that case, use a five-character (40-bit) key. If your wireless card hangs when you do this, try adding "pre-up sleep 5" before the line in /etc/network/interfaces that sets the wireless key.

At this point, we have a wireless access point using WEP and a read-only filesystem, so you can unplug it, plug it back in, and it will come up -- not as quickly as some commercial ones, maybe, but it will come back up, with no damage and no lost files.

Tweaking
Here's where this gets really fun. We can make this box do all sorts of things. The traditional example is a Web server; it's the kind of thing the media likes to portray as a giant liquid-cooled machine with lights and an ominous humming sound; but which you and I know is actually just a few megabytes of disk space and a nearly imperceptible load on the system. In this section, we'll add a couple of packages, including the Web server, using apt-get, and start running CGI scripts on our new local Web server.

Let's start by getting a list of current packages. Running /usr/local/sbin/remountrw will give us write access to local media. Next, we run apt-get update. This downloads a fairly large chunk of data (which is why we needed a 128MB CF card) -- we're getting a list of the available packages for this version of Debian.

We're going to install the Apache Web server, which requires a little bit of forethought; we want to have a space for log files, and we want it in the read-write space on the temp disk. Make a new directory called /var/log/apache. Because /var/log is actually a symbolic link to /rw/var/log, it will be created in the right place. Next, we run apt-get install apache. Hit return at a few prompts and -- poof! -- you have a Web server. Go to it; your Web server will be at whatever IP address your box was assigned, and it will have the default Apache configuration Debian uses.

Unfortunately, the /rw filesystem is discarded on every reboot. If you want the log files to get created correctly next time, too, you'll have to modify the template for the /rw filesystem, which is the /ro directory. Go into /ro/var/log and make a directory called apache. Now, after a reboot, your Web server should be up and running. On my system, this brought me to 63MB in use -- probably too much to fit on a 64MB CF card.

What next? How about a CGI script? Go to /usr/lib/cgi-bin. You'll need to mount the filesystem read-write to create a script. Let's start with hello.cgi:

Listing 2. Hello wireless world!


#!/usr/bin/perl -w
print <<EOH;
Content-Type: text/plain

Hello, world!
EOH
Save this, make it executable (mode 755), and try visiting /cgi-bin/hello.cgi on your Web server.

What else could we do? Anything we want. Once you've got a Web server and Perl, the world's your oyster. Let's add another script, called stats.cgi:

Listing 3. Getting statistical


#!/bin/sh
cat <<EOF
Content-Type: text/html

<HTML><HEAD><TITLE>WAP Stats</TITLE></HEAD>
<BODY>
<H2>Stats:</H2>
<PRE>
EOF

ifconfig -a

cat <<EOF
</PRE>
</BODY>
</HTML>
EOF
Look! Traffic reporting... It's not well formatted, but who cares? It took 30 seconds to write.

Hmm... What if we want to review our configuration? Here's file.cgi:

Listing 4. Just checking


#!/bin/sh

cat <<EOF
Content-Type: text/plain

EOF

cat $1
To call this a security hole is to understate the point woefully. But it's a great demo of how insanely flexible our wireless access point is now. In fact, I used this script to get the other scripts off of the system; easier than using scp.

These examples aren't very in-depth; a detailed discussion of CGI programming is beyond the scope of this article. The point is just to give you a few starting ideas. You could host a weblog on a box like this, although you'd want to have some kind of secondary storage for the actual data files. Of course, you could mount a remote disk over NFS!

The embedded system I used (the Soekris Net4521) had more than 36MB of free memory and about 50MB of free disk space when I was done setting it up with the above. That's enough space for a lot of stuff, and it leaves enough CPU time free to run all sorts of small services.

Tutorial Pages:
» Custom Solution Offers Flexibility and Customizability -- and a Chance to Learn
» Why bother?
» Requirements
» Project Plan
» Conclusions
» Resources


First published by IBM DeveloperWorks


 | Bookmark
Related Tutorials:
» Secrets of the Wireless Elite: Alexei Polyakov
» Linux Wireless Networking
» A New Strategy of Language Pack Management for Wireless Apps
» Open Source Wireless Tools Emerge
» Getting Practical About Wireless Security, Part 1: Building a Wireless Sniffer with Perl
» Challenges and Opportunities in Mobile Games

Advertise with Us!


Tutorials Scripts Web Hosting Developer Manuals
Resources