使用 OpenWrt 构建自定义固件

作者:Mike Petullo

OpenWrt 提供了一个环境,用于为各种嵌入式设备构建基于 Linux 内核的自定义固件。OpenWrt 最初的目标是 Linksys WRT54G 系列路由器,现在它为各种设备提供支持,包括 Openmoko 手机以及来自 Linksys、NETGEAR 和 D-Link 的路由器。本文重点介绍 Linksys WRT160NL 路由器,我选择它的原因是它支持 802.11n 无线网络、USB 连接以及价格合理。在设备的 8MB 闪存和 32MB 内存中,我将解释如何安装 Kerberos 身份验证服务器、LDAP 目录服务器、NFS 文件服务器、打印服务器和 iTunes 兼容的媒体服务器。

除了 Linksys WRT160NL 路由器之外,您还需要一个外部 USB 硬盘驱动器、一台 USB 打印机、一个 USB 集线器、一个构建工作站和一条定制的控制台电缆。为了帮助构建控制台电缆,您还需要一个连续性测试仪(通常作为万用表的功能提供)。前两项的总价不到 200 美元。任何 USB 打印机都应该足够,只要您的网络客户端支持它即可。构建工作站应该运行最新的 Linux 发行版。最后,控制台电缆是一条修改过的诺基亚 DKU-5 连接电缆;这种类型的电缆具有 USB 连接和嵌入式 USB 转串口适配器。在本文中,我使用 example.com 域名、someuser 用户帐户和 server.local 路由器主机名。您应该将这三项替换为您自己的名称。

本项目包含七个步骤:准备构建工作站、下载 OpenWrt 构建环境、配置和构建固件镜像、将固件镜像安装到 WRT160NL 上、配置外部 USB 磁盘、执行 WRT160NL 的安装后配置以及配置网络客户端。此外,本文还描述了如何使用控制台电缆救援配置错误的 WRT160NL。如果您在执行这些步骤时发现路由器在任何时候都无法启动,请跳到最后的章节。

使用 OpenWrt 构建固件镜像的第一步是准备您的构建工作站。OpenWrt 要求在构建工作站上安装 gcc、g++、binutils、patch、bzip2、flex、bison、make、gettext、pkg-config、unzip、glibc 头文件、libz 头文件、ncurses 头文件和 perl-XML-parser。所有主要的发行版都为这些项目提供了软件包,尽管软件包名称可能与上游标题略有不同。

在您的构建工作站上安装完所有必需的软件包后,使用以下命令下载 OpenWrt

svn co -r 20526 svn://svn.openwrt.org/openwrt/trunk

(在下载 OpenWrt 之前,您可能需要检查是否有更新的版本可用,并在 -r 选项中替换其修订号。)这将在当前工作目录中创建一个名为 trunk 的目录。使用以下命令进入此目录cd trunk。在内部,您将看到 OpenWrt 核心构建系统。其他软件包由 OpenWrt 所谓的 feeds 提供。通过执行以下命令拉取默认配置提供的 feeds

./scripts/feeds update

最后,使用以下命令完成构建可选软件包所需文件的安装

./scripts/feeds install krb5-server \
                        openldap-server \
                        nfs-kernel-server \
                        p910nd \
                        mt-daapd \
                        ntpd

第三步是配置您的固件并构建包含它的镜像。OpenWrt 构建环境类似于许多 BSD ports 系统、MacPorts 或 Gentoo Linux,因为它允许用户定义系统将下载和编译的软件包列表。与这些系统的通用用途不同,OpenWrt 通常必须交叉编译其软件包。例如,虽然我的构建工作站配备了 Intel Core 2 Duo 处理器,但 WRT160NL 路由器配备了 MIPS32 处理器。因此,在从源代码下载和编译通用软件包之前,OpenWrt 会从源代码下载并构建交叉编译器和其他构建工具。

OpenWrt 提供了一个配置系统,该系统与 Linux 内核的配置系统非常相似,可以使用以下命令调用make menuconfig。您可以使用箭头键导航基于菜单的配置工具,并通过按 Enter 键选择子菜单。按 Y 键激活项目,或者在一系列选择的情况下,按 Enter 键。相反,按 N 键取消激活项目。按 Esc 键返回上一个菜单屏幕。

make menuconfig命令提供的配置菜单中,首先选择 Target System(目标系统),然后选择 Atheros AR71xx/AR7240/AR913x 选项。将 Target Profile(目标配置文件)设置为 Linksys WRT160NL。在 Target Images(目标镜像)子菜单中,确保仅激活 squashfs。

激活 Advanced configuration options (for developers)(高级配置选项(针对开发者)),并在高亮显示此选项时按 Enter 键。选择 Toolchain options(工具链选项),然后再次按 Enter 键。取消激活 Build/install c++ compiler and libstdc++(构建/安装 c++ 编译器和 libstdc++),因为此示例构建的软件包都不需要 C++ 环境。

使用 Esc 键返回主菜单。选择 Base System(基础系统),然后选择 block-mount 和 block-hotplug。

返回主菜单并选择 Network(网络)。激活 Filesystem(文件系统)、nfs-kernel-server;Time Synchronization(时间同步)、ntpd;Printing(打印)、p910nd;howl-mdnsresponder 和 openldap-server。

返回主菜单并选择 Kernel Modules(内核模块)。激活 Filesystems(文件系统)、kmod-fs-ext3 和 USB Support(USB 支持)、kmod-usb-printer 和 kmod-usb-storage。

返回主菜单,选择 Extra Packages(额外软件包),然后激活 krb5-server。

返回主菜单,选择 Sound(声音),然后激活 mt-daapd。最后,按 Esc 键退出配置工具,确保在提示时保存您的配置。

现在您的 OpenWrt 构建已配置完成,执行以下命令make V=99以构建固件镜像。此过程需要很长时间才能完成,因为 OpenWrt 正在编译构建环境本身,然后编译 Linux 内核和所有固件程序。很可能,这将需要几个小时。

构建过程的结果是一个固件镜像,存储在 bin/ar71xx/openwrt-ar71xx-wrt160nl-squashfs.bin 中。假设您尚未替换 Linksys 的默认固件,则可以使用 Linksys 的固件升级工具将 OpenWrt 固件安装到您的路由器上。Linksys 固件提供基于 Web 的配置(图 1)。Linksys 固件的默认 IP 地址为 192.168.1.1,默认用户名为“admin”,默认密码为“admin”。通过将您的构建工作站添加到 192.168.1.0 网络来配置您的构建工作站后,将您的浏览器指向 192.168.1.1。单击 Administration(管理),然后单击 Firmware Upgrade(固件升级)。最后,单击 Choose File(选择文件),然后选择您刚刚构建的固件镜像,即 openwrt-ar71xx-wrt160nl-squashfs.bin。按照屏幕上的说明将 Linksys 的固件替换为 OpenWrt 固件。升级过程完成后,重启路由器。

Building Custom Firmware with OpenWrt

图 1. 固件升级实用程序

现在您已在路由器上安装了固件,现在是时候将注意力集中在将用作路由器数据存储的 USB 磁盘上了。将磁盘连接到您的构建工作站。您将在磁盘上创建两个分区,一个 64MB 的交换分区和一个跨越磁盘其余部分的文件系统分区。您可以使用以下 parted 命令执行此操作

$ parted /dev/sdX
 (parted) mklabel msdos
 (parted) mkpart primary 0 64
 (parted) mkpart primary ext3 64 -0
 (parted) quit
$ mkswap /dev/sdX1
$ mkfs.ext3 /dev/sdX2

请记住将 /dev/sdX 中的 X 替换为您系统上新连接驱动器的正确字母。最后,按如下方式创建目录骨架(假设 /mnt 是一个未使用的挂载点)

$ mount /dev/sdX2 /mnt
$ mkdir -p /mnt/Storage/Music /mnt/home /mnt/mt-daapd

现在,将您的音乐库复制到 /mnt/Storage/Music。

在您将注意力转向客户端之前,还剩下最后一步。路由器上的最后一步是安装后配置。将新初始化的磁盘、集线器和打印机连接到您的路由器,并重启路由器,路由器连接到您的构建工作站,但尚未连接到公共网络。确保您的工作站配置为使用 DHCP 获取 IP 地址。路由器启动完成后,使用以下命令连接到它telnet 192.168.1.1。使用以下命令更改 root 密码passwd。完成后,路由器将不再接受 telnet 连接。相反,您将使用安全 shell 连接ssh root@192.168.1.1.

现在您已登录到路由器,让我们暂停一下并解决您可能想知道的问题:下一次固件升级。安装 OpenWrt 固件后,您将无法再使用之前使用的 Linksys 固件升级工具。您将使用 OpenWrt 提供的命令行工具执行未来的固件安装。首先,使用scp命令将固件镜像复制到路由器的 /tmp 目录。然后,登录到路由器,并执行mtd -r write <镜像路径> firmware.

继续在路由器的命令提示符下工作,现在让我们创建九个配置文件。第一个文件配置路由器的 hostname 和时区,/etc/config/system

config system
    option hostname server.local
    option timezone  UTC

接下来的三个文件配置路由器的网络参数。首先,您将配置路由器的以太网设备。以下配置将导致所有五个以太网接口桥接以在一个网络 192.168.1.0 上执行交换。该配置将路由器的 IP 地址设置为 192.168.1.2(这与默认的 192.168.1.1 不同)。此配置假定 192.168.1.0 和上游网络之间的路由以及 Internet DNS 解析将由另一个 IP 地址为 192.168.1.1 的设备(例如,DSL 设备)执行

/etc/config/network:

config interface loopback
    option ifname  lo
    option proto   static
    option ipaddr  127.0.0.1
    option netmask 255.0.0.0

config interface lan
    option ifname "eth0 eth1"
    option type    bridge
    option proto   static
    option ipaddr  192.168.1.2
    option netmask 255.255.255.0
    option dns     192.168.1.1
    option gateway 192.168.1.1

WRT160NL 共有五个以太网端口,但上面的配置选项显示了两个

option ifname "eth0 eth1"

这是正确的。WRT160NL 的四个 LAN 端口执行交换功能,并且在 Linux 内核中统称为 eth0。内核将单个 WAN 端口称为 eth1。此配置将所有五个以太网端口桥接在一起,以在一个子网上执行交换功能。它还将交换机配置为充当主机,分配 IP 地址 192.168.1.2。应用此配置后,所有五个以太网端口都是等效的交换端口。

接下来,配置路由器的无线接口

/etc/config/wireless:

config wifi-device radio0
    option type     mac80211
    option channel  5
    option macaddr  <MAC-ADDRESS>
    option hwmode   11ng
    list ht_capab   HT40-
    list ht_capab   SHORT-GI-40
    list ht_capab   DSSS_CCK-40

config wifi-iface
    option device   radio0
    option network  lan
    option mode     ap
    option ssid     <SSID>
    option encryption psk2
    option key      <WPA2 KEY>

通过写入 /etc/config/dhcp 来配置 DHCP 服务

config dhcp lan
    option interface    lan
    option start        100
    option limit        150
    option leasetime    24h
    # GW, DNS:
    option dhcp_option "3,192.168.1.1 6,192.168.1.1"

config dhcp wan
    option interface    wan
    option ignore       1

config dnsmasq
    option leasefile   '/tmp/dhcp.leases'
    option resolvfile  '/tmp/resolv.conf.auto'

接下来,删除默认的 fstab,使用rm /etc/config/fstab,因为所有挂载和交换空间都将由热插拔系统动态设置。

使用 /etc/exports 配置磁盘的两个共享目录

/mnt/sda2/Storage *(fsid=0,rw,insecure,no_subtree_check,sync)
/mnt/sda2/home *(rw,insecure,no_subtree_check,sync)

通过创建 /etc/krb5.conf 来配置 Kerberos

[libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 24h
    forwardable = yes

[realms]
    EXAMPLE.COM = {
        kdc = localhost:88
        admin_server = localhost:749
        default_domain = local
    }

[domain_realm]
    .local = EXAMPLE.COM
    local = EXAMPLE.COM

OpenLDAP 的配置文件为 /etc/openldap/slapd.conf

include    /etc/openldap/schema/core.schema
include    /etc/openldap/schema/cosine.schema
include    /etc/openldap/schema/inetorgperson.schema
include    /etc/openldap/schema/nis.schema
include    /etc/openldap/schema/autofs.schema

allow bind_v2

pidfile    /var/run/openldap/slapd.pid
argsfile   /var/run/openldap/slapd.args

database   ldif
directory "/etc/openldap/ldif"
suffix    "dc=example,dc=com"
rootdn    "cn=Manager,dc=example,dc=com"
rootpw    "<PASSWORD>"

通过写入 /etc/mt-daapd.conf 来配置媒体服务器 mt-daapd

web_root        /usr/share/mt-daapd/admin-root
port            3689
admin_pw        <PASSWORD>
db_dir          /mnt/sda2/mt-daapd
mp3_dir         /mnt/sda2/Storage/Music
servername      server.local
runas           nobody
playlist        /etc/mt-daapd.playlist
extensions      .mp3,.m4a,.m4p

最后,使用 /etc/config/p910nd 配置打印机共享

config p910nd
    option device        /dev/lp0
    option port          0
    option bidirectional 1
    option enabled       1

由于 OpenWRT 有时会在内核初始化 USB 子系统之前启动服务,因此您需要进行最后一次修改。编辑 /etc/rc.d/S50mt-daapd 并添加sleep 5作为 start() 函数的第一行。这确保 mt-daapd 在内核意识到包含您的媒体文件的 USB 磁盘之前不会启动。

重启路由器以确保所有配置更改生效。

下一步是初始化路由器的 Kerberos 数据库。使用以下命令重新登录到路由器ssh root@192.168.1.2。使用以下命令初始化帐户数据库kadmin.local,这将提供一个交互式界面

$ kadmin.local
  > add_principal someuser
  > exit

返回到构建工作站,让我们初始化 LDAP 数据库。首先,创建一个名为 example.com.ldif 的文件,其中包含以下内容,一个以 LDIF 格式定义用户帐户和自动挂载配置的数据库

dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example Organization
dc: example

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: group

dn: cn=ldapusers,ou=group,dc=example,dc=com
objectClass: posixGroup
objectClass: top
cn: ldapusers
userPassword:: WFhYWA==
gidNumber: 1002

dn: uid=someuser,ou=people,dc=example,dc=com
uid: someuser
cn: Some User
objectClass: account
objectClass: posixAccount
objectClass: top
userPassword:: WFhYWA==
loginShell: /bin/bash
uidNumber: 1100
gidNumber: 1002
homeDirectory: /home/someuser
gecos: Some User

dn: automountMapName=auto_master,dc=example,dc=com
objectClass: top
objectClass: automountMap
automountMapName: auto_master

dn: automountKey=/home,automountMapName=auto_master,dc=example,dc=com
objectClass: top
objectClass: automount
automountKey: /home
automountInformation: auto.home

dn: automountMapName=auto.home,dc=example,dc=com
objectClass: top
objectClass: automountMap
automountMapName: auto.home

dn: automountKey=*,automountMapName=auto.home,dc=example,dc=com
objectClass: top
objectClass: automount
automountKey: *
automountInformation: server.local:/mnt/sda2/home/&

接下来,使用以下命令将文件加载到路由器上的 LDAP 数据库中

ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f example.com.ldif

最后,返回到路由器并创建 someuser 的主目录,mkdir /var/sda2/home/someuser,然后执行chown 1100:1002。请注意,chown 命令的 UID:GID 参数与上面 LDIF 文件中分配给 someuser 的参数匹配。现在您可以将路由器连接到您的真实网络。

要添加其他用户,请查看上面 LDIF 文件中的第五个块,为每个用户量身定制它,并使用以下命令添加它们ldapadd。此外,像以前一样创建每个用户的主目录。

您的路由器现在应该可以完全正常工作了,因此现在是时候配置客户端了。一些现有文章记录了如何配置客户端以在 LDAP 和 Kerberos 环境中运行(请参阅资源)。您可以通过编辑配置文件来配置客户端,也可以研究您的发行版的管理工具。

我遇到的一个难题与自动挂载器使用的 LDAP 模式有关。不同的 UNIX 版本使用不同的模式。我的说明使用 Mac OS X 使用的模式,因为它也在 Fedora 上受支持。为了指示 Fedora 自动挂载器使用此模式,请将以下内容写入 /etc/sysconfig/autofs

MASTER_MAP_NAME="auto_master"
TIMEOUT=300
BROWSE_MODE="no"
USE_MISC_DEVICE="yes"

# Mac OS X 10.5-compatible schema:
MAP_OBJECT_CLASS="automountMap"
ENTRY_OBJECT_CLASS="automount"
MAP_ATTRIBUTE="automountMapName"
ENTRY_ATTRIBUTE="automountKey"
VALUE_ATTRIBUTE="automountInformation"

其他发行版可能会以不同的方式配置自动挂载器。如果自动挂载器配置为使用适当的模式,它将从您之前创建的 LDAP 条目中了解 NFS 提供的 home 共享,并按需挂载用户的主目录。

有关如何连接到网络打印机的说明,请参阅您的客户端系统的文档。您的 OpenWrt 固件将使用 HP Jetdirect 协议共享连接的 USB 打印机。Linux、Mac OS X、Windows 和许多其他操作系统都支持此协议。

iTunes、Rhythmbox 以及任何其他支持 DAAP 协议的媒体播放器都可以访问您的 OpenWrt 设备的音乐共享。兼容的播放器通常会将共享作为选项与本地音乐库列表一起显示。

如果您安装了有缺陷的固件,并且路由器处于无法启动的状态怎么办?这就是您的控制台电缆的用武之地。图 2 显示了已完成的控制台电缆以及未修改的 DKU-5。WRT160NL 上有三个点可以连接控制台电缆。第一个是 WAN 和 LAN 4 RJ45 插座内的两组相同的引线,与以太网引线相对。第二个是 WRT160NL 主板上的一个五针连接器。为了使用后一个接口,您必须打开 WRT160NL 的外壳,这将使设备的保修失效。

Building Custom Firmware with OpenWrt

图 2. 控制台电缆

图 3 提供了诺基亚 DKU-5 电缆连接器的图片。电缆的另一侧有一个 USB 连接器。将电缆剪成两半,使大部分长度在 USB 连接器侧。现在,露出诺基亚连接器侧的六根引线。使用连续性测试仪来识别六根引线中的哪四根对应于图 3 中注释的功能引脚。注意连接到每个引脚的引线的绝缘体颜色。现在将注意力集中到电缆的另一半,即带有 USB 连接器的那一半。露出与先前注释的颜色匹配的四根引线。将这些引线中的每一根连接到图 4 中标记的五个接线柱中的四个,确保引线和接线柱功能匹配。您可以使用 PCB 连接器、钩到皮考钩跳线或更原始的技术连接它们。

Building Custom Firmware with OpenWrt

图 3. DKU-5 连接器

Building Custom Firmware with OpenWrt

图 4. 路由器的控制台接口

将控制台电缆的 USB 连接器连接到您的构建工作站。在您的构建工作站上安装一个串行终端仿真器,例如 minicom,并运行该程序。将仿真器配置为使用八个数据位、无奇偶校验位和一个停止位。选择 115200 波特率。启动路由器并观察仿真器控制台。您应该看到路由器通过控制台接口打印诊断信息。密切注意通过控制台打印的消息,并在 U-Boot 引导加载程序提示您“Hit any key to stop autoboot.”(按任意键停止自动引导)时按下一个键。您应该看到 U-Boot 命令提示符,ar7100>。输入命令upgrade code.bin以指示 U-Boot 启动 tftp 服务器。返回到构建工作站命令行,输入命令tftp 192.168.1.1,然后

tftp> binary
tftp> put <firmware filename>

观察通过控制台界面显示的数据传输。返回到终端仿真器,并在 U-Boot 提示符下输入go

您使用此技术加载的固件可以是来自 Linksys 的官方固件,也可以是您构建的 OpenWrt 固件。

结论

本文演示了一种使用 Linksys WRT160NL 无线路由器提供 Kerberos、LDAP、网络文件系统、打印和媒体服务的方法。结果是为家庭或小型办公室提供的低成本网络服务器。OpenWrt 拥有广泛的可用软件包,因此围绕这个功能强大的平台开发许多其他解决方案是可能的。例如,Samba 可以实现与 Windows 客户端的紧密集成。另一个选择是 Netatalk,它提供原生 Mac OS X 文件共享,包括与 Apple Time Machine 备份软件的集成。Linux、开源应用程序和流行的网络硬件(如 Linksys WRT160NL)为开发创新设备奠定了坚实的基础。

资源

Craig Swanson 和 Matt Lung 的“OpenLDAP Everywhere”,LJ,2002 年 12 月(参见标题为“Configure the Linux LDAP Client”的部分):www.linuxjournal.com/article/6266

Alf Wachsmann 的“Centralized Authentication with Kerberos 5, Part I”,LJ,2005 年 1 月(参见标题为“Configuring the Clients”的部分):www.linuxjournal.com/article/7336

Mike Petullo 的“Serving Apples: Integrating Mac OS X clients into a Fedora network”,Red Hat Magazine,2008 年 1 月(演示如何配置 Mac OS X 客户端):magazine.redhat.com/2008/01/17/serving-apples-integrating-mac-os-x-clients-into-a-fedora-network

Mike Petullo 在美国陆军服役,喜欢使用创新的开源软件解决问题。他自 1997 年以来一直从事 Linux 工作,欢迎您在 mike@flyn.org 提出您的意见。

加载 Disqus 评论