Oct 12

源码: Psiphon 3 Tunnel Core 项目
编译:
原项目中关于编译说的比较简单笼统,这里详细说下。
首先确认 Go 编译环境已经安装好,可以参考 Tomatoware ARM 下建立 Go 编译环境 一文。
然后要下载一些依赖及源程序:
go get -u -v github.com/Psiphon-Inc/bolt
go get -u -v github.com/Psiphon-Inc/dns
go get -u -v github.com/Psiphon-Inc/goptlib
go get -u -v github.com/Psiphon-Inc/goregen
go get -u -v github.com/Psiphon-Inc/ratelimit
go get -u -v github.com/Psiphon-Inc/crypto/nacl/box
go get -u -v github.com/Psiphon-Inc/crypto/nacl/secretbox
go get -u -v github.com/Psiphon-Inc/crypto/ssh
go get -u -v github.com/Psiphon-Inc/goarista/monotime
go get -u -v github.com/Psiphon-Inc/goselect
go get -u -v github.com/Psiphon-Inc/sss
go get -u -v github.com/Psiphon-Inc/gocapability/capability
go get -u -v github.com/Psiphon-Inc/m3u8
go get -u -v github.com/Psiphon-Labs/psiphon-tunnel-core

写个编译脚本:

#!/bin/sh

WORKDIR=$(pwd)

cd src/github.com/Psiphon-Labs/psiphon-tunnel-core

BUILDDATE=$(date --iso-8601=seconds)
BUILDREPO=$(git config --get remote.origin.url)
BUILDREV=$(git rev-parse --short HEAD)
GOVERSION=$(go version | perl -ne '/go version (.*?) / && print $1')
DEPENDENCIES=$(echo -n "{" && go list -f '{{range $dep := .Deps}}
{{printf "%sn" $dep}}{{end}}' | xargs go list -f '{{if not .Standard}}
{{.ImportPath}}{{end}}' | xargs -I pkg bash -c 'cd $GOPATH/src/pkg
 && echo -n "\"pkg\":\"$(git rev-parse --short HEAD)\","' | sed 's/,$/}/')

LDFLAGS="
-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildDate=$BUILDDATE 
-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRepo=$BUILDREPO 
-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.buildRev=$BUILDREV 
-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.goVersion=$GOVERSION 
-X github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common.dependencies=$DEPENDENCIES 
"

cd ConsoleClient && go build -ldflags "${LDFLAGS}"
mv -f ./ConsoleClient ${WORKDIR}/bin/psiphon-tunnel-core-$BUILDREV
cd ${WORKDIR}
strip bin/psiphon-tunnel-core-$BUILDREV
upx -9 bin/psiphon-tunnel-core-$BUILDREV

bin/psiphon-tunnel-core-$BUILDREV

命令行运行:
./psiphon-tunnel-core -config ./psiphon.config -serverList ./server_list.dat -listenInterface br0 -formatNotices

psiphon.config 以及 server_list.dat 文件可以从 Windows 版本的 Psiphon3 (赛风3) 安装版本中提取。
运行结果:
psiphon-tunnel-core: Starting psiphon-tunnel-core...
2016-10-12T02:52:38Z BuildInfo {"buildDate":"2016-09-27T16:28:36+08:00","buildRepo":"https://github.com/Psiphon-Labs/psiphon-tunnel-core","buildRev":"31dad76","goVersion":"go1.6","gomobileVersion":"go1.6"}
2016-10-12T02:52:38Z AvailableEgressRegions {"regions":["CA","DE","GB","IN","JP","NL","SG","US"]}
2016-10-12T02:52:38Z ListeningSocksProxyPort {"port":7788}
2016-10-12T02:52:38Z ListeningHttpProxyPort {"port":8788}
2016-10-12T02:52:38Z ImpairedProtocolClassification {"classification":{}}
2016-10-12T02:52:38Z CandidateServers {"count":153,"protocol":"","region":""}
2016-10-12T02:52:42Z Homepage {"url":"http://www.psiphontoday.com/zh/index_desktop.html?client_region=CN"}
2016-10-12T02:52:42Z ClientUpgradeAvailable {"version":"116"}
2016-10-12T02:52:42Z Tunnels {"count":1}

出现 Tunnels {"count":1} 字样就表示连接服务器成功了。

新版编译出错:
# github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tls
/mnt/data/compile/go/src/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tls/tls.go:106: undefined: deadlineTimeout

修改:

if !dialer.Deadline.IsZero() {
  		deadlineTimeout := dialer.Deadline.Sub(time.Now())
  		if timeout == 0 || deadlineTimeout < timeout {
  			timeout = deadlineTimeout
  		}
  	}

参考: https://github.com/golang/go/issues/14595


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




Jul 24

关于无线灯,也就是 WLED ,用 telnet 登录路由器,输入以下指令:


nvram set wl0gpio0=8
nvram commit
reboot

(wl0gpio0=8 是指无线开启LED不亮,有流量闪动,无线关闭LED常亮,这好象是 Linksys 以及 DD-WRT 默认的设置;如果设为136,则无线开启 LED 就亮,有流量闪动,无线关闭 LED 就不亮,这是我目前的设置)

关于那个 WPS 灯,也就是 SES LED(或者叫 WPS LED 什么的都行,反正就是 WPS 加密按钮上面那个灯),加入以下启动脚本:

while sleep 1; do if [ `nvram get security_mode` = "disabled" ]; then gpio disable 3; else gpio enable 3; fi; done &

实现的效果是,如果打开无线加密,灯是绿色,如果关闭就是黄色。

这玩意折磨我最久,关键是 security_mode 这个参数,网络上找到的基本都是 wl0_security_mode,而这个参数在我的 WRT54G2 上,无论设置无线加密与否它都是 psk2 不变!所以脚本根本不起作用。通过不停的开关无线加密,然后用 nvram show|grep 查看参数,最后找到了这个适用于表示 WRT54G2 的无线加密切换参数。

参考资料:

Security LED Script WRT300n v1.1

WZR-G300N gpio

Useful Scripts

Linksys WRT54G2 V1 with DD-WRT (Fixing WPS lights)


Jun 04

通常猫下面接了个路由器之后,我们不能再通过网络浏览器访问猫的设置界面了。因为通常来说,路由器和猫不在同一个网段,而且路由器通常是设置为网关而不是路由模式。如果你的路由器可以刷 DD-WRT 或者 Tomato 固件,则使用以下方法可以“穿透”路由器访问猫。

DD-WRT:

1. 假设你的路由器 IP 地址为 192.168.1.1 ;

2. 假设你的猫 IP 地址为 192.168.2.1

3. 用浏览器打开 DD-WRT 设置界面, 转到管理员>命令;

4. 键入:


ifconfig vlan1:0 192.168.2.2 netmask 255.255.255.0

然后点击 <保存在启动项>

5. 键入:


/usr/sbin/iptables -I POSTROUTING -t nat -o vlan1 -d 192.168.2.0/24 -j MASQUERADE

然后点击 <保存在防火墙>

注意:脚本中的 IP 子网范围其实只与猫的子网有关,如上例,猫的子网是 192.168.2.X,则脚本中两个涉及子网的参数都为 192.168.2.X;我们只需保证路由器和猫的子网不同即可,这是基本原则。这个规则同样适用于以下 Tomato 的方法;

Tomato:

1.现在我们假设猫的 IP 地址是: 192.168.0.1 ;根据上述规则,我们不必关心路由器的 IP 地址;

2.在浏览器中访问 Tomato 设置界面,转到 管理/脚本 页面:

初始化 或者 外网上线 中键入:


sleep 5
ip addr add 192.168.0.13/24 dev $(nvram get wan_ifname) brd +

防火墙 中键入:

iptables -I POSTROUTING -t nat -o $(nvram get wan_ifname) -d 192.168.0.0/24 -j MASQUERADE

3.重启路由器即可。

2011-06-05 补充一个硬件的方法,适合通用路由器(未测试 2012-02-07 测试有效!):

把猫和路由设置为同一网段但是不同的 IP,例如路由器是 192.168.1.1,猫是 192.168.1.2,注意路由器的 DHCP 不要和猫的 IP 冲突(只在猫或者路由器上启用 DHCP),电脑网卡也要分配同网段的 IP 才能访问。
接线方法是:猫连接到路由器上的任意 LAN 口,路由器的 WAN 口连接到自身的任意 LAN 口,电脑连接到路由器的任意 LAN 口。
电脑设置好 IP 后直接访问猫的 IP 即可,缺点就是你少了两个可用的 LAN 口,优点是可以直接访问猫,而且如果你的帐号如果支持多次拨号的话还可以用电脑直接拨号上网。