为什么要拿手机做路由器?因为我现在每天要带着一个火柴盒大小的路由器(703n)。它提供了一个f了q的无线网络,电脑,手机,平板等设备连接上这个无线网络之后之后就可以自由上twitter,看youtube。但是它还不够理想。,我不希望在拥挤的包里再塞一个设备,我还希望在路上只有3G网络没有USB电源的地方也可以刷刷twitter。最好的设备莫过于手机了。

手机拿来做fq路由器最大的缺陷在于,它不是一个路由器。最开始手机都是处于网络的终端,要么接收3G信号,要么接收wifi信号。后来技术发展之后,手机开始有了无线发射的功能,这个在iphone上叫personal hotspot,在android上叫softap。虽然手机能够发射无线了,但是其还不能承担路由器的功能。手机只要开始发射无线,本来连着的无线网络(上行无线)就会被断开。这样,手机要么只能做客户端,要么只能做无线热点。只有同时做客户端,又做无线热点才能满足手机做fq路由器的要求。有什么办法呢?最直接的办法是,手机用3G上网,然后提供无线热点出来。这个能力基本上现在所有的智能手机都可以做到了。但是3G上网多贵啊。

手机能不能既连着上行无线,又开启无线热点把***环境共享给其他的设备呢?这是我一直以来的一个梦想。如今梦想成真了。今天不谈fq这一块,单独来讲怎么把Android手机变成无线中继路由器。

何为无线中继?前面的描述并不是非常的精确。最精确的关于无线组网的文章是OpenWRT的 一文。我所说的无线中继是文章中的Routed Client Mode - Masqueraded。就是一个设备同时加入两个子网,用iptables的masquerade功能代理一个子网的设备去访问另外一个子网。masquerade一个更常用的名称是NAT。基本上所有的家用无线路由器都是这个模式的网络。

无线中继路由器与普通的家用无线路由器的组网有一个本质不同。普通的无线路由器上行走的一般是ADSL的pppoe,也就是有线网络。下行通过无线热点把有线网络的internet共享给其他设备用。无线中继不同,无线中继的上行是一个无线网络,一般就是家里那个连着猫的无线路由器共享出来的无线热点,而下行是另外一个无线网络。所以,无线中继路由器的配置要比普通的路由器更加麻烦。刷了OpenWRT操作系统的家用无线路由器(比如tplink 703n)可以比较容易的实现无线中继功能,因为OpenWRT自身设计就支持这样一种组网方式,而且其硬件也设计得非常通用(ar71xx)对于使用方式限制很少。一般无线硬件厂商把芯片分为三个等级,比如broadcom就分为手机bcm4334(Galaxy S3), 平板 bcm43241(Nexus 10),以及 固定基础设施(Infrastructure)bcm4360(Asus RT-AC66U)。OpenWRT适用的设备就是属于Infrastructure系列的无线芯片。这些路由器的芯片本来就是专业做无线热点的,所以支持无线中继就不奇怪了。但是手机与平板的无线芯片与这些路由器的无线芯片虽然是同一个厂家的,但是因为使用场合完全不同,支持无线中继就变得非常困难。

所以,虽然Android手机是一个非常理想的***路由器平台,但是仅仅把Android手机变成一个路由器就非常不容易。其间要跨过这么几道坎:

  • 手机无线芯片硬件本身是否支持无线中继
  • 手机的无线芯片使用的固件(运行在无线芯片上的小操作系统)是否支持无线中继
  • 芯片对应的驱动是否支持无线中继
  • Android上相关的启动命令是否在手机上存在
  • 与对应无线芯片相适应的配置无线中继的脚本

=== 用户态 ===脚本VV命令(iw, p2p-cli等) V[Via Netlink Socket]=== 内核态 ===V驱动 (比如bcmdhd)V[Via SDIO]=== 另外一个小机器 ==V固件 (比如fw_bcm4330.bin)VV硬件 (比如bcm4330)


第1、2、3点是你我无法搞定的。如果硬件本身不支持,哪怕是驱动的一个编译参数,普通用户,甚至是开发者都很难搞定。因为Linux的内核与驱动之间没有稳定的ABI,在一个linux上编译好的驱动没有办法拿到另外一个linux上去用。只要原厂的无线驱动不直接支持无线中继,那么哪怕我可以找出修改驱动的方式,要给千千万万种手机,不同的Linux内核配置编译合适的无线驱动简直是一个不可想象的事情。何况很多手机的内核都没有办法自己编译,如果要逼到去无线驱动的份上基本上就属于无解了。

无线芯片的固件是一个平时不会注意的东西。它比无线驱动还要底层。无线驱动只是一个操作木偶的提线人而已,真正干活的其实是无线芯片的固件。这个固件其实一个完整的操作系统,是一个独立的小机器。一个手机里起码有三个完整的机器,每个都有自己的CPU和内存与代码。第一个是显而易见的Android与CPU。第二个是基带(baseband)提供语音通话的。第三个是wifi芯片与其固件。所以,如果手机无线芯片的固件不支持无线中继,基本上也就无解了。因为所有的无线芯片的固件都不是开源的(哪怕对应的驱动是开源的)。而且芯片种类非常多,即便是同一个型号同一个批次的无线芯片,对应的固件都可能有好多种不同的版本(比如有的固件支持wapi,中国的无线标准)。硬件这一块我不是很懂。也许无线芯片真正到了硬件这个层次都差不多,没有什么支持不支持无线中继的问题。

好在我们解决不了的问题,Google可以帮我们解决。Google在Android 4.0中引入了对Wifi Direct的支持。而Wifi Direct就是这帮提供无线硬件设备的厂商搞的标准。于是乎第1、2、3就不成为问题了。手机原厂支持Android 4.0的,基本上都满足了Wifi Direct的标准了,也就很有可能支持无线中继。这个支持意味着:驱动支持,固件支持,硬件支持。我们需要做的,只是把启动的命令与脚本拷贝过来,执行一下就可以了。可以理解为挖掘了一个Android手机本来就支持,只是Android没有提供界面配置的一个“隐藏功能”。

Wifi Direct为什么可以解决无线中继的问题?Wifi Direct其实就是wifi技术的一个用户友好版本的一个封装。其实质就是在你离开无线网络环境的时候,可以用手机临时启动一个无线网络,然后你周围的朋友可以用手机加入你这个临时组建的无线网络,然后双方就可以干传大文件之类的事情了。其相对于蓝牙来说,带宽更大。相对于无线的ad-hoc组网方式更安全。除此之外,wifi direct还允许一个设备同时提供无线热点与做无线客户端。也就是可以在手机自身的无线网不断掉的情况下,通过wifi direct与其他设备传文件。但是这个特性有一个很严重的硬件限制,手机连接着的无线,与启动的无线热点必须是在同一个channel的(无线电频率相同)。这导致在实际使用过程中,两个设备都连接着各自的无线网(channel不同)的时候无法通过wifi direct传文件。这也就导致了很多wifi direct的实现干脆在启动wifi direct模式的时候先把无线网断了。不过Google与这些硬件厂商在设计的时候并不是这么想的。理想的情况是将来的硬件发展到可以支持multi-channel concurrency。就现状而言,原厂支持wifi direct的手机,都可以拿来做无线中继。

虽然wifi direct可以用来支持无线中继。但并不代表无线中继的唯一实现方式就是通过wifi direct的命令。家用无线路由器刷了OpenWRT之后也可以做无线中继。我们也没有看见这些路由器支持wifi direct啊。那是因为这些路由器的无线芯片支持linux 的 mac80211,简单来说就是用软件来管理无线芯片,无线芯片不用管太多,软件说发什么frame就发什么frame。那么手机上的无线芯片有支持mac80211的吗?还真有,那就是wl12xx系列(德州仪器TI出品)。比如wl1271, 这个芯片可比Android 4早很多了。当年红极一时的摩托罗拉里程碑用的就是这个芯片。但是遗憾的是,芯片与固件支持是不够的,还需要给力的驱动。wl12xx的mac80211驱动是比较晚的事情了,早期使用的驱动tiwlan_drv并不支持mac80211。所以除非有人愿意把新的wl12xx驱动backport给早期的手机,比如摩托罗拉里程碑,否则这些老手机是没法做无线中继的。不过新出的使用wl12xx系列芯片的设备都使用的是新的wl12xx驱动,比如说kindle fire。这些新设备不但支持无线中继无压力,甚至还可能可以用来做无线等更有意思的事情。

OK,我们现在已经了解到了大概的一个前提条件。要么手机原厂支持wifi direct,要么手机使用的无线网卡驱动是mac80211的。那么究竟这个配置过程是怎样的呢?这个就要分不同平台来说了。主流的手机无线芯片有四个系列(这个列表通过人工爬虫爬CM的github源代码库

  • 博通系(bcm):bcm4325, bcm4329, 【bcm4330, bcm4334, bcm43214】。
  • 德仪系(wl):【wl1271 等,统称wl12xx】
  • 山寨系(mtk):【mt6620,mt6628】
  • 高通系: wcn1312, wcn1314, ar6002, ar6003, 【wcn3660,未测试】

这四个系列中,前三个我都亲测可用的,高通系只有最新的平台(比如nexus 4用的那个)才有可能支持无线中继,因为设备还比较贵所以我没有买来测。在【】中的芯片是测试可用的,【】之外是希望比较渺茫的。

bcm与mtk的无线中继启动方式都是用wifi direct的命令。而wl的无线中继用的是mac80211的方法。高通系的启动方式我猜可能会与bcm4330的非常类似。无论是用哪种方式,过程原理都是类似的:

  • 无论用什么手段,搞出两个wifi interface,比如说默认都有一个wlan0的网卡,再弄一个ap0之类的出来
  • 保持wlan0的无线连接不动,想办法在新添加的wifi interface上启动一个无线热点
  • 给ap0配置本机的IP地址
  • 启动DHCP服务器,监听ap0,给连进来客户端分配IP地址
  • 设置本机的iptables规则(masquerade),让通过ap0连进来的客户端可以从wlan0走出去上网

目前的现状是,MTK的手机在我心目中已经把703n这样的迷你路由器pk下去了。比如说我现在用的联想P770手机,不过一千出头的售价,4.5的屏幕,有3500毫安时的电池,双卡双待,这本来已经够性价比的了。现在再加上一个无线中继当路由器,将来软件支持上来了,还可以做***路由器。拿着这样的一个手机怎么有点美军单兵武器的感觉。