Arukas容器使用ge.tt替代Endpoint域名

ge.tt 与 Endpoint

前面写了一篇介绍日本 Arukas 樱花容器及使用其 Endpoint 域名的文章,目前我在 Arukas 上面跑了一个 Shadowsocks 容器用于路由器自动爬墙。不过还是发现如果 Arukas 容器的开放端口里开启了 UDP 端口(给 OpenWRT 路由器上的 ss-tunnel 用于转发解析被封锁的域名),这种情况下 Arukas 的 Endpoint 地址就基本没办法正常访问了。文章中我写的 OpenWRT 下自动获取 Arukas 容器 Shadowsocks 配置的脚本也经常出错,用起来还是不太方便。

刚好之前为了给其他人分享文件,我还写了一篇介绍 ge.tt 文件分享 API 的文章,就想到既然 Endpoint 地址访问容易出错,那可以在 Arukas Shadowsocks 容器里使用 ge.tt 的 Python CLI 将容器的当前地址和外部端口配置文件上传到指定的 ge.tt 分享地址,这样 OpenWRT 系统里也能很方便地通过分享地址更新配置文件了。

Arukas 容器修改

这里的 Arukas 容器系统我使用的还是最新 baseimage 系统,增加了 shadowsocks-libev 服务器程序,并将 gett-cli 工具集成到 baseimage 系统,然后将 /etc/my_init.d/01_start_ss_ssh.sh 启动脚本修改为:

#!/bin/bash

# Enable SSH
rm -f /etc/service/sshd/down
/etc/my_init.d/00_regen_ssh_host_keys.sh
touch /etc/service/sshd/down

# Setup SSH key
if [ "x$SSH_AUTHORIZED_KEYS" = "x" ]; then
	/usr/sbin/enable_insecure_key
else
	mkdir ~/.ssh
	echo "$SSH_AUTHORIZED_KEYS" | sed 's/\\n/\n/g' > ~/.ssh/authorized_keys
	chmod 400 ~/.ssh/authorized_keys
fi

# Start web server
env | grep -E '^MARATHON_HOST=|MARATHON_PORT_' > /home/wwwroot/default/marathon.conf
if [ "x$MARATHON_HOST" != "x" ]; then
	getent hosts $MARATHON_HOST | awk '{print "MARATHON_HOST_IP="$1; exit;}' >> /home/wwwroot/default/marathon.conf
fi

start-stop-daemon -S -b -n tmp-httpd -d /home/wwwroot/default -x /usr/bin/python3 -- -m http.server 80

# Start ShadowSocks
env | grep '^SHADOWSOCKS_CFGS_' | awk -F '=' '{print $1;}' | while read T_NAME; do
	SS_NAME="${T_NAME:17}"
	echo "${!T_NAME}" > /etc/shadowsocks-libev/${SS_NAME}.json
	start-stop-daemon -n ss-$SS_NAME -x /usr/bin/ss-server -b -S -- -c /etc/shadowsocks-libev/${SS_NAME}.json -u --fast-open
done

if [ "x$GETT_TOKEN" != "x" ]; then
	if [ "x$HOME" = "x" ]; then
		export HOME="/root"
	fi
	echo -n "$GETT_TOKEN" > ~/.gett-token
	if [ "x$GETT_SHARE_NAME" != "x" ]; then
		python3 /usr/local/gett/uploader.py -l http://ge.tt/$GETT_SHARE_NAME | awk '{if (substr($5,1,13)=="http://ge.tt/") {print $5;}}' | xargs python3 /usr/local/gett/uploader.py --delete
		python3 /usr/local/gett/uploader.py -s http://ge.tt/$GETT_SHARE_NAME /home/wwwroot/default/marathon.conf
	fi
fi

exec /usr/sbin/sshd -D -e -u 0

这里增加了两个 ge.tt 文件分享服务相关的环境变量,通过 Docker 容器的 ENV 环境变量指定:

  • GETT_TOKEN
    在某台设备上使用 gett-cli 工具登录成功之后就能看到 ~/.gett-token 文件中的 Refresh Token 内容;
  • GETT_SHARE_NAME
    预先创建好固定的 ge.tt 分享名(例如:8D95lij2),可以在 ge.tt 网页中上传文件创建,也可以用 gett-cli 工具创建。

如果容器的 ENV 列表里有这两个环境变量,启动脚本会自动将 Arukas 容器的当前地址和外部端口配置文件 marathon.conf 上传到指定的 ge.tt 分享地址。

使用 Shadowsocks 容器

容器的 CMD 指令值以及其它 SSH 公钥和 Shadowsocks 服务器 JSON 配置文件环境变量与 Arukas 容器文章中介绍的相同,可以根据需要自行配置。

我修改后的 Arukas 上支持 ge.tt 并适用于 baseimage 系统的 Shadowsocks 服务器安装包可以从这里下载:

https://zohead.com/downloads/arukas-baseimage-xenial-ss.tar.gz

另外我还制作了一个 ShadowsocksR 服务器安装包,有需要的朋友可以下载测试看看,由于 baseimage 系统已经自带了 Python 3 环境,因此 ShadowsocksR 服务器安装包体积也要小一些:

https://zohead.com/downloads/arukas-baseimage-xenial-ssr.tar.gz

对于容器 ENV 列表中以 SHADOWSOCKS_CFGS_ 开头的变量,启动脚本会自动在 /etc/shadowsocks-libev 目录(对于 ShadowsocksR 是 /etc/shadowsocks 目录)下生成 Shadowsocks 或 ShadowsocksR 服务器配置文件,配置文件内容就是该 JSON 格式变量的值。

例如我的 Arukas 容器配置中的 ShadowsocksR 环境变量:

SHADOWSOCKS_CFGS_xxx = { "server":"0.0.0.0", "server_port":8113, "local_port":1080, "password":"ssr-pass", "timeout":30, "method":"aes-128-ctr", "protocol" : "auth_aes128_md5", "obfs" : "http_simple" }

当然对于 ShadowsocksR 容器也需要相应地将 CMD 启动指令改为:

/sbin/my_init -- sh -c 'curl -o /arukas-baseimage-xenial-ssr.tar.gz https://zohead.com/downloads/arukas-baseimage-xenial-ssr.tar.gz && tar -C / -xzf /arukas-baseimage-xenial-ssr.tar.gz && /etc/my_init.d/01_start_ss_ssh.sh'

OpenWRT 自动更新配置脚本

为了能支持从 ge.tt 分享地址下载更新 Shadowsocks 配置,我对 OpenWRT 路由器上的 arukas-ss.sh 脚本也做了修改:

#!/bin/sh
ARUKAS_ENDPOINT=""
GETT_SHRNAME=""

[ $# -ge 2 ] || exit 1

[ -f /tmp/.marathon.conf ] && mv /tmp/.marathon.conf /tmp/.marathon.conf.bak

IND=0
while [ $IND -lt 5 ]; do
	let IND++
	[ -f /tmp/.marathon.conf ] && rm -f /tmp/.marathon.conf
	if [ "x$GETT_SHRNAME" != "x" ]; then
		T_FILEID=`curl -s -k -f http://api.ge.tt/1/shares/$GETT_SHRNAME | sed -e 's/^.*"fileid"[^:]*:[^"]*"//' -e 's/".*$//'`
		if [ "x$T_FILEID" != "x" ]; then
			curl -s -k -f -o /tmp/.marathon.conf -L -e "http://ge.tt/$GETT_SHRNAME" "http://api.ge.tt/1/files/$GETT_SHRNAME/$T_FILEID/blob?download"
			[ $? -eq 0 ] && break
		fi
	fi
	curl -s -k -f -o /tmp/.marathon.conf https://$ARUKAS_ENDPOINT.arukascloud.io/marathon.conf
	[ $? -eq 0 ] && break
	sleep 1
done

[ -s /tmp/.marathon.conf ] || exit 1
echo "Fetch server config after $IND tries."

if [ -f /tmp/.marathon.conf.bak ]; then
	cmp -s /tmp/.marathon.conf /tmp/.marathon.conf.bak
	if [ $? -eq 0 ]; then
		rm -f /tmp/.marathon.conf
		exit 0
	fi
fi

. /tmp/.marathon.conf 2>/dev/null
if [ "x$MARATHON_HOST" = "x" ]; then
	rm -f /tmp/.marathon.conf
	exit 1
fi

while [ $# -gt 1 ]; do
	CMD="echo \${MARATHON_PORT_$2}"
	SS_PORT=`eval $CMD`

	if [ -f $1 -a "x$SS_PORT" != "x" ]; then
		if [ "x$MARATHON_HOST_IP" != "x" ]; then
			MARATHON_HOST="$MARATHON_HOST_IP"
		fi
		sed -i -e 's/"server"[^:]*:[^,]*,/"server" : "'$MARATHON_HOST'",/' -e 's/"server_port"[^:]*:[^,]*,/"server_port" : "'$SS_PORT'",/' $1
	fi
	shift
	shift
done

if [ "x$RESTART_SHADOWSOCKS" != "xno" ]; then
	/etc/init.d/shadowsocks restart
fi

使用之前请先根据需要修改脚本最上面的 ARUKAS_ENDPOINTGETT_SHRNAME 变量(一般指定其中一个即可),分别为 Arukas 容器的 Endpoint 名和 ge.tt 分享名,脚本会分别尝试通过 ge.tt 分享地址和 Arukas Endpoint 地址下载容器的 marathon.conf 配置文件。

为了使用简单性考虑,修改后的 arukas-ss.sh 脚本是直接通过 /etc/init.d/shadowsocks 服务脚本重启 OpenWRT 上的 Shadowsocks 客户端程序。该脚本的使用方法也请参考我之前写的介绍 Arukas 容器及 Endpoint 的文章。

最后祝大家心中无墙,玩的开心 ^_^。