由于家里那台华为的HG8245越来越不给力,虽然是自己的前东家出品,这产品也真不耐用,用后门上去可以发现经常性出现kernel分配skb不到导致上网时断时连,妈的内存只有一M空余了,当然,也许他们也知道这东西电信是不给开路由的,既然咱自己动手hack开了路由,就别怪这种后果。

于是最近花了一周晚上的时间,买了个PCDuino板,自己搭建了一个家用wifi路由器,由于我家基本不存在WLAN间互访的问题,少了个LANSWITCH影响不大,做个NAT Router,PCDuino跑的比较Happy,网速快的很开心;至于HG8245,俺将之改回了bridge模式,给俺透传个报文,目前跑的很欢。

废话少说,以下拉个清单,供有需要打造wifi router的朋友参考交流。

原材料汇总

  • PCDuino v1,v2集成wifi实则非常鸡肋,不必花冤枉钱
  • 802.11n USB WIFI无卡 (需支持AP模式),京东上购得EDUPEP-MS15002一款,只需39元,采用RTL8192CU芯片,支持2T2R实现300Mbps数据传递,对于我那只有12Mbps上的光纤,已是足足有余
  • HDMI to DVI转接线 (如显式器支持HDMI则直接买HDMI线即可)
  • 5V/2A DC电源 (本人拿IPAD充电器替代)
  • 旧笔记本上拆下来的320G硬盘,用来做下载机硬盘
  • 4G左右的SDCARD,虽然PCDuino自带4G NAND flash,但这玩意显得得保护得当,启动盘与系统盘还是复制到SDCARD上比较好

背景知识

以下是我总结下来的需要了解的一些背景知识,似乎有点多,但科班出身的咱们码农们,不少是熟之又熟啦。

  • 基础Linux操作系统知识
  • 基础网络知识(交换与路由)
  • 交叉编译
  • 内核编译、内核模块编译
  • iptables使用
  • routing/bridging
  • PPPoE
  • HostAP配置(实现wifi认证接入)

打造过程

  1. 复制系统到SDCARD

    双系统设计算是全志A10这款SoC的亮点,默认的Linaro系统接电启动可以通过Ctrl-Alt-F1进入文本模式,启动板子配置工具,此时可选择将NAND Flash上的系统拷贝到SDCARD上,A10在下次启动就可以根据SDCARD上是否存在启动文件而从SDCARD启动,从而避免对Nand Flash的寿命产生影响。

    此后除非把SDCARD上的内核弄坏,一般情况下就无需Nand Flash启动了。(二般情况下,我就犯了错,替换SDCARD启动分区上的内核文件时,没注意到大小不对,使得还需要用Nand Flash启动,手工挂载SDCARD启动分区,拷贝可用的内核予以修复,其实也并不难办,只是稍显麻烦)。

  2. 升级SDCARD上的系统

    玩过Debian系OS的话,对apt-get比较熟悉了,轻车熟悉升级一把即可,Linaro源里的包还算丰富,由于A10主频有1GHZ,并且自带1G内存,所以系统默认就带了编译工具,对于像我这里用到的RTL8192CU驱动编译的话,在PCDuino上直接就可以编译完成了,无需进行交叉编译。

  3. Wifi AP设置

    wifi AP配置的一切麻烦都来自于8192CU这看似性价比高的芯片,A10所用3.4.29+内核里的驱动虽能用,但用起来还是不够好,所以RealTek官方还是给出了自己的源码,虽然会增加麻烦,但所幸官方提供了包括修改过的HostAPD源码,编译下内核再编译个HostAPD,就可以搞定了。

    官方给出的驱动包里的东西已经比较清除了,Linksprite上的链接提供了板子上直接编译该驱动的方法,以下附上链接:

    PCDuino编译 8192CU驱动

  4. IPtables规则设置

    IPtables依赖的netfilter功能在PCDuino默认内核上是没有开启的,因此需要重新编译内核和内核模块,理论上可以直接在PCDuino上完成,但内核编译显得耗时过长,生命有限,能少折腾还是少折腾了。

    Linksprite上的链接提供了在X86_64 Linux上交叉编译内核的方法,从文章的链接中也可以找到如何替换SDCARD上内核的办法,以下附上链接:

    PCDuino交叉编译内核

    需要注意的是,因为8192CU驱动为我们自己编译,建议下完内核代码后,把这款驱动的编译修改到内核编译过程里,避免每次需要手工复制,并且如果是在板子上编译的内核模块,与新交叉编译的内核文件并不配套,导致不能顺利加载,影响wifi接入功能的顺利调试。

    因为家里有多台设备需要通过此wifi router上网,IP tables的作就就是在ppp虚拟口(在未完成PPPoE拨号时,这里可以用内置接口eth0替换,相当于在HG8245下面又做了一级NAT)和WIFI接口间进行NAT,目前只用到一条MASQUERADE规则即可:

    iptables -A POSTROUTING -t nat -o ppp0 -j MASQUERADE
    
  5. PPPoE拨号

    在之前的步骤中,我一直还是通过HG8245 DHCP接入上网的,当上述设置完成后,就可以恢复HG8245为桥接模式了,在PCDuino上通过内置的RJ45 100M端口,通过HG8245光猫PPPoE拨号出去,自此但可享受远离HG8245频繁掉线的困扰了。

    Debian/Ubuntu系统上PPPoe拨号相对比较简单,网上有大把流程,这里就不再赘述了。

陷阱(坑啊坑)

  • PPPoE与TCP MSS问题

    由于PPPoE这样Overlay在Ethernet(最近研究了太多的overlay技术了)上,显然是有额外的封装代价的(需要在正常的以太报文上再额外消耗8个字节),这样就会与TCP协商时的MSS产生冲突,TCP采取本地网卡的MTU来填写TCP报文的MSS,而大部分终端默认网卡MTU都是1500,这样就会有可能在PPPoE封包过程(设想终端发过来的报文刚好1500,再加8字节的封装就大于1500了)中产生大于运营商链路MTU的报文,从而使和报文被丢弃,直接症状就是视频或图片加较缓慢或不能加载,影响家庭用户心情。

    以下链接提供了较为详细的介绍,可供参考:

    MTU and PPPoE详解

    对此问题,Linux Iptables提供了TCP Clamping的功能,直白点就是动态干预调整TCP MSS字段的设置(另外一种方法基于path mtu discovery,但容易受现网环境影响,不必折腾),具体命令如下:

    iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1460
    

后记

PCDuino用着让人不爽的几个地方:

  • PCDuino V1有点大材小用,外置的一些如PWM接口、Arduino接口对WIFI router这个角色基本没用,全志A10实际上带了Audio DAC,然而却没有引入3.5mm插口,没有HDMI显示器的话,音频输出有点伤
  • PCDuino社区不如RaperryPI强大,Linaro这个For arm Soc的发行版也不怎么酷,A10的kernel源码还基于3.4.29+,比较旧
  • PCDuino V1所用A10的EMAC集成网卡驱动有点乱,也不支持DMA收发,有点无爱

基于Ubuntu的Linaro用着让人不爽的几个地方:

  • Upstart这套init系统用着有点不爽,看来被Systemd占了上风也是有道理的。

然而生命的意义就在于尝试和体验,折腾虽然累了点,但看着老婆上网相当开心的样子,我还是很满足的:)

成品照片

PCDuino wifi router


Comments

comments powered by Disqus