菜鸟初玩 openwrt

在一个月前其实根本不知道openwrt为何物,或许它曾在我眼前出现过,终因无缘被我淡忘。这次奇遇缘起寻找一款支持vpn的路由器,google中出现最多的就是openwrt ddwrt,对两者进行了简单了解,我觉得openwrt可能更合适一点,而且功能远不是当初我能想像的,有人给路由器扩展usb 结合wrt 搞出很多有趣的玩意,这让我想起了几天前刚刚看到的tplink一款3g无线路由器 wr703n ,正好有一个usb口,在openwrt的supported device中查找wr703n 还真找到了。不过wr703n这种配置是有点难受 32m ram 4m flash,随后在淘保找到一个店家,采购了一个ram升级到64m flash升到8m的版本。几日到手后开始了近一个月的研究折腾。

wr703到手后安装软件提示内核版本有差异不能安装的情况,随后刷了最新的openwrt,不久前安装软件又出现同样的情况。后来明白这是因为 openwrt一直处在活跃开发状态,几天就会有一个新的从trunk生成的快照版本,于是我做了一个2012年7月18号更新后packages的映像,不再用官方的源。所有包加起来才280M左右,是够mini的。

目前实现了 构建自定义软件包的固件;root 分区扩展;pulseaudio + usb 声卡支持;usb摄像头监控;脱机下载(包括迅雷离线);dlna/upnp媒体共享;xxxx(你懂的);ip变更邮件通知,ssh远程端口转发。结下来我开始一一介绍。

1.构建自定义软件包的固件
因为官方的固件一般都小于4m,所以连web界面都没集成进去,功能很有限,扩展了8mflash 怎还能容忍每次刷机后安装必备软件的麻烦。官方每发布一个固件和packages时都会生成一个 OpenWrt-ImageBuilder-ar71xx_generic-for-Linux-x86_64.tar.bz2 的包专门用于定制固件用的,下载后解压,直接执行:

make image PROFILE=TLWR703 PACKAGES="luci kmod-nls-cp437 kmod-nls-cp850 kmod-nls-iso8859-1 kmod-nls-iso8859-15 kmod-fs-vfat kmod-fs-ext4 kmod-fs-ntfs block-mount kmod-usb-core kmod-usb2 kmod-usb-ohci kmod-usb-storage usbutils"

命令执行完成,在当前目录下的bin目录中就能找到对应的固件。

2.root分区扩展
虽然升级到了8m flash也是不够用的,想要体验的软件太多,因此openwrt提供了 extroot的功能,把u盘分成两个区一个128m用来做swap,另一个 3.6g ext4分区,用作扩展root空间。这里有个不得不提的bug,openwrt swapon 一个非swap分区时 可能会破坏数据,所以我在fstat配置中使用了uuid来挂载root和swap,配置完成后在系统里看到/overlay 分区已经为3.6g,可是root分区还是5M。本以为是显示的bug,猛装软件空间很快被用完,随后在google的一个角落里看到了一个bug报告,并提供了patch。提到因为把blkid命令从busybox中移出了,脚本中没有引入环境变量,导致在系统启动过程中无法找到该命令,所以无法使用uuid挂载分区,给block mount 打上patch后终于成功(目前该bug已经在2012.7.18的版本中修复了)。在这提示下,虽然可以把整个root分区内容都搬到u盘上,但官方不建议这么做,只需要把overlay分区放到u盘即可。步骤如下:
/etc/config/fstab:

config global automount
option from_fstab 1
option anon_mount 1

config global autoswap
option from_fstab 1
option anon_swap 0

config mount
option target   /overlay
option uuid     1c92ce8f-aeef-4829-bd94-3027795915fd
option fstype   ext4
option options  rw,sync
option enabled  1
option enabled_fsck 0

config swap
option uuid     584a9e2c-eac0-430a-8ad3-9ce93d8acc00
option enabled  1

之后将u盘的ext4 分区mount到某处,如/tmp/udisk,然后将路由器 overlay 分区内容导入 u盘该分区:

tar -C /overlay -cvf - . | tar -C /tmp/udisk -xf -

重启路由器,df -h 即可看到 root分区被扩展到了3.6g。

3.pulseaudio usb声卡支持
pulseaudio是linux下的声音服务器,需要声音服务器的软件把音频数据发给pulseaudio,pulseaudio混音后送入声卡驱动。作为一个服务pulseaudio原生支持通过 tcp连接服务器。声卡我用的是“客所思KX 2A”免驱声卡,买来录歌用的。整个过程整整消耗了一周时间才搞定。
首先安装必需的软件包:

opkg update
opkg install pulseaudio pulseaudio-tools alsa-utils kmod-usb-audio madplay udevd

此时如果你的声卡被内核驱动支持,就已经可以播放声音了,可以用以下命令查看:

root@OpenWrt:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: KX2A [piq KX-2A], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

驱起声卡后用 madplay <filename.mp3>播放一首mp3音乐,应该可以听到声音了。但可能pulseaudio还识别不到你的声卡。在/etc/pulse/system.pa 最后加入以下两行(用于通过pactl管理pulseaudio和客户端tcp连接声音服务):

load-module module-esound-protocol-tcp auth-anonymous=1
load-module module-native-protocol-tcp auth-anonymous=1

尝试手动启动pulseauido

pulseaudio --system -vvvv

输出的信息中看到 module-udev-detect.c: Found 0 cards. 看来pulseaudio没有找到声卡。不过从这行输出可以看出 pulseaudio是通过udev寻找声卡的,执行“udevd  –daemon”来启动udevd,再次启动pulseaudio还是没有找到声卡。在此被困很久,通过对比opewrt 和ubuntu udev rules 最后怀疑是缺少udev rules的原因,于是将ubuntu 12.04 中/lib/udev/rules.d/78-sound-card.rules文件复制到了openwrt上,重启udev服务,再次手动启动pulseaudio 提示 module-udev-detect.c: Found 1 cards.。执行“pactl -s localhost list short sinks” 还是没有显示出声卡。继续检查pulseaudio的输出,发现一行“module-udev-detect.c: /dev/snd/controlC0 is accessible: no”,openwrt 下pulseaudio的system模式以pulse用户运行,该用户对/dev/snd下的文件没有写权限,将/dev/snd/* 下的文件权限修改为 666,再次启动pulseaudio,依然存在问题“D: [pulseaudio] conf-parser.c: Failed to open configuration file ‘/usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf’: No such file or directory”,将ubuntu下’/usr/share/pulseaudio/alsa-mixer/’的两个文件夹复制到openwrt中,再启动pulseaudio ,输出信息比之前多了很多,看来似乎是找到声卡了:

root@OpenWrt:~# pactl -s localhost list short sinks
0    alsa_output.usb-XOX_piq_KX-2A-00-KX2A.analog-stereo    module-alsa-card.c    s16le 2ch 44100Hz    SUSPENDED

此时我觉得无比幸福,终于成功了。
在笔记本上创建一下tunnel将声音输出到 openwrt上:

pactl load-module module-tunnel-sink server=192.168.100.10

如果模块加载成功,在声音设置的输出选项中就会看到”xxxxxxxx pulse@openwrt” 的sink,选中,用播放器播放音乐,声音就会从openwrt的声卡中出来。android下面没有用pulseaudio 也没能找到支持它的播放器,不过有视频看到pulseaudio作者向android移值成功,希望有一天可以通过手机直接将声音通过无线从音箱中播放出来。pulseaudio似乎有windows版本,所以windows下也是可以实现的,没有windows系统,也懒得测试。
可是一切也并没有想像的那么美好,使用过程中声音经常会出现卡钝,奇怪的是用audacious播放音乐卡的利害,而用deadbeef播放就顺畅很多,查看两个软件的配置deadbeef通过alsa模块输出音频到pulseaudio,audacious直接输出到pulseaudio,将audacious的配置改为alsa输出,声音的确好了很多,可还是时不时的有卡钝,应该不因为是带宽,最有可能的是因为延时,结果真的是这样,每次出现卡钝时,ping的延时都会大于100ms,想来这个值也不是很大,还是实时应用对延时要求太苛刻了,而且不太适全用tcp实现,而pulseaudio的 rtp 没能搞定,启用rtp会,路由器反应奇慢,且没有声音,看来只能这样了,或许换成有线更靠谱一点。

4.摄像头
这个就略去吧,配置方法到处都是。实在找不到一个好用的视频流服务,现有的软件大多画面质量难以入眼,加上400mhz 的cpu也有点吃力,要是有支持硬件编码的摄像头的朋友可以尝试一下。

5.脱机下载
因为运营商封了电驴 bt 迅雷的部分服务器,所以transmiss dldonkey 就不考虑了。http下载则使用 aria2 加上 yaaw,最好加上–file-allocation=none的参数,因为路由器写u盘的速度只有 2-3m,若要下载一个1g的文件,分配磁盘就要n久,而且分配磁盘时是不会下载任务数据的。最好的下载体验还是使用 lixian-xunlei 这套python写的迅雷离线下载工具,功能很是强大,通过它你会深刻体会到cli比gui操作更有优势。

6.xxxx
买了个米国vps架上了xxx服务,用来xxx。季付 10.5每刀。不过速度有点慢,好的时候下载也只能到100k左右,看到别人的vps 1m的速度实在有点那啥。openwrt 上通过chnroute.py每周更新一次中国的ip段 ,并加入路由表,这些网段路由到本地网关,其余的全部通过xxx出去。因为上国外网站的时候比较多,而xxx的速度又慢,所以严重影响了上网体验,也没有更好的办法来解决。要是有xxx blocked ip list就好了,哈哈

另一个思路就是用ssh tunnel+provixy。通过ssh tunnel在本地打开一个socks5的代理端口,如7070。privoxy可以将socks5类型的代理转为http类型的代理,同时还支持定义规则,访问被和谐的域名转发到ssh tunnel7070端口,其它流量直接转发出去不做处理。autoproxy2privoxy 工具可以把autoproxy的规则转换成privoxy的规则,包含了大部分被墙的网址。把浏览器的http https的代理填写好privoxy的地址和端口,就可以自由帆樯了。
如果想实现客户端零配置就要借助redsocks(官方源中没有redsocks软件包,我是自己编译的,有需要的可以和我联系),redsocks支持iptables的REDIRECT,通过配置iptables规则把80端口的数据重定向到redsocks的监听端口,然后redsocks再把数据转发给privoxy,这样客户端不需要任何配置了。相对于修改浏览器代理配置的方法,此方法躲避不了DNS污染,所以youtube能上facebook等一些dns被污染的网站还是上不去,另外不支https加密的网站,不管是否被墙。

目前最好的办法是使用dnsmasq + ipset-dns,ipset-dns 是个dns的代理服务器,dnsmasq主要用来做dns的路由,把被x的域名转发给 ipset-dns,ipset-dns 通过 vpn 解析域名,并把解析结果放到iptables(netfilter)的ipset 表,然后通过iptables 把ipset table 中的ip流量打上标记,再用策略路由把打过标记的包转发到vpn,说来复杂去ipset-dns的网站看一看很简单。

完美的FQ方案请移步至:https://code.google.com/p/autovpn-for-openwrt/

7.dlna/upnp媒体共享
这个才是重头戏,作为脱机下载,下载下来的电影音乐总不能copy到电脑上再享受吧,最好的方法则是直接让openwrt共享出来,然后手机、pad、pc都可以通过无线共享这些内容。目前有几种方法,一是http ftp,二是samba,三是dlna/upnp。一就放弃了,浏览起来太麻烦,而且很多特性不支持,samba呢太过消耗资源了,播放4g左右的片就有点卡,dlna/upnp则是最理想的选择。目前linux有两个dlna/upnp server的实现,ushare 、minidlna。ushare已经停止开发,而且使用过程中经常出现段错误,优点是ushare不用数据库支持,通过目录浏览的方式列出媒体文件,使用起来方便。minidlna则是需要sqlite数据库的,启动后数据库为空,看不到任何内容,通过inotify机制发现媒休文件,可是openwrt目前还不支持inotify最近做了些测试openwrt 12.09 rc1 已经支持inotify了,在媒体目录中如果有新的媒体文件会自动加入到数据库中。另一种发现文件的机制是在minidlna启动时使用-R参数强制扫描一遍媒体目录。minidlna有个缺点是扫描完成后如果存储设备被移除,数据库可能就会被清空,下次接入还要在再次扫描,minidlna的优点是稳定。媒体文件数量可以通过http://x.x.x.x:8200查看。dlna/upnp 性能很不错,可以供两人同时看4g左右的电影。我的平板通吃大多数视频格式,目前没有发现不能播的片,连20g的功夫熊猫都不在话下,这回派上用场了。android平台下dlna客户端用的bubbleUPNP,linux下用的LVC,windows7下可以直接支持,没有windows没测试。

8.ip变更通知,远程端口转发
为什么不用ddns,因为运营商做了nat,ddns获得的不是路由器的地址,其实发现了openwrt上的ddns支持选择ip地址,可以让ddns使用路由器接口的ip,但是还要注册帐号测试,还可能是收费的,不愿麻烦了。我的拓扑有点小复杂,wr703n并没有做为pppoe拔号,拔号的是磊科无线路由器,wr703n只是作为一个谱通pc在用(当然还有ap功能),所以用python写了个脚本,登陆磊科路由器,获得ip地址,如果ip变动发邮件给我。呵呵,这样心里踏实很多。

之后问题又来了,民用ip段只能发起连接,不能被连接,所以不在家时路由器ip能ping通,但连不上,只好用ssh在wr703和vps之间打了个遂道,连接vps的端口,转发到wr703n上来,同样用了一段python脚本来检查ssh连接是否正常,不正常则重新连接。
远程端口转发需要注意的是远端服务器上的ssh要加入“GatewayPorts yes” 的配置,否则监听端口只bind到127.0.0.1上,不能从外部连接。在openwrt上配置好密钥验证,然后执行以下命令启用远程端口转发:

ssh -f -N -R 0.0.0.0:8022:localhost:22 root@ -i /root/.ssh/id_rsa

想玩的都玩了,折腾也就到此结束了。目前正在happy使用中:

 

 

菜鸟初玩 openwrt》有25个想法

    1. ring0 文章作者

      可能你理解错了,我不是自己从头编译,而是重新打包固件,就是在现在固件里加入新的软件包。

      回复
  1. viliam

    请问你是用USB HUB吗?路由器改装一般应该只有一个USB接口的,又挂声卡的又挂摄像头的,还脱机下载挂硬盘,电源供电没问题么?

    回复
  2. 隔壁老于☎

    dlna/upnp媒体共享,android平台下dlna客户端用的bubbleUPNP 能说的具体些吗?我是小白不会用,还请多多指导

    回复
    1. ring0 文章作者

      手机和dlna服务器在同一个局域网里,android手机上安装 bunbble UPNP然后运行,在device下是会显示出当前局域网的dlna服务器,选中后点library 就可以看到这个dlna服务器上的内容了。

      回复
      1. 隔壁老于☎

        我的路由是WM4530R 刷的也是openwrt,挂在 共享 dlna都已经开启了,但是用bunbble UPNP在device下是没有显示出当前局域网的dlna服务器 ,所以更不能浏览了,是不是bunbble UPNP需要手动添加服务器呐,具体真的不会了,在有QQ吗?我的39698xxxx,这样交流方便些。感谢

        回复
  3. Pingback引用通告: beafuture's blog | openwrt+xbmc 媒体中心演示

        1. ring0 文章作者

          我好像明白你的意思了,你可能用的trunk编译的固件,trunk上的packages是不断在变的,内核升级后你再装软件就可能出现内核版本不对的提示。解决这个问题需要在下载完固后,同时镜像下来packages下的所有包,并让openwrt可以访问到(可以是本地路径,或是http)。你用的trunk的REV我也不太清楚,而且我也没有对trunk进行镜像,所以帮不了你了。

          回复
  4. zzzdev

    很好的内容,收藏了。请问站长:minidlna 的性能如何?内存需要多大,可以播放在外置硬盘的 1080p的文件吗?谢谢

    回复
    1. ring0 文章作者

      minidlna 很轻量,我的64m内存平时是够用的,minidlna 对视频格式有要求,放在处置硬盘操作起来可能会烦琐一点,播肯定是没问题的。

      回复
      1. zzzdev

        能否贴个通过wifi+ minilna 播放1080p或者720p时候的 top 图,我担心我的4M 32M 扛不住

        回复
  5. 我以为

    挖坟了。。现在新刷的openwrt15.05.1官方版本。然后加了minidlna启用inotify。结果新增文件还是不能自动扫描出来。求原因?inotify要单独再安装吗?谢谢

    回复

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据