diff --git a/README.md b/README.md index fc8b863..598e3c3 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,20 @@ * * * ## 更新信息 -2024.3.26 v1.6.4 Thanks to UUb for the official change of the compilation, dependencies jq, qrencode from apt installation to download the binary file, reduce the installation time of about 15 seconds, the implementation of the project's positioning of lightweight, as far as possible to install the least system dependencies; 感谢 UUb 兄弟的官改编译,依赖 jq, qrencode 从 apt 安装改为下载二进制文件,缩减安装时间约15秒,贯彻项目轻量化的定位,尽最大可能安装最少的系统依赖 - -2024.3.24 v1.6.3 1. Compatible with CentOS 7,8,9; 2. Remove default Github CDN; 1. 适配 CentOS 7,8,9; 2. 去掉默认的 Github 加速网 +2024.5.20 v1.6.5 1. Add Github CDN; 2. Remove subscription template 2; 1. 添加 Github 加速 CDN; 2. 去掉订阅模板2 -2024.3.13 v1.6.2 1. Subscription made optional, no nginx and qrcode installed if not needed; 2. Use native IP if it supports unlocking chatGPT, otherwise use warp chained proxy unlocking; 1. 在线订阅改为可选项,如不需要,不安装 nginx 和 qrcode; 2. 如自身支持解锁 chatGPT,则使用原生 IP,否则使用 warp 链式代理解锁 - -2024.3.10 v1.6.1 1. To protect node data security, use fake information to fetch subscribe api; 2. Adaptive the above clients. https://\/\/\; 1. 为保护节点数据安全,在 api 转订阅时,使用虚假信息; 2. 自适应以上的客户端,https://\/\/\ +2024.3.26 v1.6.4 Thanks to UUb for the official change of the compilation, dependencies jq, qrencode from apt installation to download the binary file, reduce the installation time of about 15 seconds, the implementation of the project's positioning of lightweight, as far as possible to install the least system dependencies; 感谢 UUb 兄弟的官改编译,依赖 jq, qrencode 从 apt 安装改为下载二进制文件,缩减安装时间约15秒,贯彻项目轻量化的定位,尽最大可能安装最少的系统依赖
历史更新 history(点击即可展开或收起)
+>2024.3.24 v1.6.3 1. Compatible with CentOS 7,8,9; 2. Remove default Github CDN; 1. 适配 CentOS 7,8,9; 2. 去掉默认的 Github 加速网 +> +>2024.3.13 v1.6.2 1. Subscription made optional, no nginx and qrcode installed if not needed; 2. Use native IP if it supports unlocking chatGPT, otherwise use warp chained proxy unlocking; 1. 在线订阅改为可选项,如不需要,不安装 nginx 和 qrcode; 2. 如自身支持解锁 chatGPT,则使用原生 IP,否则使用 warp 链式代理解锁 +> +>2024.3.10 v1.6.1 1. To protect node data security, use fake information to fetch subscribe api; 2. Adaptive the above clients. https://\/\/\; 1. 为保护节点数据安全,在 api 转订阅时,使用虚假信息; 2. 自适应以上的客户端,https://\/\/\ +> >2024.3.2 v1.6 1. Support V2rayN / Nekobox / Clash / sing-box / Shadowrocket subscribe. https://\/\/\. Index of all subscribes: https://\/\/ ; Reinstall is required; 2. Adaptive the above clients. https://\/\/\ ; 1. 增加 V2rayN / Nekobox / Clash / sing-box / Shadowrocket 订阅,https://\/\/\, 所有订阅的索引: https://\/\/,需要重新安装; 2. 自适应以上的客户端,https://\/\/\ > >2024.2.6 V1.5 Argo run protocol uses default instead of http2. The default value is auto, what will automatically configure the quic protocol. If cloudflared is unable to establish UDP connections, it will fallback to using the http2 protocol; Argo 运行的协议使用默认值,而不是 http2。默认值为 auto,将自动配置 quic 协议。如果 cloudflared 无法建立 UDP 连接,它将回落到使用 http2 协议。 diff --git a/argox.sh b/argox.sh index d3d7018..927632e 100644 --- a/argox.sh +++ b/argox.sh @@ -1,17 +1,19 @@ #!/usr/bin/env bash # 当前脚本版本号 -VERSION='1.6.4 (2024.03.26)' +VERSION='1.6.5 (2024.05.20)' # 各变量默认值 +GH_PROXY='https://ghproxy.agrayman.gay/' WS_PATH_DEFAULT='argox' WORK_DIR='/etc/argox' TEMP_DIR='/tmp/argox' TLS_SERVER=addons.mozilla.org METRICS_PORT='3333' -CDN_DOMAIN=("cn.azhz.eu.org" "www.who.int" "skk.moe" "time.cloudflare.com" "csgo.com") +CDN_DOMAIN=("cn.azhz.eu.org" "acjp.cloudflarest.link" "xn--b6gac.eu.org" "dash.cloudflare.com" "skk.moe" "visa.com") SUBSCRIBE_TEMPLATE="https://raw.githubusercontent.com/fscarmen/client_template/main" -SUBSCRIBE_API=("bav6.889876.xyz" "api.v1.mk") + +export DEBIAN_FRONTEND=noninteractive trap "rm -rf $TEMP_DIR; echo -e '\n' ;exit 1" INT QUIT TERM EXIT @@ -19,8 +21,8 @@ mkdir -p $TEMP_DIR E[0]="Language:\n 1. English (default) \n 2. 简体中文" C[0]="${E[0]}" -E[1]="Thanks to UUb for the official change of the compilation, dependencies jq, qrencode from apt installation to download the binary files, reduce the installation time of about 15 seconds, the implementation of the project's positioning of lightweight, as far as possible to install the least system dependencies." -C[1]="感谢 UUb 兄弟的官改编译,依赖 jq, qrencode 从 apt 安装改为下载二进制文件,缩减安装时间约15秒,贯彻项目轻量化的定位,尽最大可能安装最少的系统依赖" +E[1]="1. Add Github CDN; 2. Remove subscription template 2." +C[1]="1. 添加 Github 加速 CDN; 2. 去掉订阅模板2" E[2]="Project to create Argo tunnels and Xray specifically for VPS, detailed:[https://github.com/fscarmen/argox]\n Features:\n\t • Allows the creation of Argo tunnels via Token, Json and ad hoc methods. User can easily obtain the json at https://fscarmen.cloudflare.now.cc .\n\t • Extremely fast installation method, saving users time.\n\t • Support system: Ubuntu, Debian, CentOS, Alpine and Arch Linux 3.\n\t • Support architecture: AMD,ARM and s390x\n" C[2]="本项目专为 VPS 添加 Argo 隧道及 Xray,详细说明: [https://github.com/fscarmen/argox]\n 脚本特点:\n\t • 允许通过 Token, Json 及 临时方式来创建 Argo 隧道,用户通过以下网站轻松获取 json: https://fscarmen.cloudflare.now.cc\n\t • 极速安装方式,大大节省用户时间\n\t • 智能判断操作系统: Ubuntu 、Debian 、CentOS 、Alpine 和 Arch Linux,请务必选择 LTS 系统\n\t • 支持硬件结构类型: AMD 和 ARM\n" E[3]="Input errors up to 5 times.The script is aborted." @@ -166,17 +168,23 @@ hint() { echo -e "\033[33m\033[01m$*\033[0m"; } # 黄色 reading() { read -rp "$(info "$1")" "$2"; } text() { grep -q '\$' <<< "${E[$*]}" && eval echo "\$(eval echo "\${${L}[$*]}")" || eval echo "\${${L}[$*]}"; } -# 自定义友道或谷歌翻译函数 +# 自定义谷歌翻译函数,使用两个翻译 api,如均不能翻译,则返回原英文 translate() { - [ -n "$@" ] && EN="$@" - ZH=$(wget --no-check-certificate -qO- --tries=1 --timeout=2 "https://translate.google.com/translate_a/t?client=any_client_id_works&sl=en&tl=zh&q=${EN//[[:space:]]/}" 2>/dev/null) - [[ "$ZH" =~ ^\[\".+\"\]$ ]] && cut -d \" -f2 <<< "$ZH" + [ -n "$@" ] && local EN="$@" + [ -z "$ZH" ] && local ZH=$(curl -km8 -sSL "https://translate.google.com/translate_a/t?client=any_client_id_works&sl=en&tl=zh&q=${EN//[[:space:]]/%20}" 2>/dev/null | awk -F '"' '{print $2}') + [ -z "$ZH" ] && local ZH=$(curl -km8 -sSL "https://findmyip.net/api/translate.php?text=${EN//[[:space:]]/%20}" 2>/dev/null | awk -F '"' '{print $16}') + [ -z "$ZH" ] && echo "$EN" || echo "$ZH" +} + +# 检测是否需要启用 Github CDN,如能直接连通,则不使用 +check_cdn() { + [ -n "$GH_PROXY" ] && wget --server-response --quiet --output-document=/dev/null --no-check-certificate --tries=2 --timeout=3 https://raw.githubusercontent.com/fscarmen/ArgoX/main/README.md >/dev/null 2>&1 && unset GH_PROXY } # 检测是否解锁 chatGPT,以决定是否使用 warp 链式代理或者是 direct out check_chatgpt() { local CHECK_STACK=$1 - local SUPPORT_COUNTRY=(AL DZ AD AO AG AR AM AU AT AZ BS BD BB BE BZ BJ BT BO BA BW BR BN BG BF CV CA CL CO KM CG CR CI HR CY CZ DK DJ DM DO EC SV EE FJ FI FR GA GM GE DE GH GR GD GT GN GW GY HT VA HN HU IS IN ID IQ IE IL IT JM JP JO KZ KE KI KW KG LV LB LS LR LI LT LU MG MW MY MV ML MT MH MR MU MX FM MD MC MN ME MA MZ MM NA NR NP NL NZ NI NE NG MK NO OM PK PW PS PA PG PY PE PH PL PT QA RO RW KN LC VC WS SM ST SN RS SC SL SG SK SI SB ZA KR ES LK SR SE CH TW TZ TH TL TG TO TT TN TR TV UG UA AE GB US UY VU ZM) + local SUPPORT_COUNTRY=(AD AE AF AG AL AM AO AR AT AU AZ BA BB BD BE BF BG BH BI BJ BN BO BR BS BT BW BZ CA CD CF CG CH CI CL CM CO CR CV CY CZ DE DJ DK DM DO DZ EC EE EG ER ES ET FI FJ FM FR GA GB GD GE GH GM GN GQ GR GT GW GY HN HR HT HU ID IE IL IN IQ IS IT JM JO JP KE KG KH KI KM KN KR KW KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MG MH MK ML MM MN MR MT MU MV MW MX MY MZ NA NE NG NI NL NO NP NR NZ OM PA PE PG PH PK PL PS PT PW PY QA RO RS RW SA SB SC SD SE SG SI SK SL SM SN SO SR SS ST SV SZ TD TG TH TJ TL TM TN TO TR TT TV TW TZ UA UG US UY UZ VA VC VN VU WS YE ZA ZM ZW) [[ "${SUPPORT_COUNTRY[@]}" =~ $(wget --no-check-certificate -$CHECK_STACK -qO- --tries=3 --timeout=2 https://chat.openai.com/cdn-cgi/trace | awk -F '=' '/loc/{print $2}') ]] && echo 'unlock' || echo 'ban' } @@ -207,141 +215,34 @@ check_root() { # 判断处理器架构 check_arch() { case $(uname -m) in - aarch64|arm64 ) ARGO_ARCH=arm64; XRAY_ARCH=arm64-v8a; JQ_ARCH=arm64; QRENCODE_ARCH=arm64 ;; - x86_64|amd64 ) ARGO_ARCH=amd64; XRAY_ARCH=64; JQ_ARCH=amd64; QRENCODE_ARCH=amd64 ;; - armv7l ) ARGO_ARCH=arm; XRAY_ARCH=arm32-v7a; JQ_ARCH=armhf; QRENCODE_ARCH=arm ;; - * ) error " $(text 25) " ;; + aarch64|arm64 ) + ARGO_ARCH=arm64; XRAY_ARCH=arm64-v8a; JQ_ARCH=arm64; QRENCODE_ARCH=arm64 + ;; + x86_64|amd64 ) + ARGO_ARCH=amd64; XRAY_ARCH=64; JQ_ARCH=amd64; QRENCODE_ARCH=amd64 + ;; + armv7l ) + ARGO_ARCH=arm; XRAY_ARCH=arm32-v7a; JQ_ARCH=armhf; QRENCODE_ARCH=arm + ;; + * ) + error " $(text 25) " esac } # 查安装及运行状态,下标0: argo,下标1: xray,下标2:docker;状态码: 26 未安装, 27 已安装未运行, 28 运行中 check_install() { [ -s $WORK_DIR/nginx.conf ] && IS_NGINX=is_nginx || IS_NGINX=no_nginx - STATUS[0]=$(text 26) && [ -s /etc/systemd/system/argo.service ] && STATUS[0]=$(text 27) && [ "$(systemctl is-active argo)" = 'active' ] && STATUS[0]=$(text 28) + STATUS[0]=$(text 26) && [[ -s /etc/systemd/system/argo.service ]] && grep -q "^ExecStart=$WORK_DIR" /etc/systemd/system/argo.service && STATUS[0]=$(text 27) && [ "$(systemctl is-active argo)" = 'active' ] && STATUS[0]=$(text 28) STATUS[1]=$(text 26) # xray systemd 文件存在的话,检测一下是否本脚本安装的,如果不是则提示并提出 if [ -s /etc/systemd/system/xray.service ]; then ! grep -q "$WORK_DIR" /etc/systemd/system/xray.service && error " $(text 53)\n $(grep 'ExecStart=' /etc/systemd/system/xray.service) " STATUS[1]=$(text 27) && [ "$(systemctl is-active xray)" = 'active' ] && STATUS[1]=$(text 28) fi - [[ ${STATUS[0]} = "$(text 26)" ]] && [ ! -s $WORK_DIR/cloudflared ] && { wget --no-check-certificate -qO $TEMP_DIR/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$ARGO_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/cloudflared >/dev/null 2>&1; }& - [[ ${STATUS[1]} = "$(text 26)" ]] && [ ! -s $WORK_DIR/xray ] && { wget --no-check-certificate -qO $TEMP_DIR/Xray.zip https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-$XRAY_ARCH.zip >/dev/null 2>&1; unzip -qo $TEMP_DIR/Xray.zip xray *.dat -d $TEMP_DIR >/dev/null 2>&1; }& - { wget --no-check-certificate --continue -qO $TEMP_DIR/jq https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-$JQ_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/jq >/dev/null 2>&1; }& - { wget --no-check-certificate --continue -qO $TEMP_DIR/qrencode https://github.com/fscarmen/client_template/raw/main/qrencode-go/qrencode-go-linux-$QRENCODE_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/qrencode >/dev/null 2>&1; }& -} - -# 订阅 api 函数,为保证节点数据的安全性,将置换为伪造数据去获取 api 配置信息,之后再置换为真实的 -fetch_subscribe() { - # 1. 获取参数 - local TARGET=$1 - local REAL_FILE=$2 - local URL=$3 - - # 2. 获取重点键值,由于 sing-box 使用 v2ray 插件不成功的原因,所以 sing-box 去掉 shadowsocks+WSS 的协议 - [ "$TARGET" = 'singbox' ] && local REAL_CONTENT=$(sed '/type: ss/d' $REAL_FILE) || local REAL_CONTENT=$(cat $REAL_FILE) - local REAL_NAME=($(sed -n 's/.*\-[ ]*{[ ]*name:[ ]*"\([^"]*\)".*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_SERVER=($(sed -n 's/.*,[ ]*server:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_SERVERNAME=($(sed -n 's/.*servername:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_HOST=($(sed -n 's/.*ost:[ ]*\([^,}]\+\).*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_SNI=($(sed -n 's/.*sni:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_PORT=($(sed -n 's/.*,[ ]*port:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_UUID=($(sed -n 's/.*,[ ]*uuid:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_PASSWORD=($(sed -n 's/.*,[ ]*password:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_PUBLIC=($(sed -n 's/.*{[ ]*public-key:[ ]*\([^,]\+\),.*/\1/gp' <<< "$REAL_CONTENT")) - local REAL_PATH=($(sed -n 's/.*path:[ ]*"\/\([^"]\+\)",.*/\1/gp' <<< "$REAL_CONTENT")) - - # 3. 混淆各键值 - local FAKE_CONTENT=$REAL_CONTENT - local FAKE_FILE=${REAL_FILE}-${TARGET}-fake - local FAKE_URL=${URL}-${TARGET}-fake - - for d in ${!REAL_NAME[@]}; do - local FAKE_NAME[d]=$(cat /proc/sys/kernel/random/uuid) - local FAKE_CONTENT=$(sed "1,/name: \"${REAL_NAME[d]}/s/${REAL_NAME[d]}/${FAKE_NAME[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_SERVER[@]}; do - local FAKE_SERVER[d]="$(cat /proc/sys/kernel/random/uuid)" - local FAKE_CONTENT=$(sed "1,/server: ${REAL_SERVER[d]}/s/server: ${REAL_SERVER[d]}/server: ${FAKE_SERVER[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_SERVERNAME[@]}; do - local FAKE_SERVERNAME[d]="$(cat /proc/sys/kernel/random/uuid)" - local FAKE_CONTENT=$(sed "1,/servername: ${REAL_SERVERNAME[d]}/s/servername: ${REAL_SERVERNAME[d]}/servername: ${FAKE_SERVERNAME[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_SNI[@]}; do - local FAKE_SNI[d]="$(cat /proc/sys/kernel/random/uuid)" - local FAKE_CONTENT=$(sed "1,/sni: ${REAL_SNI[d]}/s/sni: ${REAL_SNI[d]}/sni: ${FAKE_SNI[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_HOST[@]}; do - local FAKE_HOST[d]="$(cat /proc/sys/kernel/random/uuid)" - local FAKE_CONTENT=$(sed "1,/ost: ${REAL_HOST[d]}/s/ost: ${REAL_HOST[d]}/ost: ${FAKE_HOST[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_PORT[@]}; do - local FAKE_PORT[d]=$(shuf -i 10000-65535 -n 1) - local FAKE_CONTENT=$(sed "1,/port: ${REAL_PORT[d]}/s/port: ${REAL_PORT[d]}/port: ${FAKE_PORT[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_UUID[@]}; do - local FAKE_UUID[d]=$(cat /proc/sys/kernel/random/uuid) - local FAKE_CONTENT=$(sed "1,/uuid: ${REAL_UUID[d]}/s/uuid: ${REAL_UUID[d]}/uuid: ${FAKE_UUID[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_PASSWORD[@]}; do - local FAKE_PASSWORD[d]=$(cat /proc/sys/kernel/random/uuid) - local FAKE_CONTENT=$(sed "1,/password: ${REAL_PASSWORD[d]}/s/password: ${REAL_PASSWORD[d]}/password: ${FAKE_PASSWORD[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_PUBLIC[@]}; do - local FAKE_PUBLIC[d]=$(cat /proc/sys/kernel/random/uuid) - local FAKE_CONTENT=$(sed "1,/public-key: ${REAL_PUBLIC[d]}/s/public-key: ${REAL_PUBLIC[d]}/public-key: ${FAKE_PUBLIC[d]}/" <<< "$FAKE_CONTENT") - done - for d in ${!REAL_PATH[@]}; do - local FAKE_PATH[d]=$(cat /proc/sys/kernel/random/uuid) - local FAKE_CONTENT=$(sed "1,/path: \"${REAL_PATH[d]}\"/s#path: \"/${REAL_PATH[d]}#path: \"/${FAKE_PATH[d]}#" <<< "$FAKE_CONTENT") - done - - # 4. 把混淆节点保存到本地,以让外网能访问 - echo "$FAKE_CONTENT" > $FAKE_FILE - - # 5. 通过转订阅后端 api 获取配置信息 - FROM_API=$(wget --no-check-certificate -qO- --tries=3 --timeout=2 "https://${SUBSCRIBE_API[0]}/sub?target=$TARGET&url=$FAKE_URL&insert=false&config=https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini&emoji=true&list=false&tfo=false&scv=false&fdn=false&sort=false&new_name=true") - - # 6. 删除临时文件 - rm -f $FAKE_FILE - - # 7. 还原数据 - local REAL_CONFIG="$FROM_API" - for d in ${!FAKE_NAME[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_NAME[d]}/${REAL_NAME[d]}/g" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_SERVER[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_SERVER[d]}/${REAL_SERVER[d]}/g" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_SERVERNAME[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_SERVERNAME[d]}/${REAL_SERVERNAME[d]}/" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_SNI[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_SNI[d]}/${REAL_SNI[d]}/g" <<< "$REAL_CONFIG") - done - ### 此处修正理订阅服务里存在的 bug,在 trojan + WSS 协议转换中,server_name 本应是 sni 独立的,转换中 server_name 与 sni 一样了,故修正回来 - local REAL_CONFIG=$(sed "s/${FAKE_SNI[0]}/${FAKE_HOST[2]}/" <<< "$REAL_CONFIG") - for d in ${!FAKE_HOST[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_HOST[d]}/${REAL_HOST[d]}/" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_PORT[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_PORT[d]}/${REAL_PORT[d]}/g" <<<"$REAL_CONFIG") - done - for d in ${!FAKE_UUID[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_UUID[d]}/${REAL_UUID[d]}/g" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_PASSWORD[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_PASSWORD[d]}/${REAL_PASSWORD[d]}/g" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_PUBLIC[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_PUBLIC[d]}/${REAL_PUBLIC[d]}/g" <<< "$REAL_CONFIG") - done - for d in ${!FAKE_PATH[@]}; do - local REAL_CONFIG=$(sed "s/${FAKE_PATH[d]}/${REAL_PATH[d]}/g" <<< "$REAL_CONFIG") - done - - # 8. 输出最终真实结果 - echo "$REAL_CONFIG" + [[ ${STATUS[0]} = "$(text 26)" ]] && [ ! -s $WORK_DIR/cloudflared ] && { wget --no-check-certificate -qO $TEMP_DIR/cloudflared ${GH_PROXY}https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-$ARGO_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/cloudflared >/dev/null 2>&1; }& + [[ ${STATUS[1]} = "$(text 26)" ]] && [ ! -s $WORK_DIR/xray ] && { wget --no-check-certificate -qO $TEMP_DIR/Xray.zip ${GH_PROXY}https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-$XRAY_ARCH.zip >/dev/null 2>&1; unzip -qo $TEMP_DIR/Xray.zip xray *.dat -d $TEMP_DIR >/dev/null 2>&1; }& + { wget --no-check-certificate --continue -qO $TEMP_DIR/jq ${GH_PROXY}https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-$JQ_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/jq >/dev/null 2>&1; }& + { wget --no-check-certificate --continue -qO $TEMP_DIR/qrencode ${GH_PROXY}https://github.com/fscarmen/client_template/raw/main/qrencode-go/qrencode-go-linux-$QRENCODE_ARCH >/dev/null 2>&1 && chmod +x $TEMP_DIR/qrencode >/dev/null 2>&1; }& } # 为了适配 alpine,定义 cmd_systemctl 的函数 @@ -382,25 +283,25 @@ EOF check_system_info() { # 判断虚拟化 - if [ $(type -p systemd-detect-virt) ]; then + if [ -x "$(type -p systemd-detect-virt)" ]; then VIRT=$(systemd-detect-virt) - elif [ $(type -p hostnamectl) ]; then + elif [ -x "$(type -p hostnamectl)" ]; then VIRT=$(hostnamectl | awk '/Virtualization/{print $NF}') - elif [ $(type -p virt-what) ]; then + elif [ -x "$(type -p virt-what)" ]; then VIRT=$(virt-what) fi - [ -s /etc/os-release ] && SYS="$(grep -i pretty_name /etc/os-release | cut -d \" -f2)" - [[ -z "$SYS" && $(type -p hostnamectl) ]] && SYS="$(hostnamectl | grep -i system | cut -d : -f2)" - [[ -z "$SYS" && $(type -p lsb_release) ]] && SYS="$(lsb_release -sd)" - [[ -z "$SYS" && -s /etc/lsb-release ]] && SYS="$(grep -i description /etc/lsb-release | cut -d \" -f2)" - [[ -z "$SYS" && -s /etc/redhat-release ]] && SYS="$(grep . /etc/redhat-release)" - [[ -z "$SYS" && -s /etc/issue ]] && SYS="$(grep . /etc/issue | cut -d '\' -f1 | sed '/^[ ]*$/d')" + [ -s /etc/os-release ] && SYS="$(awk -F '"' 'tolower($0) ~ /pretty_name/{print $2}' /etc/os-release)" + [[ -z "$SYS" && -x "$(type -p hostnamectl)" ]] && SYS="$(hostnamectl | awk -F ': ' 'tolower($0) ~ /operating system/{print $2}')" + [[ -z "$SYS" && -x "$(type -p lsb_release)" ]] && SYS="$(lsb_release -sd)" + [[ -z "$SYS" && -s /etc/lsb-release ]] && SYS="$(awk -F '"' 'tolower($0) ~ /distrib_description/{print $2}' /etc/lsb-release)" + [[ -z "$SYS" && -s /etc/redhat-release ]] && SYS="$(cat /etc/redhat-release)" + [[ -z "$SYS" && -s /etc/issue ]] && SYS="$(sed -E '/^$|^\\/d' /etc/issue | awk -F '\\' '{print $1}' | sed 's/[ ]*$//g')" REGEX=("debian" "ubuntu" "centos|red hat|kernel|alma|rocky" "arch linux" "alpine" "fedora") RELEASE=("Debian" "Ubuntu" "CentOS" "Arch" "Alpine" "Fedora") - EXCLUDE=("") - MAJOR=("9" "16" "7" "3" "" "37") + EXCLUDE=("---") + MAJOR=("9" "16" "7" "" "" "37") PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update" "pacman -Sy" "apk update -f" "dnf -y update") PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "pacman -S --noconfirm" "apk add --no-cache" "dnf -y install") PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "pacman -Rcnsu --noconfirm" "apk del -f" "dnf -y autoremove") @@ -412,11 +313,11 @@ check_system_info() { # 针对各厂商的订制系统 if [ -z "$SYSTEM" ]; then - [ $(type -p yum) ] && int=2 && SYSTEM='CentOS' || error " $(text 5) " + [ -x "$(type -p yum)" ] && int=2 && SYSTEM='CentOS' || error " $(text 5) " fi # 先排除 EXCLUDE 里包括的特定系统,其他系统需要作大发行版本的比较 - for ex in "${EXCLUDE[@]}"; do [[ ! "{$SYS,,}" =~ $ex ]]; done && + for ex in "${EXCLUDE[@]}"; do [[ ! "{$SYS,,}" =~ $ex ]]; done && [[ "$(echo "$SYS" | sed "s/[^0-9.]//g" | cut -d. -f1)" -lt "${MAJOR[int]}" ]] && error " $(text 6) " # 针对部分系统作特殊处理 @@ -425,19 +326,26 @@ check_system_info() { # 检测 IPv4 IPv6 信息 check_system_ip() { - if [ -z "$VARIABLE_FILE" ]; then - IP4=$(wget -4 -qO- --no-check-certificate --user-agent=Mozilla --tries=2 --timeout=3 http://ip-api.com/json/) && - WAN4=$(expr "$IP4" : '.*query\":[ ]*\"\([^"]*\).*') && - COUNTRY4=$(expr "$IP4" : '.*country\":[ ]*\"\([^"]*\).*') && - ASNORG4=$(expr "$IP4" : '.*isp\":[ ]*\"\([^"]*\).*') && - [[ "$L" = C && -n "$COUNTRY4" ]] && COUNTRY4=$(translate "$COUNTRY4") - - IP6=$(wget -6 -qO- --no-check-certificate --user-agent=Mozilla --tries=2 --timeout=3 https://api.ip.sb/geoip) && - WAN6=$(expr "$IP6" : '.*ip\":[ ]*\"\([^"]*\).*') && - COUNTRY6=$(expr "$IP6" : '.*country\":[ ]*\"\([^"]*\).*') && - ASNORG6=$(expr "$IP6" : '.*isp\":[ ]*\"\([^"]*\).*') && - [[ "$L" = C && -n "$COUNTRY6" ]] && COUNTRY6=$(translate "$COUNTRY6") + local DEFAULT_LOCAL_INTERFACE4=$(ip -4 route show default | awk '/default/ {for (i=0; i/dev/null 2>&1 ${PACKAGE_INSTALL[int]} ${DEPS_ALPINE[@]} >/dev/null 2>&1 - [[ -z "$VIRT" && "${DEPS_ALPINE[@]}" =~ 'virt-what' ]] && VIRT=$(virt-what) + [[ -z "$VIRT" && "${DEPS_ALPINE[@]}" =~ 'virt-what' ]] && VIRT=$(virt-what | tr '\n' ' ') fi - [ ! $(type -p systemctl) ] && wget --no-check-certificate --quiet https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl3.py -O /bin/systemctl && chmod a+x /bin/systemctl + [ ! -x "$(type -p systemctl)" ] && wget --no-check-certificate --quiet ${GH_PROXY}https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl3.py -O /bin/systemctl && chmod a+x /bin/systemctl fi # 检测 Linux 系统的依赖,升级库并重新安装依赖 local DEPS_CHECK=("wget" "systemctl" "ss" "unzip" "bash") local DEPS_INSTALL=("wget" "systemctl" "iproute2" "unzip" "bash") - for g in ${!DEPS_CHECK[@]}; do - [ ! $(type -p ${DEPS_CHECK[g]}) ] && DEPS+=(${DEPS_INSTALL[g]}) + for g in "${!DEPS_CHECK[@]}"; do + [ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS+=(${DEPS_INSTALL[g]}) done if [ "${#DEPS[@]}" -ge 1 ]; then info "\n $(text 7) $(sed "s/ /,&/g" <<< ${DEPS[@]}) \n" @@ -601,7 +509,7 @@ check_dependencies() { # 检查并安装 nginx check_nginx() { - if [ ! $(type -p nginx) ]; then + if [ ! -x "$(type -p nginx)" ]; then info "\n $(text 7) nginx \n" ${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1 # 如果新安装的 Nginx ,先停掉服务 @@ -611,7 +519,7 @@ check_nginx() { # 处理防火墙规则 check_firewall_configuration() { - if [[ -s /etc/selinux/config && $(type -p getenforce) && $(getenforce) = 'Enforcing' ]]; then + if [[ -s /etc/selinux/config && -x "$(type -p getenforce)" && $(getenforce) = 'Enforcing' ]]; then hint "\n $(text 69) \n" setenforce 0 sed -i 's/^SELINUX=.*/# &/; /SELINUX=/a\SELINUX=disabled' /etc/selinux/config @@ -640,7 +548,7 @@ events { } http { - map \$http_user_agent \$path1 { + map \$http_user_agent \$path { default /; # 默认路径 ~*v2rayN|Neko /base64; # 匹配 V2rayN / NekoBox 客户端 ~*clash /clash; # 匹配 Clash 客户端 @@ -650,15 +558,6 @@ http { # ~*Chrome|Firefox|Mozilla /; # 添加更多的分流规则 } - map \$http_user_agent \$path2 { - default /; # 默认路径 - ~*v2rayN|Neko /base64; # 匹配 V2rayN / NekoBox 客户端 - ~*clash /clash2; # 匹配 Clash 客户端 - ~*ShadowRocket /shadowrocket; # 匹配 ShadowRocket 客户端 - ~*SFM|SFI|SFA /sing-box2; # 匹配 Sing-box pc 和 phone 客户端 - # ~*Chrome|Firefox|Mozilla /; # 添加更多的分流规则 - } - include /etc/nginx/mime.types; default_type application/octet-stream; @@ -680,16 +579,11 @@ http { server { listen 127.0.0.1:3006 proxy_protocol; # xray fallbacks - # 来自 /auto2 的分流 - location ~ ^/${UUID}/auto2 { - default_type 'text/plain; charset=utf-8'; - alias ${WORK_DIR}/subscribe/\$path2; - } # 来自 /auto 的分流 location ~ ^/${UUID}/auto { default_type 'text/plain; charset=utf-8'; - alias ${WORK_DIR}/subscribe/\$path1; + alias ${WORK_DIR}/subscribe/\$path; } location ~ ^/${UUID}/(.*) { @@ -1156,7 +1050,7 @@ create_shortcut() { cat > $WORK_DIR/ax.sh << EOF #!/usr/bin/env bash -bash <(wget --no-check-certificate -qO- https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) \$1 +bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) \$1 EOF chmod +x $WORK_DIR/ax.sh ln -sf $WORK_DIR/ax.sh /usr/bin/argox @@ -1171,7 +1065,7 @@ export_list() { [[ ! -s $WORK_DIR/jq && -s /usr/bin/jq ]] && cp /usr/bin/jq $WORK_DIR/ if [ ! -s $WORK_DIR/qrencode ]; then check_arch - wget -qO $WORK_DIR/qrencode https://github.com/fscarmen/client_template/raw/main/qrencode-go/qrencode-go-linux-$QRENCODE_ARCH && chmod +x $WORK_DIR/qrencode + wget -qO $WORK_DIR/qrencode ${GH_PROXY}https://github.com/fscarmen/client_template/raw/main/qrencode-go/qrencode-go-linux-$QRENCODE_ARCH && chmod +x $WORK_DIR/qrencode fi fi @@ -1241,8 +1135,6 @@ export_list() { # 生成 clash 订阅配置文件 wget --no-check-certificate -qO- --tries=3 --timeout=2 ${SUBSCRIBE_TEMPLATE}/clash | sed "s#NODE_NAME#${NODE_NAME}#g; s#PROXY_PROVIDERS_URL#http://${ARGO_DOMAIN}/${UUID}/proxies#" > $WORK_DIR/subscribe/clash - fetch_subscribe clash $WORK_DIR/subscribe/proxies https://${ARGO_DOMAIN}/${UUID}/proxies > $WORK_DIR/subscribe/clash2 - # 生成 Shadowrocket 订阅文件 local SHADOWROCKET_SUBSCRIBE="vless://$(echo -n "auto:${UUID}@${SERVER_IP_2}:${REALITY_PORT}" | base64 -w0)?remarks=${NODE_NAME}%20reality-vision&obfs=none&tls=1&peer=${TLS_SERVER}&xtls=2&pbk=${REALITY_PUBLIC} vless://$(echo -n "auto:${UUID}@${SERVER_IP_2}:${REALITY_PORT}" | base64 -w0)?remarks=${NODE_NAME}%20reality-grpc&path=grpc&obfs=grpc&tls=1&peer=${TLS_SERVER}&pbk=${REALITY_PUBLIC} @@ -1265,36 +1157,23 @@ trojan://${UUID}@${SERVER}:443?security=tls&sni=${ARGO_DOMAIN}&type=ws&host=${AR local INBOUND_REPLACE="{ \"type\":\"vless\", \"tag\":\"${NODE_NAME} reality-vision\", \"server\":\"${SERVER_IP}\", \"server_port\": ${REALITY_PORT}, \"uuid\":\"${UUID}\", \"flow\":\"xtls-rprx-vision\", \"packet_encoding\":\"xudp\", \"tls\":{ \"enabled\":true, \"server_name\":\"${TLS_SERVER}\", \"utls\":{ \"enabled\":true, \"fingerprint\":\"chrome\" }, \"reality\":{ \"enabled\":true, \"public_key\":\"${REALITY_PUBLIC}\", \"short_id\":\"\" } } }, { \"type\": \"vless\", \"tag\":\"${NODE_NAME} reality-grpc\", \"server\": \"${SERVER_IP}\", \"server_port\": ${REALITY_PORT}, \"uuid\": \"${UUID}\", \"packet_encoding\":\"xudp\", \"tls\": { \"enabled\": true, \"server_name\": \"${TLS_SERVER}\", \"utls\": { \"enabled\": true, \"fingerprint\": \"chrome\" }, \"reality\": { \"enabled\": true, \"public_key\": \"${REALITY_PUBLIC}\", \"short_id\": \"\" } }, \"transport\": { \"type\": \"grpc\", \"service_name\": \"grpc\" } }, { \"type\":\"vless\", \"tag\":\"${NODE_NAME}-Vl\", \"server\":\"${SERVER}\", \"server_port\":443, \"uuid\":\"${UUID}\", \"tls\": { \"enabled\":true, \"server_name\":\"${ARGO_DOMAIN}\", \"utls\": { \"enabled\":true, \"fingerprint\":\"chrome\" } }, \"transport\": { \"type\":\"ws\", \"path\":\"/${WS_PATH}-vl\", \"headers\": { \"Host\": \"${ARGO_DOMAIN}\" }, \"max_early_data\":2048, \"early_data_header_name\":\"Sec-WebSocket-Protocol\" } }, { \"type\":\"vmess\", \"tag\":\"${NODE_NAME}-Vm\", \"server\":\"${SERVER}\", \"server_port\":443, \"uuid\":\"${UUID}\", \"tls\": { \"enabled\":true, \"server_name\":\"${ARGO_DOMAIN}\", \"utls\": { \"enabled\":true, \"fingerprint\":\"chrome\" } }, \"transport\": { \"type\":\"ws\", \"path\":\"/${WS_PATH}-vm\", \"headers\": { \"Host\": \"${ARGO_DOMAIN}\" }, \"max_early_data\":2048, \"early_data_header_name\":\"Sec-WebSocket-Protocol\" } }, { \"type\":\"trojan\", \"tag\":\"${NODE_NAME}-Tr\", \"server\": \"${SERVER}\", \"server_port\": 443, \"password\": \"${UUID}\", \"tls\": { \"enabled\":true, \"server_name\":\"${ARGO_DOMAIN}\", \"utls\": { \"enabled\":true, \"fingerprint\":\"chrome\" } }, \"transport\": { \"type\":\"ws\", \"path\":\"/${WS_PATH}-tr\", \"headers\": { \"Host\": \"${ARGO_DOMAIN}\" }, \"max_early_data\":2048, \"early_data_header_name\":\"Sec-WebSocket-Protocol\" } }" local NODE_REPLACE="\"${NODE_NAME} reality-vision\", \"${NODE_NAME} reality-grpc\", \"${NODE_NAME}-Vl\", \"${NODE_NAME}-Vm\", \"${NODE_NAME}-Tr\"" - # 模板1 + # 模板 local SING_BOX_JSON1=$(wget --no-check-certificate -qO- --tries=3 --timeout=2 ${SUBSCRIBE_TEMPLATE}/sing-box1) echo $SING_BOX_JSON1 | sed 's#, {[^}]\+"tun-in"[^}]\+}##' | sed "s#\"\"#$INBOUND_REPLACE#; s#\"\"#$NODE_REPLACE#g" | $WORK_DIR/jq > $WORK_DIR/subscribe/sing-box-pc echo $SING_BOX_JSON1 | sed 's# {[^}]\+"mixed"[^}]\+},##; s#, "auto_detect_interface": true##' | sed "s#\"\"#$INBOUND_REPLACE#; s#\"\"#$NODE_REPLACE#g" | $WORK_DIR/jq > $WORK_DIR/subscribe/sing-box-phone - # 模板2 - fetch_subscribe singbox $WORK_DIR/subscribe/proxies https://${ARGO_DOMAIN}/${UUID}/proxies | $WORK_DIR/jq > $WORK_DIR/subscribe/sing-box2 - # 生成二维码 url 文件 [ "$IS_NGINX" = 'is_nginx' ] && cat > $WORK_DIR/subscribe/qr << EOF $(text 66): -$(text 67) 1: +$(text 67): https://${ARGO_DOMAIN}/${UUID}/auto -$(text 67) 2: -https://${ARGO_DOMAIN}/${UUID}/auto2 - -$(text 67) 1: +$(text 67): $(text 64) QRcode: https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://${ARGO_DOMAIN}/${UUID}/auto -$(text 67) 2: -$(text 64) QRcode: -https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://${ARGO_DOMAIN}/${UUID}/auto2 - -$(text 67) 1: +$(text 67): $($WORK_DIR/qrencode "https://${ARGO_DOMAIN}/${UUID}/auto") - -$(text 67) 2: -$($WORK_DIR/qrencode "https://${ARGO_DOMAIN}/${UUID}/auto2") EOF # 生成客户端配置文件 @@ -1370,24 +1249,14 @@ https://${ARGO_DOMAIN}/${UUID}/shadowrocket") ******************************************* $(hint " $(text 66): -$(text 67) 1: +$(text 67): https://${ARGO_DOMAIN}/${UUID}/auto -$(text 67) 2: -https://${ARGO_DOMAIN}/${UUID}/auto2 - $(text 64) QRcode: -$(text 67) 1: -https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://${ARGO_DOMAIN}/${UUID}/auto +$(text 67): +https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://${ARGO_DOMAIN}/${UUID}/auto") -$(text 67) 2: -https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://${ARGO_DOMAIN}/${UUID}/auto2") - -$(hint "$(text 67) 1:") $($WORK_DIR/qrencode https://${ARGO_DOMAIN}/${UUID}/auto) - -$(hint "$(text 67) 2:") -$($WORK_DIR/qrencode https://${ARGO_DOMAIN}/${UUID}/auto2) " EXPORT_LIST_FILE+=" @@ -1466,24 +1335,24 @@ uninstall() { rm -f /etc/local.d/argo.start /etc/local.d/xray.start rc-update add local >/dev/null 2>&1 [ ! $(ls /etc/systemd/system/*.service) ] && rm -f /bin/systemctl - fi + fi } # Argo 与 Xray 的最新版本 version() { # Argo 版本 - local ONLINE=$(wget --no-check-certificate -qO- "https://api.github.com/repos/cloudflare/cloudflared/releases/latest" | grep "tag_name" | cut -d \" -f4) + local ONLINE=$(wget --no-check-certificate -qO- "${GH_PROXY}https://api.github.com/repos/cloudflare/cloudflared/releases/latest" | grep "tag_name" | cut -d \" -f4) local LOCAL=$($WORK_DIR/cloudflared -v | awk '{for (i=0; i