最近想搞个无线路由,linux下的无线路由/无线AP的实现就是 hostapd 这个软件了。

网上有很多关于 hostapd 的介绍,百度一下就能得到很多相关的信息,这里只是整理我自己配置hostapd的一步骤,过程中也遇到大大小小的坑,方便以后查询避免。

硬件部分

AP的工作模式我们只需要一块无线网卡和一块有线网卡。无线网卡PCI接口或者USB接口的都可以,有线网卡通常集成在主板上或插在主板上百兆/千兆的速率,市面上也很常见。

一般linux系统内核默认就已经支持绝大多数的硬件型号并且工作良好,如果遇到内核无法识别的网卡型号,就需要自己手动安装驱动模块或者手动编译。搞定驱动的方法及相关步骤并不在本文的讨论范围之内。

要使用AP模式无线网卡首先要支持AP模式才行。如何检测无线网卡是否支持AP模式,可以通过下面命令查看:

iw list
[root@server ~]# iw list
Wiphy phy0
……省略……
 Supported interface modes:
   * IBSS
   * managed
   * AP                                    #说明无线网卡支持AP模式
   * AP/VLAN
   * monitor
……省略……

我的Intel Corporation Centrino Wireless-N 105 无线网卡支持5种,AP模式也在受支持的范围。

软件部分

我用的是 CentOS 7 的系统,目前已经更新至 CentOS 7.1, 官方实际上并没有提供hostapd的软件包,要使用hostapd这个软件的第一步就是要启用EPEL的源。

关于EPEL源的介绍请自行百度或看看《CentOS 7 安装EPEL源》

1、安装 EPEL 源

yum update                            #先更新系统
yum install epel-release              #安装EPEL源

2、安装 hostapd 软件

我们可能不知道系统提供哪些有关hostapd的软件包,可以先搜索一下有哪些包含hostapd的软件包。

当然如果没有安装并启用EPEL源的话将无法通过 yum search <软件包名字符串> 命令搜索到任何结果。安装并启用EPEL源后使用下面命令搜索。

yum search hostapd
[root@server ~]# yum search hostapd
已加载插件:fastestmirror, remove-with-leaves
Loading mirror speeds from cached hostfile
============================ N/S matched: hostapd ============================
hostapd-logwatch.x86_64 : Logwatch scripts for hostapd
hostapd.x86_64 : IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator

从上面可以看到hostapd.x86_64就是我们想要的软件包,使用 yum 进行安装。

yum install hostapd

那么接下来配置使用 hostapd 就是从他的软件包中的文件入手。因此要先查看hostapd软件包所提供文件列表,使用 rpm -ql <软件包名>进行查询。

rpm -ql hostapd
[root@server ~]# rpm -ql hostapd
/etc/hostapd
/etc/hostapd/hostapd.conf                        #最主要的配置文件
/etc/sysconfig/hostapd                           
/usr/lib/systemd/system/hostapd.service          #服务脚本
/usr/sbin/hostapd                                #主要的命令
/usr/sbin/hostapd_cli
……省略……
/usr/share/doc/hostapd-2.4/hostapd.conf          #该文件夹下包含相关配置示例一定要看
……省略……
/usr/share/man/man1/hostapd_cli.1.gz             #man手册
/usr/share/man/man8/hostapd.8.gz

3、确保无线网卡没有被 NetworkManager 接管

在安装好无线网卡后,如果没有连接过任何无线接入点(如无线路由器、其他wifi等)可以直接看下一步。


坑提示:如果是 NetworkManager 管理的无线网卡,是无法启动 hostapd 服务的。我们可能想要无线网卡既能连接其他无线接入点(如无线路由器、其他wifi等)又能供其它手机等客户端连接,需要在 hostapd.conf 配置文件中设置。 


未连接过任何无线接入点(如无线路由器、其他wifi等)的情况下 NetworkManager 中显示的无线网卡的状态默认是“不可用”的。通过 nmcli device show 命令就可以查看到,只要确保无线网卡的状态为“不可用”或“未管理”就可以,就像下面这样。

nmcli device show
[root@server ~]# nmcli device show 
……省略……                   
GENERAL.设备:                           wlp2s0
GENERAL.类型:                           wifi
GENERAL.硬盘:                           80:5B:22:D0:7C:64
GENERAL.MTU:                            1500
GENERAL.状态:                           20 (不可用)
GENERAL.CONNECTION:                     --
GENERAL.CON-PATH:                       --

那如果有连接过其他的无线接入点(如无线路由器、其他wifi等),那有两种方法可以用。

第一种:使用 nmcli 命令删除与无线网卡接口对应的无线连接配置

先用 nmcli connection show 查看系统已存在的连接配置。

nmcli connection show
[root@server ~]# nmcli connection show 
名称             UUID                                  类型             设备   
wifi-wlp2s0      f921eace-fe96-446e-a70c-7f707c3370af  802-11-wireless  wlp2s0
p2p1             54fec36f-6103-4342-aca1-4aabd42ee999  802-3-ethernet   p2p1

删除无线网卡对应的连接配置 wifi-wlp2s0,注意这里对应的无线网卡接口为:wlp2s0。

nmcli connection delete wifi-wlp2s0
第二种:修改 NetworkManager 配置文件

通过修改配置文件使 NetworkManager 取消自动接管无线网卡,配置文件通常位于 /etc/NetworkManager/NetworkManager.conf。

vi /etc/NetworkManager/NetworkManager.conf
[root@server ~]# vi /etc/NetworkManager/NetworkManager.conf
[main]
plugins=ifcfg-rh                    #这行系统默认就有如果不清楚就不要修改
                                    #添加下面两行指定排除的MAC地址,MAC地址可以有多个
[keyfile]                           #这里是排除了两个MAC地址的示例。
unmanaged-devices=mac:E0:05:CC:77:DF:B0;mac:80:5B:22:D0:7C:64

修改保存之后重启 NetworkManager.service

systemctl restart NetworkManager.service

重启服务后再次查看接口状态:

nmcli device show
[root@server ~]# nmcli device show 
……省略……                   
GENERAL.设备:                           wlp2s0
GENERAL.类型:                           wifi
GENERAL.硬盘:                           80:5B:22:D0:7C:64
GENERAL.MTU:                            1500
GENERAL.状态:                           10 (未管理)
GENERAL.CONNECTION:                     --
GENERAL.CON-PATH:                       --

4、启动或停止 hostapd 操作

如果需要开机自动启动 hostapd 服务

systemctl enable hostapd.service

手动启动

systemctl start hostapd.service

重启

systemctl restart hostapd.service

停止

systemctl stop hostapd.service

禁止开机自动启动

systemctl disable hostapd.service

5、hostapd AP模式配置

首先要说明的是:默认安装的 hostapd 是没有配置的并且无法启动。

通过上面 rpm -ql hostapd 命令可以看到,hostapd 软件包已经提供了 hostapd.conf 的最全最详细的说明,也就是上面软件包文件列表中的 /usr/share/doc/hostapd-<版本号>/hostapd.conf 这个文件,只不过里面全是英文的。有关 hostapd.conf 的中文说明可以看看《CentOS 7 之 hostapd.conf 配置说明》

按照我们要求 hostapd 正常启动并工作且满足下面几点:

  1. 工作在AP模式

  2. 连接时要求输入密码

工作在AP模式就需要有线网卡和无线网卡进行桥接,这就要求我们首先要建立一个桥接接口。

使用 nmcli 命令来配置:

首先使用 ip link 命令就可以看到哪些本机已经识别是网卡名称:

ip link
[root@server ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: p2p1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:14:78:66:2e:a7 brd ff:ff:ff:ff:ff:ff
3: wlp2s0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
    link/ether 90:94:e4:78:49:b5 brd ff:ff:ff:ff:ff:ff

使用 nmcli 建立一个桥接接口 br0 并设置开机自动连接,“br0”可以自由设定,只要保证上下配置一致就可以。为了方便通用,一般桥接接口都是用这种方式命名。

nmcli connection add type bridge autoconnect yes save yes ifname br0

将有线接口 p2p1 加入到桥接接口 br0 中,CentOS 7 中的网络接口默认不再像以前 eth0 eth1 等这种方式命名,而是会加上总线顺序等来进行命名,我这里是的PCI 千兆网卡为 p2p1 有些主板上会类似 enp2s0 这种。

nmcli connection add type bridge-slave autoconnect yes save yes ifname p2p1 master br0

查看接口

[root@server ~]# nmcli connection show 
NAME               UUID                                  TYPE            DEVICE
bridge-br0         bc7e63a4-7fee-4419-8f09-e316a78f42e7  bridge          br0
bridge-slave-p2p1  59fc1f91-4e60-4388-ad41-1a4937c8ff25  802-3-ethernet  p2p1


坑提示:实际上到这一步就可以了,这里我们只建立了一个只有一个有线接口的桥,并没有包含无线接口。而事实上 nmcli 命令也并不支持将将无线接口加入网桥接口 br0 无线接口加入网桥就只能通过 hostapd.conf 来进行。


虽然将无线网卡接口加入网桥的命令可以正常执行。

nmcli connection add type bridge-slave autoconnect yes save yes ifname wlp2s0 master br0

但显示网络连接时注意 DEVICE 字段,新添加的无线网卡的桥接的 DEVICE 字段为“--”空。

nmcli connection show
[root@server ~]# nmcli connection show 
NAME                      UUID                                  TYPE            DEVICE
bridge-br0                bc7e63a4-7fee-4419-8f09-e316a78f42e7  bridge          br0
bridge-slave-p2p1         59fc1f91-4e60-4388-ad41-1a4937c8ff25  802-3-ethernet  p2p1
bridge-slave-wlp2s0       18880002-44c1-4a84-968a-66670c00322f  802-3-ethernet  --

当激活连接时会提示未找到设备。

nmcli connection up bridge-slave-wlp2s0
[root@server ~]# nmcli connection up bridge-slave-wlp2s0 
Error: no device found for connection 'bridge-slave-wlp2s0'.

好吧……删掉没有用的无线桥接连接。

nmcli connection delete bridge-slave-wlp2s0


下面继续:

之前有提到过有关 hostapd.conf 的中文说明可以看看《CentOS 7 之 hostapd.conf 配置说明》

这里只是一个最小化的配置:

# /etc/hostapd/hostapd.conf 最小化配置
interface=wlp2s0
bridge=br0                              #无线网卡桥接到 br0 就是通过这个参数来完成
driver=nl80211
ssid=test
hw_mode=g
channel=1
auth_algs=3
ignore_broadcast_ssid=0                 # 是否广播,0 广播
wpa=3
wpa_passphrase=12345678                 # 无线连接密码


坑提示:我在上面的提示中提到过,之前我们只建立了一个只有一个有线接口的桥。请注意上面 bridge=br0 选项,这个非常重要,如果要运行AP模式就一定要指定要桥接的网桥接口。bridge=br0 选项说明将无线网卡接口 wlp2s0 加入到网桥 br0 ,无线网卡接口由第一行 interface=wlp2s0 选项指定。这样 br0 才是一个包含有线接口 p2p1 和一个无线接口 wlp2s0 的网桥。


其他命令方式进行配置:

虽然还有其他方式建立网桥的命令,但是如果是在 CentOS 7 下面,最简单的还是使用 nmcli 命令,因为 CentOS 7 默认提供 NeteorkManager 这个软件,使用 nmcli 命令配置好连接后一直有效。但 nmcli 也并不是万能的,前面有提到过,我目前遇到了两个问题:1. nmcli 不支持将无线网卡加入到网桥;2. 到目前为止 nmcli 不支持设置无线网卡静态IP地址(这个在 hostapd 配置路由模式会遇到)。

关于 CentOS 7 桥接网络配置可以看看《<<<<<<这篇文章>>>>>>>》。

启动 hostapd 服务

到此我们已经配置了网桥,网桥将自动从路由器获取IP地址、网关及DNS等设置,也就是本机将自动就能上网。hostapd 也配置好了,SSID为test,密码12345678。因为是桥接接口,所以当无线客户端连接成功后也将自动从路由器那获取IP地址、网关及DNS等设置。

现在是时候启动 hostapd 服务了。

systemctl start hostapd.service

而结果确实启动失败,查看服务状态:

systemctl status hostapd.service
[root@server ~]# systemctl status hostapd          
● hostapd.service - Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
   Loaded: loaded (/etc/systemd/system/hostapd.service; enabled)
   Active: failed (Result: exit-code) since 一 2015-09-21 20:19:49 CST; 3s ago
  Process: 6897 ExecStart=/usr/sbin/hostapd /etc/hostapd/hostapd.conf -P /run/hostapd.pid $OTHER_ARGS (code=exited, status=1/FAILURE)
 Main PID: 6897 (code=exited, status=1/FAILURE)
9月 21 20:19:49 server hostapd[6897]: wlp2s0: interface state HT_SCAN->DISABLED
9月 21 20:19:49 server hostapd[6897]: wlp2s0: AP-DISABLED
9月 21 20:19:49 server hostapd[6897]: wlp2s0: Unable to setup interface.
9月 21 20:19:49 server hostapd[6897]: wlp2s0: interface state DISABLED->DISABLED
9月 21 20:19:49 server hostapd[6897]: wlp2s0: AP-DISABLED
9月 21 20:19:49 server hostapd[6897]: hostapd_free_hapd_data: Interface wlp2s0 wasn't started
9月 21 20:19:49 server hostapd[6897]: nl80211: deinit ifname=wlp2s0 disabled_11b_rates=0
9月 21 20:19:49 server systemd[1]: hostapd.service: main process exited, code=exited, status=1/FAILURE
9月 21 20:19:49 server systemd[1]: Unit hostapd.service entered failed state.
9月 21 20:19:49 server systemd[1]: hostapd.service failed.

上面实际上看不出任何问题的具体细节。

6、hostapd 调试

先看看 man hostapd 的手册了解一下如何进行调试。

man hostapd
[root@server ~]# man hostapd
……省略……
hostapd [-hdBKtv] [-P <PID file>] <configuration file(s)>
       -h     Show usage.
       -d     Show more debug messages.             #调试选项
       -dd    Show even more debug messages.        #调试选项详细输出
       -B     Run daemon in the background.
       -P <PID file>    Path to PID file.
       -K     Include key data in debug messages.
       -t     Include timestamps in some debug messages.
       -v     Show hostapd version.
……省略……

看样子很简单大致就是上面的内容。那接下来以调试模式运行。

/usr/sbin/hostapd /etc/hostapd/hostapd.conf -d
[root@server ~]# /usr/sbin/hostapd /etc/hostapd/hostapd.conf -d
……省略……
Could not set interface wlp2s0 flags (UP): Operation not possible due to RF-kill
nl80211: Failed to set interface up after switching mode
……省略……


坑提示:“Operation not possible due to RF-kill”,那么 RF-kill 又是什么呢?关于 RF-kill 可以看看这篇《rfkill 无线设备软开关》


好吧,先安装 rfkill 软件包。

yum install rfkill

看看无线网卡是否被关掉了

rfkill list
[root@server ~]# rfkill list
0: phy0: Wireless LAN
        Soft blocked: yes
        Hard blocked: no

解锁

rfkill unblock wlan
[root@server ~]# rfkill unblock wlan

再次运行调试模式

/usr/sbin/hostapd /etc/hostapd/hostapd.conf -d

OK一切正常,那么就可以结束调试以正常模式启动服务了

systemctl start hostapd.service

搞定。

7、配置小结

在 hostapd AP模式的配置中实际可能会遇到以及需要解决的问题就是网桥的配置,而且有点奇葩。