内容


在 Linux 上构建无线接入点

定制解决方案提供了灵活性和可定制性 — 和学习的机会

Comments

在本文中,我将带您来了解构建运行 Linux 的无线接入点这一过程。我不会讲述每一行代码、每一个中间步骤以及每一个硬件细节;那需要一本书来讲解,而且到您读到它的时候,它已经过时了。本文的目的是:向您显示在您想这么做时,您将面临的问题和困难。对于本文,我们构建接入点,让它作为网桥运行;它的作用只是在无线网络和本地以太网之间转发数据包。这使得只要使用现有网络就能打开并连接无线设备 — 无需新的配置,也无需特殊路由。

为何“自寻烦恼”?

我或许应该从“为什么不要自寻烦恼”谈起。很显然,买现成的设备要比构建定制机器便宜得多。定制设备所需的硬件大约花了我 400 美元,并且这还不包括我所投入的时间可能创造出的价值。话虽是那么说,但构建自己的无线接入点有两个好的理由。

第一个理由是灵活性和可定制性。想要防火墙吗?没问题。定制路由呢?NAT 呢?所有这些都很容易做到。定制基于 Web 的配置呢?只需半小时的 CGI 脚本工作。如果您愿意,可以添加网络流量图。现成的设备可能有一个专用的仅适用于 Windows 的配置工具,因此不可能使用 ssh 来更改设置。您不能脱离 Web 服务器来运行 weblog。如果出了问题,您就必须等待“固件升级” — 这也许能够解决您的问题,也许不能够解决您的问题。

另一个可能更具说服力的理由是:它 很有趣,它是了解在运行嵌入式 Linux 系统过程中可能碰到的问题的好办法。可以把这看作是爱好者的一个测试项目,如果您为它编出一个极棒的应用程序,那么无论如何您完全能够从中受益。

需求

对于这个项目,我使用的计算机是 Soekris net4521 嵌入式系统。CPU 是一个 133Mhz 的 486 级处理器;处理能力足够了。这个 OS 装在 CompactFlash(CF)卡中。我需要一块无线适配器;我找了一块便宜的 LinkSys WPC11,它是基于 Intersil Prism 2 芯片组的。类似的系统也行。

要进行整个工作,您还需要 另一台Linux 机器,以格式化和配置闪卡。最好是一台膝上型计算机,不过如果您有一个可以在 Linux 下工作的 CF 读卡器,那么任何带有 USB 端口的计算机都可以工作。

至于软件,现有的软件包就基本上能够达到设备的要求,您也可以用一套旧的安装 CD 来从头做起,费尽精力地去完成任务。对于本文,我从 Pebble Linux 开始谈起,它是一个小型分发版,基本上能够立即满足我的需求。不过,调整设置以及可能会添加一些定制功能也有很多乐趣。从现在起,我将假定您已经具备使用 Linux 的一些基本经验:编辑文件、运行命令甚至可能会配置一个简单的网络。如果您没有这方面的经验,那么只要请您友好邻近的 Linux 高手吃块比萨,他可能就会帮您完成这一项目,如果您再给他一份奶酪的话,他可能会解释接下来的事情。

对于本项目,我使用 802.11b 无线标准,它是 Apple 在最初的 Airport 网络中所使用的标准,也是得到最广泛应用的无线标准。它的理论带宽为 11Mbps,也就是说只比慢速以太网快一点儿。实际带宽足以满足一般的宽频带。接收范围是可变的,但大多数人的接收范围可达后院或邻居家的房子。

项目计划

该计划被分成几个阶段;每个阶段的末尾都有具体且可测试的结果。在一个小时左右的构建内,每个阶段都应该是可管理的。

这些阶段包括:

  • 初始设置:引导嵌入式系统并提供控制台登录提示符。
  • 网络设置:启动网络并让它运行,使机器能够实际用作起作用的接入点。
  • 调整:开始漫长的更改和调试机器功能的过程。

初始设置

获得嵌入式系统。我使用的是 Soekris Net4521,但如果使用其它系统,如 Technologic TS-5500,过程可能也一样。如果您非常需要,可以使用一台旧的膝上型计算机!现在,重要的部件是 PCMCIA 插槽和磁盘,可以从另外一台机器上对磁盘进行格式化和配置。嵌入式系统大都使用 CF 磁盘作为其主驱动器。

您还需要一个主机系统。运行 Linux 的膝上型计算机可以担当此任务,采用运行 Linux 并支持 CF 驱动器的台式机也可以。我使用了一个已安装好的嵌入式系统,它带有一个 USB CF 驱动器,这在本质上与我们的要求相背,但实际上没有任何差异。

对于本项目,我使用了一块 128MB CF 卡。这一容量看起来很大 — 并且确实很大 — 但有一些空余空间总不是件坏事。讨论中的分发版(Pebble Linux)甚至可以相当好地驻留在 64MB 卡中。空余的空间稍后将用于安装其它“小玩艺儿”。

在将硬件装配到一起之后,引导主机系统。连接其中带有 128MB CF 卡的读卡器。这块卡应该显示为 sda;运行下面这条命令来测试这一点:

fdisk /dev/sda

您应该看到一个提示符。

现在,对磁盘进行分区。输入 p 以打印分区表。如果您的卡以前没有这样用过,那么它可能会显示一个 DOS 分区。输入 d 以删除该分区,然后会出现一个提示,这时输入分区号。使用 n 命令创建一个新分区;使用缺省的范围即可。输入 a 以将该分区标记为活动的分区,然后会出现一个提示,这时输入分区号。现在,输入 w 。现在您已将该驱动器分区完毕,其上只有一个 Linux 分区。

如果您正在膝上型计算机上使用 PCMCIA-to-CF 适配器,那么显示使用的是 hd 驱动器而不是 sd 驱动器。这也是对的;只是要使用它的正确名称。

接下来,格式化磁盘。执行这一操作的命令是 mke2fs /dev/sda1 。格式化完磁盘之后,挂装该磁盘。

现在,解压缩 Pebble 分发版。Pebble 的安装程序假定您先在其它磁盘上进行解压缩,然后再复制到新磁盘上。如果您不方便在目标系统上使用另一个磁盘,那么就必须编辑安装程序;您可以将 Pebble 分发版的归档文件解压缩至目标磁盘,然后在这个磁盘上本地更新脚本。如果正在使用的磁盘不是上面所建议的那一种磁盘,那么您必须为您的目标驱动器制作一个新的 lilo.conf 文件;复制 hdc 的 lilo.conf,然后替换掉设备名。如果您决定以手工方式引导系统,那么必须运行 lilo,生成 ssh 主机密钥,然后设置 root 密码。您可能还需要对某些其它的内核模块进行配置;/etc/modules.* 中提供了对一些系统的可能的配置。例如,/etc/modules.net4521 是用于 Soekris Net4521 系统的一组模块。

这里有一件棘手的事情,就是您的目标磁盘可能是目标系统中的另一个磁盘。所提供的 lilo 配置文件反映了这一点;它们指定一个磁盘,但接下来指定“bios 0x80”来警告 lilo:该磁盘将成为新系统上的主磁盘。与此类似,在新的 fstab 文件中,您要确保自己指的是正确的磁盘;在典型的嵌入式系统上,该磁盘将是 /dev/hda1 而不是 /dev/sda1。最后,请确保在 inittab 中设置了正确的控制台端口;对于 Soekris 机器,缺省的控制台速度是 19200kbps 而不是 Pebble Linux 所提供的 9600。

一旦这些都设置好了之后,您就应该有了一个完全能在您的目标系统上引导和运行的 CF 卡。在看到登录提示符之后,请登录然后四处看看。与 Pebble Linux 一起还提供一些有用的脚本,它们可以让您将根文件系统重新挂装为只读或读/写。缺省情况为只读 — 这对于您可能希望经常拔下设备的系统来说是再好不过了。

如果您位于一个带有 DHCP 的网络上,那么您可能会发现您的系统在其主以太网端口上已经有了一个 IP 地址。(在 Soekris Net4521 上,我将网线插在了 eth0。)这会在下一步中节省我们一些工作。

网络设置

对于接入点,我们真正需要的是一个简单的网桥;来自一个网络的数据包出现在另一个网络上,没有什么特别用途。这个机器不是路由器,也不是 DHCP 服务器或者任何别的东西,它只是一个网桥。当然,可以将它设置为 DHCP 服务器或者其它角色(这样的角色有许多种),但设置为网桥最容易。网桥仅仅在有线网和无线网之间传递数据包。这样,无线设备可以查找任何自己想要找的内容,就好像自己完全连接在物理网络上。

Pebble Linux 基于 Debian,因此这意味着它使用 /etc/network/interfaces。用 Google 可以快速地搜索到一组可供使用的样本命令:

清单 1. 构建网桥
   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

这看起来有点令人望而生畏,但确实一点都不难。接口本身是网桥(br0),使用 dhcp 进行配置,在 eth0(第一块以太网卡)和 wlan0(我们的无线网卡)之间起桥接作用。在启动该接口之前,有一组命令要运行(pre-up),在关闭该接口之后,有另外一组命令要运行(pre-down)。

在本例中,我们需要启动将要进行桥接的那两个接口,将我们的无线网卡置于“master”方式(使它成为接入点),然后构建一个网桥接口并将那两个接口连接到该接口上。完成之后,dhcp 限定符就使我们的机器自己通过 dhcp 获取一个 IP 地址。这实际上是可选的;网桥并不需要有自己的 IP 地址,因为它将透明地把数据包从一个接口转发到另一个接口。不过,如果它有自己的 IP 地址,那么我们就可以在网络上使用接入点本身了;这样做的安全性要差一些,但在用于演示方面会更有趣。

当我们关闭接口时,我们关闭了以太网端口,将它们从网桥上除去,然后除去网桥接口。我们必须先创建网桥接口,然后才能向它添加以太网端口,因此,现在我们先除去以太网端口,然后再删除网桥接口。

这一过程假定这些接口不是由任何其它机制来配置的,因此我们希望注释掉与 wlan0 或 eth0 有关的其它行,但我们确实使用了 /etc/pcmcia/hostap_cs.conf 来设置无线网卡的 ESSID(基站名称)。我们可以在用于 br0 的 pre-up 脚本中这样做,只是对于这块特定的卡,如果将 ESSID 和 WEP 密钥设置得太过于接近,那么卡就会挂起一会儿。(什么是 WEP 密钥?就是那个我们要加入一些内容的密钥。)

您可能认为,可以在 /etc/network/interfaces 中仅仅添上“auto br0”,然后会自动配置接口。遗憾的是,如果无线网卡是 PCMCIA 卡,那么在正常启动网络接口时,PCMCIA 卡的接口将不可用。因此,稍后我将在引导过程中处理这一问题。在 /etc/rc2.d 中创建一个名为“S99local”的文件。在该文件中,加入下面这一行:

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

实际上,--force 和 -v 这两个选项都是可选的。接口不应该立即启动,因此我们不需要 --force 选项。使用 -v 仅仅是为了让我们在配置期间能够看到正在运行的命令。

现在,保存所做的更改然后重新引导系统。如果一切按计划进行,那么现在您应该能够连接到我们刚刚建立的无线网络(网络标识为“test”),能够运行 DHCP 客户机并从常规的 DHCP 服务器获取 DHCP 服务。(如果不是这样,那么您的有线网络所使用的网块中的某个静态 IP 地址也能行。)

当然,这里有一个明显的缺陷:我们没有使用 WEP(有线对等保密,Wired Equivalent Privacy)密钥。WEP 理论上被认为会使您的网络很安全;实际上,它只会略微减缓入侵者的入侵速度。如果您不介意那些随意的过路人使用您的网络,那么没有 WEP 密钥也不是什么大不了的事情。但是,万一您介意,您就应该设置一个 WEP 密钥。为了做到这一点,我们:在 /etc/network/interfaces 中将 br0 设置中的 iwconfig 行更改为下面的样子:

pre-up iwconfig wlan0 mode master key s:blahblahblah1

它将密钥指定为 13 个字符(104 位)的字符串。有些网卡可能无法支持 104 位的密钥;在这种情况下,请使用 5 个字符(40 位)的密钥。如果您的无线网卡在您这么做的时候挂起了,那么请尝试在 /etc/network/interfaces 中用于设置无线密钥的那一行前面添加“pre-up sleep 5”。

现在,我们有了一个使用 WEP 和只读文件系统的无线接入点,因此您可以把它拆下来,再插回去,它将会启动 — 可能没有某些商业性接入点那么快,但它会再次启动,没有任何损失也不会丢失任何文件。

调整

以下内容才真正有趣。我们可以让这台机器做各种事情。传统的一个示例是 Web 服务器;媒体可能会把这种事物描绘成一台庞大的液体冷却的机器,它闪着光芒,机声隆隆;但您我都知道,它实际上只占用几兆字节的磁盘空间和对系统产生几乎无法察觉的负载。在这一节中,我们将使用 apt-get 来添加几个软件包(包括 Web 服务器),然后在这个新的本地 Web 服务器上开始运行 CGI 脚本。

让我们从获取当前软件包列表开始。运行 /usr/local/sbin/remountrw 将使我们具备本地介质的写访问权。接下来,我们运行 apt-get update 。该命令会下载大量数据(这就是为什么我们需要 128MB CF 卡的原因了) — 我们正在获取这个 Debian 版本可用的软件包的列表。

我们将要安装 Apache Web 服务器,这需要我们具有一点前瞻性;我们希望为日志文件分配一块空间,并且我们希望它位于临时磁盘空间中,并且具有读-写权限。创建一个名为 /var/log/apache 的新目录。因为 /var/log 实际上是 /rw/var/log 的符号链接,安装程序会在正确的地方创建它。接下来,运行 apt-get install apache 。在看到几个提示符时按回车键 — 哦!— 您有了一个 Web 服务器。访问这个 Web 服务器;您的 Web 服务器将位于分配给您的机器的 IP 地址上,并且将具有 Debian 所使用的缺省 Apache 配置。

遗憾的是,在每次重新引导时都会丢弃 /rw 文件系统。如果您希望日志文件下次也能够正确地被创建,那么就必须修改 /rw 文件系统的模板,即 /ro 目录。进入 /ro/var/log,然后创建一个名为 apache 的目录。现在,在重新引导之后,您的 Web 服务器应该已经启动并且正在运行。在我的系统上,Web 服务器占用了 63MB 空间 — 对于 64MB CF 卡,这可能太大了一点。

接下来做什么?CGI 脚本呢?转至 /usr/lib/cgi-bin。您必须挂装文件系统(具有读写权限)来创建脚本。让我们从 hello.cgi 开始:

清单 2. 您好,无线世界!
   #!/usr/bin/perl -w
   print <<EOH;
   Content-Type: text/plain
   Hello, world!
   EOH

保存该脚本,使它能够执行(模式为 755),然后尝试访问 Web 服务器上的 /cgi-bin/hello.cgi。

我们还可以做其它什么事情呢?想做什么就做什么。有了 Web 服务器和 Perl 之后,世界就会变得精彩。让我们添加另外一个名为 stats.cgi 的脚本:

清单 3. 获取统计数据
   #!/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

瞧!网络流量报告……虽然格式不是很好,但谁又在乎这个问题呢?编写这个脚本花了 30 秒钟。

嗯……如果我们想复查我们的配置,该怎么做?以下是 file.cgi:

清单 4. 仅仅作检查
   #!/bin/sh
   cat <<EOF
   Content-Type: text/plain
   EOF
   cat $1

不幸的是,将它称之为安全性漏洞有些轻描淡写。但它极好地演示了我们的无线接入点现在是多么的灵活。实际上,我使用该脚本来从系统删除别的脚本;这比使用 scp 要容易一些。

这些示例并不十分深奥;对 CGI 编程的详细讨论已经超出了本文的范围。这里只是为了给您一些启蒙思想。您可以在类似这样的机器上托管一个 weblog,但您可能希望使用某种辅助存储器来存放实际的数据文件。当然,您可以通过 NFS 挂装一个远程磁盘!

在我完成上述设置之后,我所使用的嵌入式系统(Soekris Net4521)有超过 36MB 的可用内存以及大约 50MB 的可用磁盘空间。对于很多存储需求而言,这些空间已经足够了,并且它还留出了足够的可用 CPU 时间用于运行各种小的服务。

结束语

首先,本项目比一开始可能听上去的要容易得多。这里的关键是在别人的工作之上进行构建。我在 Pebble 上进行构建。Pebble 在 Debian 上进行构建。这其中很多最困难的问题已得到解决。例如,可能需要进行为数不少的测试和重新引导来搞清楚如何构建一个从只读文件系统进行引导的系统。我们中有多少人真正记得在引导期间需要对哪些文件进行修改?例如,/etc/network/ifstate 实际上是由系统进行修改。日志文件很容易记住,但其它文件可能就比较难记住。类似地,获取满足 Apache 安装的最小相关性的安装过程由 Debian 软件包系统自动处理。

开放源码使得曾经需要几天或者几周的项目只需一个悠闲的下午就能完成。这使爱好者的项目变得不再不切实际,而且它也建立了一个好的原型;如果您正打算做某类嵌入式系统,并且希望它成为一个接入点,那么在准备好最初的硬件样本之前进行软件配置将是获取实践的好方式。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=22236
ArticleTitle=在 Linux 上构建无线接入点
publish-date=09012003