Mar 03

好吧,Tomatoware 1.7 已经基于 OpenSSL 1.1.1b 编译,本文可以不看了。

~~~~~


:mrgreen: :mrgreen: :mrgreen:


Jan 25

kdigknot-dns 中的类似 dig 的工具,使用 TLSv1.3 DoT 查询比起 dig 来要方便许多。静态编译它花了很多功夫,最终还是在 Tomatoware 作者的指导下才成功。

kdig 依赖:libedit, libunistring, gmp, nettle, gnutls,其中后三者 Tomatoware 都已自带,前两个需要下载源码编译。(注:Tomatoware 带的 gnutls 编译时未带证书,所以静态编译出来的 kdig 在运行时要指定 ca-file=/path/to/certfile,我个人为了偷懒是重新编译了带证书的 gnutls)

#libedit
./configure --prefix=/mmc/s --enable-shared=no

#libunistring
./configure --prefix=/mmc/s --enable-shared=no

#gnutls:
#opt
./configure --prefix=/mmc --enable-local-libopts --without-p11-kit --with-included-libtasn1 --enable-static --with-included-unistring --disable-doc --with-system-priority-file=/opt/etc/gnutls/default-priorities --with-default-trust-store-file=/opt/etc/ssl/certs/ca-certificates.crt --with-default-trust-store-dir=/opt/etc/ssl/certs --with-unbound-root-key-file=/opt/etc/unbound/root.key

/opt/etc/ssl/certs/ca-certificates.crt 这个证书文件可以通过 Entware 的 opkg install ca-bundle 来安装。

然后开始编译 knot-dns,我们只要其中的工具 kdig:

#knot-dns:
./configure --prefix=/opt --disable-daemon --disable-modules --disable-documentation --disable-fastparser --without-libidn
make V=99 LDFLAGS="-zmuldefs -all-static"

make V=99 用来查看编译中的详细信息,-zmuldefs 处理编译中出现的重复定义错误。

这个编译过程会出错停在开始编译 kdig 的时候,注意最后一句 gcc 相关的编译出错:

libtool: link: gcc -g -O2 -Wall -Werror=format-security -Werror=implicit -Wstrict-prototypes -zmuldefs -static -o kdig utils/kdig/kdig-kdig_exec.o utils/kdig/kdig-kdig_main.o utils/kdig/kdig-kdig_params.o ./.libs/libknotus.a /mmc/src/knot/knot-2.7.5/src/.libs/libknot.a -L/mmc/lib /mmc/src/knot/knot-2.7.5/src/.libs/libdnssec.a /mmc/lib/libedit.a -lncurses /mmc/lib/libgnutls.a -lnettle -lhogweed /mmc/lib/libgmp.a /mmc/lib/libintl.a /mmc/lib/libiconv.a -lc

复制下来,然后把外部调用的库用 -Wl,--whole-archive 和 -Wl,--no-whole-archive 包围起来,进入 src 目录手动编译:
cd src
gcc -g -O2 -Wall -Werror=format-security -Werror=implicit -Wstrict-prototypes -zmuldefs -static -o kdig utils/kdig/kdig-kdig_exec.o utils/kdig/kdig-kdig_main.o utils/kdig/kdig-kdig_params.o ./.libs/libknotus.a /mmc/src/knot/knot-2.7.5/src/.libs/libknot.a -L/mmc/lib /mmc/src/knot/knot-2.7.5/src/.libs/libdnssec.a -Wl,--whole-archive /mmc/lib/libedit.a -lncurses /mmc/lib/libgnutls.a -lnettle -lhogweed /mmc/lib/libgmp.a /mmc/lib/libintl.a /mmc/lib/libiconv.a -lc -Wl,--no-whole-archive

这样就可以编译出静态版本的 kdig 了:

file /opt/bin/kdig
/opt/bin/kdig: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, no section header

测试:

kdig +tls -d @1.1.1.1 quakemachinex.com
;; DEBUG: Querying for owner(quakemachinex.com.), class(1), type(1), server(1.1.1.1), port(853), protocol(TCP)
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG: #1, C=US,ST=California,L=San Francisco,O=Cloudflare\, Inc.,CN=cloudflare-dns.com
;; DEBUG: SHA-256 PIN: TdBczz+YjD3Q/taSfHXL5n4LnRxzJk0WG0JAX7nRu6s=
;; DEBUG: #2, C=US,O=DigiCert Inc,CN=DigiCert ECC Secure Server CA
;; DEBUG: SHA-256 PIN: PZXN3lRAy+8tBKk2Ox6F7jIlnzr2Yzmwqc3JnyfXoCw=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, skipping certificate verification
;; TLS session (TLS1.3)-(ECDHE-SECP256R1)-(ECDSA-SECP256R1-SHA256)-(AES-256-GCM)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 50261
;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 1

;; EDNS PSEUDOSECTION:
;; Version: 0; flags: ; UDP size: 1452 B; ext-rcode: NOERROR
;; PADDING: 402 B

;; QUESTION SECTION:
;; quakemachinex.com. IN A

;; ANSWER SECTION:
quakemachinex.com. 4 IN A 113.67.73.162

;; Received 468 B
;; Time 2019-01-25 08:57:44 CST
;; From 1.1.1.1@853(TCP) in 66.2 ms


Jan 05

想利用 DD-WRT 支持 Buffalo WZR-1750DHP 全部 512M 内存的固件来做编译机,安装了 Tomatoware。

编译一些无需通过 automake/autoconf 生成 Makefile 的源程序都没啥问题,但是一旦编译通过 autogen.sh (应该调用 automake 等程序)生成的 Makefile 就会直接出错,信息类似:

[goflex@GoFLEX:/home/local/goflex/work/shairport-sync_git 35%] ~ make
make all-recursive
make[1]: Entering directory '/home/local/goflex/work/shairport-sync_git'
Making all in man
Makefile:518: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/home/local/goflex/work/shairport-sync_git'
Makefile:371: recipe for target 'all' failed
make: *** [all] Error 2
[goflex@GoFLEX:/home/local/goflex/work/shairport-sync_git 36%] ~

参考:

https://forum.openwrt.org/viewtopic.php?id=60605

https://github.com/lancethepants/tomatoware/issues/18#issuecomment-168871785

目前没什么好的解决办法,好在出错的地方有些规律,就是在 Makefile 中 dot_seen=no; 这句上面的反斜杠“\”需要去掉;写了个脚本做提示:

#!/bin/sh

curr_dir=`pwd`

bad_makefile=""
bad_makefile_line=""

bad_makefile_line=$(sed -n '/dot_seen=no;/=' `grep -lr 'dot_seen=no;' $curr_dir`)
bad_makefile=$(grep -lr 'dot_seen=no;' $curr_dir)

for bfile in $bad_makefile; do
    echo $bfile
done

for line in $bad_makefile_line; do
    fi_line="$(($line - 1))"
    echo $fi_line
done

echo "sed -i 'LINEs/\//' FILE"

它会列出需要修改的文件,所在行数,提示用:

sed -i 'LINEs/\//' FILE

去修改。

参考上面的帖子链接,最终确认是 DD-WRT 自带 /bin/bash 的问题,解决方法是:在 ./configure 之前建立一个环境变量:

export CONFIG_SHELL=/mmc/bin/bash

用来覆盖配置文件建立时默认使用的 /bin/bash 即可。


Jan 02

一. 预备工作:

首先请建立一个足够大的 SWAP 分区/文件,建议 512M 以上。通过源码编译 Go 的时候路由器的 256M 内存很快就会被耗尽。如下是建立一个 1G 的 swapfile 并且挂载为交换区:

dd if=/dev/zero of=/mnt/swap/swapfile bs=1024 count=1048576
mkswap /mnt/swap/swapfile
swapon /mnt/swap/swapfile

然后你需要指定一个临时文件存放目录 TMPDIR,在编译 Go 时,Tomatoware 内置的 TMP 和 TEMP 环境变量不能被编译过程识别,它会把临时文件全部丢去 /tmp 目录,而 /tmp 目录是用内存虚拟的,空间瞬间就会被耗尽。

export TMPDIR=/mmc/tmp

二. 开始编译:(安装目标目录为 /mmc/usr/go,你可以修改为你自己的)

下载解压源码:

rm -fr /mmc/usr/go
curl -sSL https://storage.googleapis.com/golang/go1.4.3.src.tar.gz | tar -xz -C /mmc/usr
#或者:
rm -fr /mmc/usr/go
curl -O https://storage.googleapis.com/golang/go1.4.3.src.tar.gz
tar -xzf go1.4.3.src.tar.gz -C /mmc/usr

编译:
cd /mmc/usr/go/src
./make.bash

这里耗时约 20分钟(ASUS RT-AC68P 1000MHz);
测试:

export PATH=/mmc/usr/go/bin:$PATH
go version
#应该显示:
go version go1.4.3 linux/arm

打包:
为了在其他路由器上也能直接使用,我们可以压缩打包这个编译好的 Go:
tar --numeric-owner -czf /mnt/data/go1.4.3.linux-armv7.tar.gz -C /mmc/usr go
保存这个压缩包,今后在其他路由器上,只需:

rm -fr /mmc/usr/go
tar -xzf /mnt/data/go1.4.3.linux-armv7.tar.gz -C /mmc/usr
export PATH=/mmc/usr/go/bin:$PATH
go version

#应该显示:
go version go1.4.3 linux/arm

即可。

三. 升级为 Go 1.5.2:
Go 1.5.2 并不能直接编译,它需要 1.4.3 版本的支持,还好,我们上面已经编译好 1.4.3 版本的 Go 了。那么开始编译 1.5.2:

mv /mmc/usr/go /mmc/usr/go1.4
rm -fr /mmc/usr/go
curl -sSL https://storage.googleapis.com/golang/go1.5.2.src.tar.gz | tar -xz -C /mmc/usr
#或者解压已下载好的包:
tar -xzf ./go1.11.4.src.tar.gz -C /mmc/usr
cd /mmc/usr/go/src
#替换证书位置为 Tomato 默认位置 (避免这个问题:Tomato 下运行 Golang 程序的 SSL/TLS 证书问题 )
sed -i 's#\/etc\/pki\/tls#\/rom#g' ./crypto/x509/root_linux.go
GOROOT_BOOTSTRAP=/mmc/usr/go1.4 ./make.bash

这个时间很长,你可以去做点别的,大约 30 分钟到 1 小时不等;编译好后你一样可以用上面的方法打包好以便今后使用。

四. 编译实战:

我们以 https://github.com/cyfdecyf/cow 为例来静态编译一下 COW 程序:
export GOPATH=/mnt/data/compile/go
cd /mnt/data/compile/go
go get github.com/cyfdecyf/cow

这里可能会提示出错:
package golang.org/x/crypto/blowfish: unrecognized import path "golang.org/x/crypto/blowfish"
package golang.org/x/crypto/cast5: unrecognized import path "golang.org/x/crypto/cast5"
package golang.org/x/crypto/salsa20/salsa: unrecognized import path "golang.org/x/crypto/salsa20/salsa"

因为 golang.org 被 X 了;使用设置 http_proxy 以及 https_proxy 环境变量的办法在我这不行,所以我们曲线救国:
mkdir -p $GOPATH/src/golang.org/x
cd $GOPATH/src/golang.org/x
git clone https://go.googlesource.com/crypto

这样再编译就没问题了:
cd /mnt/data/compile/go/src/github.com/cyfdecyf/cow
go build

不过这样编译出来的不是静态文件,静态编译要这样:
CGO_ENABLED=0 go build

下载链接是基于 go 11.4 源码编译的成品。 编译环境:

Buffalo WZR-1750DHP:1G/512MB
DD-WRT v3.0-r29875M kongac (06/11/16),内核版本的 Linux 3.10.101;

不在 Asus RT-AC68P 上面编译的原因是: Golang 1.9 之后 ARMv5 已经不支持内核版本低于 3.1 以下升级编译(参考链接)。而 Tomato 固件的内核是 2.6 的。

编译后的版本在 Tomato 这种老内核上运行没问题,支持(基于博通 BCM 4708/4709 的 Asus RT-AC68U/P/Netgear R7000/6300v2/6250/小米) 等路由器。

1.11.4
链接: https://pan.baidu.com/s/1Zj547uPNAijml5BXXuFU8g 提取码: wc9i

1.12.0
链接: https://pan.baidu.com/s/1n6vC0nv9C6GIQUeqvRVEsQ 提取码: d56i

参考: How to compile Go on any ARM device




Dec 30

先配置下选项,我这里以 PolarSSL 为例:
./configure --prefix=/opt --with-crypto-library=polarssl --with-polarssl=/mmc/lib --with-polarssl-include=/mmc/include

为了解决编译时出现的 epoll 相关错误(应为 uClibc 版本低的原因),需要:
sed -i "s/epoll_create1/epoll_create/g" ./libev/ev_epoll.c

使用 ldtools 的话,可以在编译二进制文件时指定 -all-static:
sed -i "s/LDFLAGS = /LDFLAGS = -all-static/g" ./src/Makefile

然后就可以:

make
strip ./src/ss-*
make install

[1/2]  1 2 >