为R6300v2新固件交叉编译shadowsocks-libev

还记得很久之前阿三的一个被嘲讽为bad hack的R6300v2的dd-wrt固件刚出的时候,本人曾经还为其交叉编译了python:
http://tengattack.com/archive/755

当时用的工具链还是hndtools-arm-linux-2.6.36-uclibc-4.5.3,uclibc果然在这类嵌入式设备中用的很多啊。
不过自从Kong Mod的R6300v2的dd-wrt固件在 r24500 (Build 24500) 之后,他把uClibc更换为musl,让很多以前交叉编译出来的东西都用不了。
(可以参考 http://www.desipro.de/ddwrt/K3-AC-Arm/Changelog Build 24500 )

不过本人今天难得有点时间,正好折腾完了服务器上的kvm虚拟化了一台Archlinux当Web Server,和一台Windows Server来跑点其他的小玩意,也是之前那篇博文有人问到了,就来折腾一下新固件的交叉编译吧。

首先,我们肯定要知道他用的工具链是啥,他在他的博客和固件发布页没写任何信息,只是知道换成了musl,如果是自己搭的工具链那就无解了,不过我相信没人这么蛋疼。
最后我搜了半天,终于找到了,是crossx86-arm-linux-musleabi-1.1.2,虽然不能确认就是这个,但是至少用这个编译出来的可以正常运行,我们也就用这个工具链吧。
(可以在我这里找到:https://bless.moe/io/linux/toolchains/

为了编译shadowsocks-libev,我们在他的GitHub页可以看到一些说明,得知我们需要首先编译OpenSSL或PolarSSL。
由于在一开始提到的文章中也编译过OpenSSL,所以这里打算直接用。
不过在更换为musl的C Library之后编译会遇到一些问题,我们可以来看看。

这里我使用的openssl版本是 openssl-1.0.1i

在设定好交叉编译的环境后,进入openssl的源码目录,我们编译时会提示缺少 termio.h 文件,这个头文件是uClibc才有的,而我们现在是musl。
所以我们需要做一些修改,首先把Configure配置文件中的 -DTERMIO 改为 -DTERMIOS

sed -i 's/-DTERMIO/-DTERMIOS/g' Configure

然后就是配置和编译,prefix可根据自己的需求修改:

CC=arm-linux-gcc CXX=arm-linux-g++ AR=arm-linux-ar RANLIB=arm-linux-ranlib ./Configure no-asm shared --prefix=/usr/local/arm/ssl linux-armv4
make && make install

改完后编译还是有点问题,他还是会提示缺少 termio.h 文件,这时我们得修改 ./crypto/ui/ui_openssl.c 文件来强制更换定义。
大概在222行处,在

#ifdef TERMIOS

这行代码前面,来强制更换定义:

#define TERMIOS
#undef  TERMIO
#undef  SGTTY

不知有没有更好的方法,希望能告知,万分感谢!

然后继续编译,搞定!别忘记 make install

接着就是 shadowsocks-libev 了,这里本人使用的版本是 1.4.6 。
从git上拖下代码,进入源码目录,配置和编译(参数需根据自己的环境修改):

CC=arm-linux-musleabi-gcc CXX=arm-linux-musleabi-g++ AR=arm-linux-musleabi-ar RANLIB=arm-linux-musleabi-ranlib ./configure --prefix=/usr/local/arm/shadowsocks-libev --with-openssl=/usr/local/arm/ssl --host=arm-linux
make && make install

如果需要编译 ss-redir 我们需要用到linux内核的头文件,在这个工具链中没有,由于之前下过dd-wrt官网的工具链:
http://www.dd-wrt.com/site/support/other-downloads?path=others/sourcecode/toolchains/

找了个相近的工具链(toolchain-arm_cortex-a9_gcc-4.9-linaro_musl-1.1.2_eabi),直接把需要用到的文件链接了过来:
(这里的路径需要根据自己的环境进行修改,我这里的工具链都放在 /media/s/ 下了)

ln -s /media/s/dd-wrt/toolchain-arm_cortex-a9_gcc-4.9-linaro_musl-1.1.2_eabi/include/linux /media/s/dd-wrt/arm-linux-musleabi/arm-linux-musleabi/include/
ln -s /media/s/dd-wrt/toolchain-arm_cortex-a9_gcc-4.9-linaro_musl-1.1.2_eabi/include/asm /media/s/dd-wrt/arm-linux-musleabi/arm-linux-musleabi/include/
ln -s /media/s/dd-wrt/toolchain-arm_cortex-a9_gcc-4.9-linaro_musl-1.1.2_eabi/include/asm-generic /media/s/dd-wrt/arm-linux-musleabi/arm-linux-musleabi/include/

接着继续编译,搞定收工~

最后是使用体验,从uClibc到musl的固件,能感觉速度有明显的提升(应该不是我的错觉)。
对shadowsocks-libev的感觉就是他大量的连接处理还是不行,我这里实际环境是内网到内网的代理,所以不存在丢包和网络不稳定的一些情况。
在这种条件下,如果连接一多就明显发现网页打开的速度变慢,如果能尽快加上python版的worker的特性应该会有所改善吧。
另外如果在高并发条件下有提示 ERROR: No file descriptors available 这样的错误的话,可以尝试用下面的命令来提高并发,一般默认是1024。

ulimit -n 51200

下面附上我编译好的shadowsocks的二进制文件:
https://bless.moe/io/linux/R6300v2/shadowsocks-libev/

另外,还要感谢一下马尾菊苣,给我了很多指点,中间做了不少蠢事,真是给他添麻烦了。