目前在用的科学上网工具有两款:Trojan和V2Ray。V2Ray的使用方式有很多,这里不作详细记录。Trojan的优势在于配置相对简单、采用的科学上网的方法不易被发现、速度快。V2Ray的优势在于功能齐全,搭配其他工具可以实现从简单到复杂的各种科学上网方式,缺点是某些方式速度较慢。综合两者的优缺点,我一般将两者搭配使用,Trojan负责科学上网,V2Ray负责路由功能。
### 安装Trojan和V2Ray 是否在Debian/Ubuntu官方仓库中
Trojan
: ✔ (ubuntu从19.04开始)V2Ray
: ✘
V2Ray
的官方安装脚本在国内下载速度很慢,经常失败。结合上面信息,应选择优先安装Trojan
,然后在终端下开启科学上网模式,再安装V2Ray
。安装流程全自动,一切都很Nice。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| function trojan_environment_varibles() { TROJAN_PREFIX=/directory/to/trojan/real/config.json TROJAN_CERT=$TROJAN_PREFIX/cert.pem TROJAN_CERT_PATH_IN_CONFIG=$TROJAN_CERT TROJAN_CONFIG=$TROJAN_PREFIX/config.json TROJAN_CONFIG_EXAMPLE=$TROJAN_PREFIX/config_example.json TROJAN_SERVER=$SERVER_NAME }
function trojan_install_for_old_distributor() { }
function trojan_install() { trojan_environment_varibles [ ! -f $TROJAN_CONFIG ] && cp $TROJAN_CONFIG_EXAMPLE $TROJAN_CONFIG if ! command -v trojan > /dev/null 2>&1; then TROJAN_CONFIG=/path/to/模板配置文件 TROJAN_CERT=/path/to/本地证书 if 满足条件:Ubuntu及版本在19.04及以上; then sudo apt install trojan sudo ln -sf $TROJAN_CONFIG /etc/trojan/config.json else trojan_install_for_old_distributor TROJAN_CERT_PATH_IN_CONFIG=/usr/local/etc/ssl/cert.pem fi fi if $TROJAN_CONFIG中不含$TROJAN_CERT_PATH_IN_CONFIG; then sed -i "s|\"cert.*|\"cert\": \"$TROJAN_CERT_PATH_IN_CONFIG\",|" $TROJAN_CONFIG fi trojan_first_start }
|
配置文件
这里只讨论Trojan在本地的配置以及相关脚本。Trojan的客户端配置中有三项在切换VPS时需要修改,分别是
remote_addr | IP/域名 |
sni | 域名 |
cert | 本地证书路径 |
因为使用了CloudFlare
家的泛域名证书,因此在多个VPS上可以使用同一套证书,意味着即使在配置文件中本地证书路径使用了软链接地址,也无需对其指向的证书文件做任何修改。因此在切换VPS时,真正需要修改的只有两个地方:remote_addr
和sni
。
remote_addr
选择的规则为
原因在于remote_addr
必须解析到VPS自己的IP
。
切换VPS并重启服务的脚本
根据上面的分析,采用模板配置文件的方式,选取特定的VPS后,用sed
直接修改配置文件中上述两个选项的值,再用service
命令重启服务。
VPS信息
VPS的相关信息,都存放在文件server_info.ini
中,如下所示:
1 2 3 4 5 6 7 8 9
| [cloudcone] ip = xxx.xxx.xxx.xxx domain = www.example.com dns_proxy = true
[racknerd] ip = xxx.xxx.xxx.xxx domain = www.example2.com dns_proxy = false
|
借助awk
定义两个函数用于读取ini
文件中的服务器信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| SERVER_INFO_FILE=/path/to/server_info.ini
function read_section_ini() { INI_FILE=$1 awk -F '=' '{ if ($1 ~ /\[/) { gsub(/[\[\]]/, "", $1) print $1 } }' $INI_FILE }
function read_ini() { INI_FILE=$1 SECTION=${2:-cloudcone} KEY=${3:-ip} awk -F '=' '{ if ($1 ~ /\[/) if ($1 ~ /\['$SECTION'/) { a = 1 } else { a = 0 } else if (a == 1 && $1 ~ /'$KEY'/) { gsub(/[[:blank:]]/, "", $2) print $2 } }' $INI_FILE }
VPS_SERVERS=($(read_section_ini $SERVER_INFO_FILE))
|
切换VPS脚本
接下来就涉及到Trojan
和V2Ray
相关的脚本了,同样定义两个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| function choose_server_for_trojan() { TROJAN_SERVER=$1 TROJAN_CONFIG=/path/to/trojan的模板配置文件 dns_proxy=$(read_ini $SERVER_INFO_FILE $TROJAN_SERVER dns_proxy) ip=$(read_ini $SERVER_INFO_FILE $TROJAN_SERVER ip) sni=$(read_ini $SERVER_INFO_FILE $TROJAN_SERVER sni) if $dns_proxy; then remote_addr=$ip else remote_addr=$sni fi sed -i "s|\"remote_addr.*|\"remote_addr\": \"$remote_addr\",|" $TROJAN_CONFIG sed -i "s|\"sni.*|\"sni\": \"$sni\",|" $TROJAN_CONFIG sudo service trojan restart sudo service trojan status }
function choose_server_for_v2ray() { }
function change_server() { VPS_SERVERS=($(read_section_ini $SERVER_INFO_FILE)) SERVER_ID=${1:-0} SERVER_NAME=$(VPS_SERVERS[$SERVER_ID]) if [ $SERVER_ID -ge 0 ] && [ $SERVER_ID -lt ${#VPS_SERVERS[*]} ]; then choose_server_for_trojan $SERVER_NAME choose_server_for_v2ray $SERVER_NAME else echo "错误:VPS服务器不存在" echo "尝试:'$COMMAND -i' 查看可用服务器" fi }
|
都到这个程度了,干脆写成一个简单的命令行程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| function show_help() { echo "欢迎使用本脚本切换VPS服务器" echo "用法:vps_server 选项" echo "选项:" echo " -h [--help] 显示本帮助" echo " -s [--server=val] 通过val选择不同VPS服务器" echo " -i [--info] 显示可用服务器汇总信息" echo " -c [--current] 显示当前使用的VPS服务器" }
function show_servers_info() { [ -z "$VPS_SERVERS" ] && VPS_SERVERS=($(read_section_ini $SERVER_INFO_FILE)) echo "可用的服务器有:" for i in "${!VPS_SERVERS[@]}"; do echo " $i ): ${VPS_SERVERS[i]}" done echo "" echo "服务器端安装完成:" echo " 将证书下载至客户端所在主机并放置在正确路径" echo " 客户端配置文件中需指定证书(或其软链接)路径" echo " 若CloudFlare中开启了代理,则客户端配置文件中只能使用IP。" echo "" echo "客户端安装完成:" echo " 从服务器上下载证书并安装" echo " 配置文件中需指定证书绝对路径" echo " | | | remote_addr |" echo " | | | IP | 域名 |" echo " | CloudFlare | DNS | ✔ | ✔ |" echo " | | Proxy | ✔ | ✘ |" echo "" }
function get_current_server() { awk -F ':' '{ if ($1 ~ /\"sni/) { gsub(/\"/, "", $2) print $2 } }' $TROJAN_PREFIX/config.json }
while [[ $# -ge 1 ]]; do case "$1" in -h|--help ) show_help ;; -i|--info) show_servers_info ;; -c|--current) VPS=$(get_current_server) echo "当前VPS服务器:" echo " ${VPS%%.*}" ;; -s|--server) shift if [[ $# -ge 1 ]]; then ID=$1 else ID=0 fi change_server $ID ;; *) echo "错误:未识别选项 '$1'" echo "尝试 '$COMMAND -h|--help' 查看帮助信息" ;; esac shift done
|