From 7159e0d5b176a8b342942c1aaf3f884f5b25c67a Mon Sep 17 00:00:00 2001 From: fscarmen <62703343+fscarmen@users.noreply.github.com> Date: Tue, 21 May 2024 09:50:46 +0000 Subject: [PATCH] Add Github proxy and translation api; Renew CF CDN; Optimize code. --- README.md | 20 ++--- docker_init.sh | 18 ++++- sing-box.sh | 206 +++++++++++++++++++++++++++++-------------------- 3 files changed, 147 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 52fb089..28de2ca 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b ### 方式2. KV 传参,举例
- 使用 Origin Rule + 订阅 + 使用 Origin Rule + 订阅(点击即可展开或收起)
``` @@ -148,7 +148,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Origin Rule ,不要订阅 + 使用 Origin Rule ,不要订阅(点击即可展开或收起)
``` @@ -168,7 +168,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Argo 临时隧道 + 订阅 + 使用 Argo 临时隧道 + 订阅(点击即可展开或收起)
``` @@ -188,7 +188,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Argo 临时隧道,不要订阅 + 使用 Argo 临时隧道,不要订阅(点击即可展开或收起)
``` @@ -207,7 +207,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Argo Json 隧道 + 订阅 + 使用 Argo Json 隧道 + 订阅(点击即可展开或收起)
``` @@ -229,7 +229,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Argo Json 隧道,不要订阅 + 使用 Argo Json 隧道,不要订阅(点击即可展开或收起)
``` @@ -250,7 +250,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Argo Token 隧道 + 订阅 + 使用 Argo Token 隧道 + 订阅(点击即可展开或收起)
``` @@ -272,7 +272,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
- 使用 Argo Token 隧道,不要订阅 + 使用 Argo Token 隧道,不要订阅(点击即可展开或收起)
``` @@ -338,7 +338,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b * 需要20个连续可用的端口,以 `START_PORT` 开始第一个
- Docker 部署 + Docker 部署(点击即可展开或收起)
``` @@ -369,7 +369,7 @@ docker run -dit \
- Docker Compose 部署 + Docker Compose 部署(点击即可展开或收起)
``` diff --git a/docker_init.sh b/docker_init.sh index 253a11f..fdb43de 100644 --- a/docker_init.sh +++ b/docker_init.sh @@ -67,7 +67,7 @@ install() { local CDN=${CDN:-"skk.moe"} # 检测是否解锁 chatGPT - 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 -qO- --tries=3 --timeout=2 https://chat.openai.com/cdn-cgi/trace | awk -F '=' '/loc/{print $2}') ]] && { CHAT_GPT_OUT_V4=direct && CHAT_GPT_OUT_V6=direct; } || { CHAT_GPT_OUT_V4=warp-IPv4-out && CHAT_GPT_OUT_V6=warp-IPv6-out ; } # 生成 dns 配置 @@ -612,6 +612,7 @@ EOF # 生成 supervisord 配置文件 mkdir -p /etc/supervisor.d SUPERVISORD_CONF="[supervisord] +user=root nodaemon=true logfile=/dev/null pidfile=/run/supervisord.pid @@ -751,6 +752,15 @@ stdout_logfile=/dev/null echo "$NGINX_CONF" > /etc/nginx/nginx.conf + # IPv6 时的 IP 处理 + if [[ "$SERVER_IP" =~ : ]]; then + SERVER_IP_1="[$SERVER_IP]" + SERVER_IP_2="[[$SERVER_IP]]" + else + SERVER_IP_1="$SERVER_IP" + SERVER_IP_2="$SERVER_IP" + fi + # 生成各订阅文件 # 生成 Clash proxy providers 订阅文件 local CLASH_SUBSCRIBE='proxies:' @@ -805,7 +815,7 @@ stdout_logfile=/dev/null vless://$(echo -n "auto:${UUID}@${SERVER_IP_2}:${PORT_XTLS_REALITY}" | base64 -w0)?remarks=${NODE_NAME} xtls-reality&obfs=none&tls=1&peer=addons.mozilla.org&mux=1&pbk=${REALITY_PUBLIC} " [ "${HYSTERIA2}" = 'true' ] && local SHADOWROCKET_SUBSCRIBE+=" -hysteria2://${UUID}@${SERVER_IP_2}:${PORT_HYSTERIA2}?insecure=1&obfs=none#${NODE_NAME}%20hysteria2 +hysteria2://${UUID}@${SERVER_IP_1}:${PORT_HYSTERIA2}?insecure=1&obfs=none#${NODE_NAME}%20hysteria2 " [ "${TUIC}" = 'true' ] && local SHADOWROCKET_SUBSCRIBE+=" tuic://${UUID}:${UUID}@${SERVER_IP_2}:${PORT_TUIC}?congestion_control=bbr&udp_relay_mode=native&alpn=h3&allow_insecure=1#${NODE_NAME}%20tuic @@ -825,7 +835,7 @@ vmess://$(echo -n "none:${UUID}@${CDN}:80" | base64 -w0)?remarks=${NODE_NAME}%20 " [ "${VLESS_WS}" = 'true' ] && local SHADOWROCKET_SUBSCRIBE+=" ---------------------------- -vless://$(echo -n "auto:${UUID}@${CDN}:443" | base64 -w0)?remarks=${NODE_NAME}%20vless-ws-tls&obfsParam=$ v&path=/${UUID}-vless?ed=2048&obfs=websocket&tls=1&peer=${ARGO_DOMAIN}&allowInsecure=1 +vless://$(echo -n "auto:${UUID}@${CDN}:443" | base64 -w0)?remarks=${NODE_NAME} vless-ws-tls&obfsParam=${ARGO_DOMAIN}&path=/${UUID}-vless?ed=2048&obfs=websocket&tls=1&peer=${ARGO_DOMAIN}&allowInsecure=1 " [ "${H2_REALITY}" = 'true' ] && local SHADOWROCKET_SUBSCRIBE+=" ---------------------------- @@ -1016,7 +1026,7 @@ vless://${UUID}@${SERVER_IP_1}:${PORT_GRPC_REALITY}?security=reality&sni=addons. [ "${H2_REALITY}" = 'true' ] && local INBOUND_REPLACE+=" { \"type\": \"vless\", \"tag\": \"${NODE_NAME} h2-reality\", \"server\": \"${SERVER_IP}\", \"server_port\": ${PORT_H2_REALITY}, \"uuid\":\"${UUID}\", \"tls\": { \"enabled\":true, \"server_name\":\"addons.mozilla.org\", \"utls\": { \"enabled\":true, \"fingerprint\":\"chrome\" }, \"reality\":{ \"enabled\":true, \"public_key\":\"${REALITY_PUBLIC}\", \"short_id\":\"\" } }, \"packet_encoding\": \"xudp\", \"transport\": { \"type\": \"http\" } }," && - local NODE_REPLACE+="\"${REALITY_H2_NODE} h2-reality\"," + local NODE_REPLACE+="\"${NODE_NAME} h2-reality\"," [ "${GRPC_REALITY}" = 'true' ] && local INBOUND_REPLACE+=" { \"type\": \"vless\", \"tag\": \"${NODE_NAME} grpc-reality\", \"server\": \"${SERVER_IP}\", \"server_port\": ${PORT_GRPC_REALITY}, \"uuid\":\"${UUID}\", \"tls\": { \"enabled\":true, \"server_name\":\"addons.mozilla.org\", \"utls\": { \"enabled\":true, \"fingerprint\":\"chrome\" }, \"reality\":{ \"enabled\":true, \"public_key\":\"${REALITY_PUBLIC}\", \"short_id\":\"\" } }, \"packet_encoding\": \"xudp\", \"transport\": { \"type\": \"grpc\", \"service_name\": \"grpc\" } }," && diff --git a/sing-box.sh b/sing-box.sh index 27365d5..12ba79b 100644 --- a/sing-box.sh +++ b/sing-box.sh @@ -4,7 +4,7 @@ VERSION='v1.2.4 (2024.05.09)' # 各变量默认值 -GH_PROXY='' +GH_PROXY='https://ghproxy.agrayman.gay/' TEMP_DIR='/tmp/sing-box' WORK_DIR='/etc/sing-box' START_PORT_DEFAULT='8881' @@ -16,9 +16,11 @@ TLS_SERVER_DEFAULT=addons.mozilla.org PROTOCOL_LIST=("XTLS + reality" "hysteria2" "tuic" "ShadowTLS" "shadowsocks" "trojan" "vmess + ws" "vless + ws + tls" "H2 + reality" "gRPC + reality") NODE_TAG=("xtls-reality" "hysteria2" "tuic" "ShadowTLS" "shadowsocks" "trojan" "vmess-ws" "vless-ws-tls" "h2-reality" "grpc-reality") CONSECUTIVE_PORTS=${#PROTOCOL_LIST[@]} -CDN_DOMAIN=("cn.azhz.eu.org" "dash.cloudflare.com" "skk.moe" "visa.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" +export DEBIAN_FRONTEND=noninteractive + trap "rm -rf $TEMP_DIR >/dev/null 2>&1 ; echo -e '\n' ;exit 1" INT QUIT TERM EXIT mkdir -p $TEMP_DIR @@ -221,6 +223,8 @@ E[97]="Port Hopping/Multiple Ports (Port Hopping) function needs to occupy multi C[97]="端口跳跃/多端口(Port Hopping)功能需要占用多个端口,请保证这些端口没有监听其他服务\n Tip1: 端口选择数量不宜过多,推荐1000个左右,最小值:$MIN_HOPPING_PORT,最大值: $MAX_HOPPING_PORT\n Tip2: nat 鸡由于可用于监听的端口有限,一般为20-30个。如设置了不开放的端口会导致节点不通,请慎用!\n 默认不使用该功能" E[98]="Enter the port range, e.g. 50000:51000. Leave blank to disable:" C[98]="请输入端口范围,例如 50000:51000,如要禁用请留空:" +E[99]="The \${SING_BOX_SCRIPT} is detected to be installed. Script exits." +C[99]="检测到已安装 \${SING_BOX_SCRIPT},脚本退出!" # 自定义字体彩色,read 函数 warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色 @@ -230,22 +234,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:]]/%20}" 2>/dev/null) - [[ "$ZH" =~ ^\[\".+\"\]$ ]] && awk -F '"' '{print $2}' <<< "$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/sing-box/main/README.md >/dev/null 2>&1 && unset GH_PROXY + [ -n "$GH_PROXY" ] && wget --server-response --quiet --output-document=/dev/null --no-check-certificate --tries=2 --timeout=3 https://raw.githubusercontent.com/fscarmen/sing-box/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' } @@ -259,12 +264,12 @@ statistics_of_run-times() { # 选择中英语言 select_language() { if [ -z "$L" ]; then - case $(cat $WORK_DIR/language 2>&1) in - E ) L=E ;; - C ) L=C ;; - * ) [ -z "$L" ] && L=E && hint "\n $(text 0) \n" && reading " $(text 24) " LANGUAGE - [ "$LANGUAGE" = 2 ] && L=C ;; - esac + if [ -s $WORK_DIR/language ]; then + L=$(cat $WORK_DIR/language) + else + L=E && hint "\n $(text 0) \n" && reading " $(text 24) " LANGUAGE + [ "$LANGUAGE" = 2 ] && L=C + fi fi } @@ -277,8 +282,8 @@ asc() { fi } +# 收录一些热心网友和官网的 cdn input_cdn() { - # 提供网上热心网友的anycast域名 echo "" for c in "${!CDN_DOMAIN[@]}"; do hint " $[c+1]. ${CDN_DOMAIN[c]} " @@ -288,10 +293,10 @@ input_cdn() { case "$CUSTOM_CDN" in [1-${#CDN_DOMAIN[@]}] ) CDN="${CDN_DOMAIN[$((CUSTOM_CDN-1))]}" - ;; + ;; ?????* ) CDN="$CUSTOM_CDN" - ;; + ;; * ) CDN="${CDN_DOMAIN[0]}" esac @@ -476,16 +481,42 @@ check_install() { check_port_hopping_nat [ -n "$PORT_HOPPING_END" ] && IS_HOPPING=is_hopping || IS_HOPPING=no_hopping fi - STATUS[0]=$(text 26) && [ -s /etc/systemd/system/sing-box.service ] && STATUS[0]=$(text 27) && [ "$(systemctl is-active sing-box)" = 'active' ] && STATUS[0]=$(text 28) + + # 检测是否安装其他 sing-box systemd 状态,和是否其他一键脚本 + if [ -s /etc/systemd/system/sing-box.service ]; then + SYSTEMD_EXECSTART=$(grep '^ExecStart=' /etc/systemd/system/sing-box.service) + case "$SYSTEMD_EXECSTART" in + 'ExecStart=/etc/sing-box/sing-box run -C /etc/sing-box/conf/' ) + [ "$(systemctl is-active sing-box)" = 'active' ] && STATUS[0]=$(text 28) || STATUS[0]=$(text 27) + ;; + 'ExecStart=/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json' ) + SING_BOX_SCRIPT='mack-a/v2ray-agent' && error "\n $(text 99) \n" + ;; + 'ExecStart=/etc/s-box/sing-box run -c /etc/s-box/sb.json' ) + SING_BOX_SCRIPT='yonggekkk/sing-box_hysteria2_tuic_argo_reality' && error "\n $(text 99) \n" + ;; + 'ExecStart=/usr/local/s-ui/bin/runSingbox.sh' ) + SING_BOX_SCRIPT='alireza0/s-ui' && error "\n $(text 99) \n" + ;; + 'ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json' ) + SING_BOX_SCRIPT='FranzKafkaYu/sing-box-yes' && error "\n $(text 99) \n" + ;; + * ) + SING_BOX_SCRIPT='Unknown or customized sing-box' && error "\n $(text 99) \n" + esac + else + STATUS[0]=$(text 26) + fi + if [ "${STATUS[0]}" = "$(text 26)" ] && [ ! -s $WORK_DIR/sing-box ]; then { - local VERSION_LATEST=$(wget --no-check-certificate -qO- "https://api.github.com/repos/SagerNet/sing-box/releases" | awk -F '["v-]' '/tag_name/{print $5}' | sort -r | sed -n '1p') - local ONLINE=$(wget --no-check-certificate -qO- "https://api.github.com/repos/SagerNet/sing-box/releases" | awk -F '["v]' -v var="tag_name.*$VERSION_LATEST" '$0 ~ var {print $5; exit}') - ONLINE=${ONLINE:-'1.9.0-rc.14'} + local VERSION_LATEST=$(wget --no-check-certificate --tries=2 --timeout=3 -qO- ${GH_PROXY}https://api.github.com/repos/SagerNet/sing-box/releases | awk -F '["v-]' '/tag_name/{print $5}' | sort -r | sed -n '1p') + local ONLINE=$(wget --no-check-certificate --tries=2 --timeout=3 -qO- ${GH_PROXY}https://api.github.com/repos/SagerNet/sing-box/releases | awk -F '["v]' -v var="tag_name.*$VERSION_LATEST" '$0 ~ var {print $5; exit}') + ONLINE=${ONLINE:-'1.9.0-rc.18'} wget --no-check-certificate --continue ${GH_PROXY}https://github.com/SagerNet/sing-box/releases/download/v$ONLINE/sing-box-$ONLINE-linux-$SING_BOX_ARCH.tar.gz -qO- | tar xz -C $TEMP_DIR sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box >/dev/null 2>&1 [ -s $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box ] && mv $TEMP_DIR/sing-box-$ONLINE-linux-$SING_BOX_ARCH/sing-box $TEMP_DIR 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 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 + 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 }& fi @@ -502,7 +533,7 @@ check_install() { ARGO_TYPE=is_quicktunnel_argo fi fi - [[ "${STATUS[1]}" = "$(text 26)" || "$NONINTERACTIVE_INSTALL" = 'noninteractive_install' ]] && [ ! -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)" || "$NONINTERACTIVE_INSTALL" = 'noninteractive_install' ]] && [ ! -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; }& } # 检测 sing-box 的状态 @@ -571,17 +602,17 @@ 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="$(awk -F '"' 'tolower($0) ~ /pretty_name/{print $2}' /etc/os-release)" - [[ -z "$SYS" && $(type -p hostnamectl) ]] && SYS="$(hostnamectl | awk -F ': ' 'tolower($0) ~ /operating system/{print $2}')" - [[ -z "$SYS" && $(type -p lsb_release) ]] && SYS="$(lsb_release -sd)" + [[ -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')" @@ -591,7 +622,7 @@ check_system_info() { EXCLUDE=("") MAJOR=("9" "16" "7" "3" "" "37") PACKAGE_UPDATE=("apt -y update" "apt -y update" "yum -y update --skip-broken" "pacman -Sy" "apk update -f" "dnf -y update") - PACKAGE_INSTALL=("DEBIAN_FRONTEND=noninteractive apt -y install" "DEBIAN_FRONTEND=noninteractive apt -y install" "yum -y install" "pacman -S --noconfirm" "apk add --no-cache" "dnf -y install") + 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") for int in "${!REGEX[@]}"; do @@ -600,7 +631,7 @@ 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 里包括的特定系统,其他系统需要作大发行版本的比较 @@ -648,7 +679,8 @@ add_port_hopping_nat() { rc-service iptables save >/dev/null 2>&1 rc-service ip6tables save >/dev/null 2>&1 - elif [ "$(systemctl is-active firewalld)" = 'active' ]; then + elif [ -x "$(type -p firewalld)" ]; then + [ "$(systemctl is-active firewalld)" != 'active' ] && systemctl enable --now firewalld >/dev/null 2>&1 if [ "$(firewall-cmd --query-masquerade --permanent)" != 'yes' ] ; then firewall-cmd --add-masquerade --permanent >/dev/null 2>&1 firewall-cmd --reload >/dev/null 2>&1 @@ -660,7 +692,7 @@ add_port_hopping_nat() { firewall-cmd --reload >/dev/null 2>&1 else - if ! [ -x "$(type -p netfilter-persistent)" ]; then + if [ ! -x "$(type -p netfilter-persistent)" ]; then info "\n $(text 7) iptables-persistent" ${PACKAGE_INSTALL[int]} iptables-persistent >/dev/null 2>&1 fi @@ -679,36 +711,39 @@ add_port_hopping_nat() { check_port_hopping_nat() { PORT_HOPPING_TARGET=$(awk -F [:,] '/"listen_port"/{print $2}' $WORK_DIR/conf/*${NODE_TAG[1]}_inbounds.json) if [ "$SYSTEM" = 'Alpine' ]; then - [[ $(iptables --list --table nat 2>/dev/null) =~ 'Sing-box Family Bucket' ]] && PORT_HOPPING_RANGE=$(iptables --table nat -S PREROUTING 2>/dev/null | awk '/Sing-box Family Bucket/ {for (i=0; i/dev/null | awk '/Sing-box Family Bucket/ {for (i=0; i/dev/null | grep 'Sing-box Family Bucket') + [ -n "$IPTABLES_PREROUTING_LIST" ] && PORT_HOPPING_RANGE=$(awk '{for (i=0; i/dev/null | grep 'Sing-box Family Bucket') + [ -n "$IPTABLES_PREROUTING_LIST" ] && PORT_HOPPING_RANGE=$(awk '{for (i=0; i&1 | head -n 1) grep -qi 'busybox' <<< "$CHECK_WGET" && ${PACKAGE_INSTALL[int]} wget >/dev/null 2>&1 - local DEPS_CHECK=("bash" "rc-update" "virt-what" "python3") - local DEPS_INSTALL=("bash" "openrc" "virt-what" "python3") + local DEPS_CHECK=("bash" "rc-update" "virt-what" "python3" "iptables" "ip6tables") + local DEPS_INSTALL=("bash" "openrc" "virt-what" "python3" "iptables" "ip6tables") for g in "${!DEPS_CHECK[@]}"; do - [ ! $(type -p ${DEPS_CHECK[g]}) ] && DEPS_ALPINE+=(${DEPS_INSTALL[g]}) + [ ! -x "$(type -p ${DEPS_CHECK[g]})" ] && DEPS_ALPINE+=(${DEPS_INSTALL[g]}) done if [ "${#DEPS_ALPINE[@]}" -ge 1 ]; then info "\n $(text 7) $(sed "s/ /,&/g" <<< ${DEPS_ALPINE[@]}) \n" ${PACKAGE_UPDATE[int]} >/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" "tar" "systemctl" "ss" "bash" "openssl" "iptables" "ip6tables") - local DEPS_INSTALL=("wget" "tar" "systemctl" "iproute2" "bash" "openssl" "iptables" "ip6tables") + local DEPS_CHECK=("wget" "tar" "systemctl" "ss" "bash" "openssl") + local DEPS_INSTALL=("wget" "tar" "systemctl" "iproute2" "bash" "openssl") for g in "${!DEPS_CHECK[@]}"; do - [ ! $(type -p ${DEPS_CHECK[g]}) ] && DEPS+=(${DEPS_INSTALL[g]}) + [ ! -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" - if [ "$IS_CENTOS" = 'CentOS7' ]; then - yum repolist | grep -q epef || ${PACKAGE_INSTALL[int]} epel-release >/dev/null 2>&1 - else - ${PACKAGE_UPDATE[int]} >/dev/null 2>&1 - fi + + if [ "$IS_CENTOS" = 'CentOS7' ]; then + yum repolist | grep -q epef || DEPS+=(epel-release) + [ ! -x "$(type -p firewalld)" ] && DEPS+=(firewalld) + elif [ "$IS_CENTOS" = 'CentOS8' ]; then + [ ! -x "$(type -p firewalld)" ] && DEPS+=(firewalld) + else + [ ! -x "$(type -p iptables)" ] && DEPS+=(iptables) + [ ! -x "$(type -p ip6tables)" ] && DEPS+=(ip6tables) + fi + + # 如需要安装的依赖大于0,就更新库并安装 + if [[ "${#DEPS[@]}" > 0 ]]; then + [[ ! "$SYSTEM" =~ Alpine|CentOS ]] && ${PACKAGE_UPDATE[int]} >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} ${DEPS[@]} >/dev/null 2>&1 else info "\n $(text 8) \n" @@ -899,7 +941,7 @@ check_dependencies() { # 检查并安装 nginx check_nginx() { - if [ ! $(type -p nginx) ]; then + if [ ! -x "$(type -p nginx)" ]; then info "\n $(text 7) nginx \n" ${PACKAGE_UPDATE[int]} >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1 @@ -932,7 +974,7 @@ ssl_certificate() { # 处理防火墙规则 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 84) " setenforce 0 sed -i 's/^SELINUX=.*/# &/; /SELINUX=/a\SELINUX=disabled' /etc/selinux/config @@ -942,7 +984,7 @@ check_firewall_configuration() { # Nginx 配置文件 export_nginx_conf_file() { # 在添加协议,需要用到 nginx 的时候,先检测是否已经安装 - if ! [ -x "$(type -p nginx)" ]; then + if [ ! -x "$(type -p nginx)" ]; then info "\n $(text 7) nginx" ${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1 fi @@ -1771,13 +1813,11 @@ fetch_nodes_value() { # 获取 Argo 临时隧道域名 fetch_quicktunnel_domain() { unset CLOUDFLARED_PID METRICS_ADDRESS ARGO_DOMAIN - local QUICKTUNNEL_ERROR_TIME=10 + local QUICKTUNNEL_ERROR_TIME=20 until [ -n "$ARGO_DOMAIN" ]; do - if [ -z "$CLOUDFLARED_PID" ]; then - [ "$SYSTEM" = 'Alpine' ] && CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="$WORK_DIR" '$0 ~ WORKDIR"/cloudflared" {print $1; exit}') || CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="$WORK_DIR" '$0 ~ WORK_DIR"/cloudflared" {print $2; exit}') - fi + [ "$SYSTEM" = 'Alpine' ] && CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="$WORK_DIR" '$0 ~ WORK_DIR"/cloudflared" {print $1; exit}') || CLOUDFLARED_PID=$(ps -ef | awk -v WORK_DIR="$WORK_DIR" '$0 ~ WORK_DIR"/cloudflared" {print $2; exit}') [[ -z "$METRICS_ADDRESS" && "$CLOUDFLARED_PID" =~ ^[0-9]+$ ]] && METRICS_ADDRESS=$(ss -nltp | grep "pid=$CLOUDFLARED_PID" | awk '{print $4}') - ARGO_DOMAIN=$(wget -qO- http://$METRICS_ADDRESS/quicktunnel | awk -F '"' '{print $4}') + [ -n "$METRICS_ADDRESS" ] && ARGO_DOMAIN=$(wget -qO- http://$METRICS_ADDRESS/quicktunnel | awk -F '"' '{print $4}') [[ ! "$ARGO_DOMAIN" =~ trycloudflare\.com$ ]] && (( QUICKTUNNEL_ERROR_TIME-- )) && sleep 2 || break [ "$QUICKTUNNEL_ERROR_TIME" = '0' ] && error " $(text 93) " done @@ -1844,7 +1884,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 @@ -1970,7 +2010,7 @@ vless://$(echo -n "auto:${UUID[11]}@${SERVER_IP_2}:${PORT_XTLS_REALITY}" | base6 if [ -n "$PORT_HYSTERIA2" ]; then [[ -n "$PORT_HOPPING_START" && -n "$PORT_HOPPING_END" ]] && local SHADOWROCKET_HOPPING="&mport=${PORT_HYSTERIA2},${PORT_HOPPING_START}-${PORT_HOPPING_END}" local SHADOWROCKET_SUBSCRIBE+=" -hysteria2://${UUID[12]}@${SERVER_IP_2}:${PORT_HYSTERIA2}?insecure=1&obfs=none${SHADOWROCKET_HOPPING}#${NODE_NAME[12]}%20${NODE_TAG[1]} +hysteria2://${UUID[12]}@${SERVER_IP_1}:${PORT_HYSTERIA2}?insecure=1&obfs=none${SHADOWROCKET_HOPPING}#${NODE_NAME[12]}%20${NODE_TAG[1]} " fi @@ -2017,7 +2057,7 @@ vless://$(echo -n "auto:${UUID[18]}@${CDN[18]}:443" | base64 -w0)?remarks=${NODE else WS_SERVER_IP_SHOW=${WS_SERVER_IP[18]} && TYPE_HOST_DOMAIN=$VLESS_HOST_DOMAIN && TYPE_PORT_WS=$PORT_VLESS_WS && local SHADOWROCKET_SUBSCRIBE+=" ---------------------------- -vless://$(echo -n "auto:${UUID[18]}@${CDN[18]}:443" | base64 -w0)?remarks=${NODE_NAME[18]}%20${NODE_TAG[7]}&obfsParam=$VLESS_HOST_DOMAIN&path=/$VLESS_WS_PATH?ed=2048&obfs=websocket&tls=1&peer=$VLESS_HOST_DOMAIN&allowInsecure=1 +vless://$(echo -n "auto:${UUID[18]}@${CDN[18]}:443" | base64 -w0)?remarks=${NODE_NAME[18]} ${NODE_TAG[7]}&obfsParam=$VLESS_HOST_DOMAIN&path=/$VLESS_WS_PATH?ed=2048&obfs=websocket&tls=1&peer=$VLESS_HOST_DOMAIN&allowInsecure=1 # $(text 52) " @@ -2568,6 +2608,9 @@ change_protocols() { done done + # 如有需要,删除 hysteria2 跳跃端口,待后面添加回来 + [ "$IS_HOPPING" = 'is_hopping' ] && del_port_hopping_nat + # 删除不需要的协议配置文件 [ "${#REMOVE_FILE[@]}" -gt 0 ] && for t in "${REMOVE_FILE[@]}"; do rm -f $WORK_DIR/conf/*${t} @@ -2739,7 +2782,7 @@ change_protocols() { POSITION=$(awk -v target=$CHECK_PROTOCOLS '{ for(i=1; i<=NF; i++) if($i == target) { print i-1; break } }' <<< "${INSTALL_PROTOCOLS[*]}") PORT_GRPC_REALITY=${REINSTALL_PORTS[POSITION]} else - PORT_GRPC_REALITY + unset PORT_GRPC_REALITY fi # 停止 sing-box 服务 @@ -2763,9 +2806,6 @@ change_protocols() { [ -s $WORK_DIR/tunnel.json ] && rm -f $WORK_DIR/tunnel.* fi - # 如有需要,删除 hysteria2 跳跃端口 - ! ls $WORK_DIR/conf/*${NODE_TAG[1]}_inbounds.json >/dev/null 2>&1 && del_port_hopping_nat - # 如有需要,删除 nginx 配置文件 ! ls /etc/systemd/system/argo.service >/dev/null 2>&1 && [[ -s $WORK_DIR/nginx.conf && "$IS_SUB" = 'no_sub' ]] && IS_ARGO=no_argo && rm -f $WORK_DIR/nginx.conf @@ -2809,8 +2849,8 @@ uninstall() { # Sing-box 的最新版本 version() { - local VERSION_LATEST=$(wget --no-check-certificate -qO- "https://api.github.com/repos/SagerNet/sing-box/releases" | awk -F '["v-]' '/tag_name/{print $5}' | sort -r | sed -n '1p') - local ONLINE=$(wget --no-check-certificate -qO- "https://api.github.com/repos/SagerNet/sing-box/releases" | awk -F '["v]' -v var="tag_name.*$VERSION_LATEST" '$0 ~ var {print $5; exit}') + local VERSION_LATEST=$(wget --no-check-certificate -qO- ${GH_PROXY}https://api.github.com/repos/SagerNet/sing-box/releases | awk -F '["v-]' '/tag_name/{print $5}' | sort -r | sed -n '1p') + local ONLINE=$(wget --no-check-certificate -qO- ${GH_PROXY}https://api.github.com/repos/SagerNet/sing-box/releases | awk -F '["v]' -v var="tag_name.*$VERSION_LATEST" '$0 ~ var {print $5; exit}') local LOCAL=$($WORK_DIR/sing-box version | awk '/version/{print $NF}') info "\n $(text 40) " [[ -n "$ONLINE" && "$ONLINE" != "$LOCAL" ]] && reading "\n $(text 9) " UPDATE || info " $(text 41) " @@ -2848,7 +2888,7 @@ menu_setting() { fi # 查 Nginx 版本号 - [ $(type -p nginx) ] && NGINX_VERSION=$(nginx -v 2>&1 | sed "s#.*/#Version: #") + [ -x "$(type -p nginx)" ] && NGINX_VERSION=$(nginx -v 2>&1 | sed "s#.*/#Version: #") [ "$SYSTEM" = 'Alpine' ] && NGINX_PID=$(ps -ef | awk -v WORK_DIR="$WORK_DIR" '$0 ~ WORK_DIR"/nginx.conf" {print $1; exit}') || NGINX_PID=$(ps -ef | awk -v WORK_DIR="$WORK_DIR" '$0 ~ WORK_DIR"/nginx.conf" {print $2; exit}') [[ "$NGINX_PID" =~ ^[0-9]+$ ]] && NGINX_MEMORY_USAGE="$(text 58): $(awk '/VmRSS/{printf "%.1f\n", $2/1024}' /proc/$NGINX_PID/status) MB" @@ -2876,11 +2916,11 @@ menu_setting() { ACTION[4]() { change_argo; exit; } ACTION[5]() { change_start_port; exit; } ACTION[6]() { version; exit; } - ACTION[7]() { bash <(wget --no-check-certificate -qO- "https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh"); exit; } + ACTION[7]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh); exit; } ACTION[8]() { change_protocols; exit; } ACTION[9]() { uninstall; exit; } - ACTION[10]() { bash <(wget --no-check-certificate -qO- https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) -$L; exit; } - ACTION[11]() { bash <(wget --no-check-certificate -qO- https://raw.githubusercontent.com/fscarmen/sba/main/sba.sh) -$L; exit; } + ACTION[10]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) -$L; exit; } + ACTION[11]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/fscarmen/sba/main/sba.sh) -$L; exit; } ACTION[12]() { bash <(wget --no-check-certificate -qO- https://tcp.hy2.sh/); exit; } else OPTION[1]="1. $(text 34) + Argo + $(text 80) $(text 89)" @@ -2896,10 +2936,10 @@ menu_setting() { ACTION[2]() { IS_SUB=no_sub; IS_ARGO=is_argo; install_sing-box; export_list install; create_shortcut; exit; } ACTION[3]() { IS_SUB=is_sub; IS_ARGO=no_argo; install_sing-box; export_list install; create_shortcut; exit; } ACTION[4]() { install_sing-box; export_list install; create_shortcut; exit; } - ACTION[5]() { bash <(wget --no-check-certificate -qO- "https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh"); exit; } - ACTION[6]() { bash <(wget --no-check-certificate -qO- https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) -$L; exit; } - ACTION[7]() { bash <(wget --no-check-certificate -qO- https://raw.githubusercontent.com/fscarmen/sba/main/sba.sh) -$L; exit; } - ACTION[8]() { bash <(wget --no-check-certificate -qO- https://tcp.hy2.sh/); exit; } + ACTION[5]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh); exit; } + ACTION[6]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) -$L; exit; } + ACTION[7]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/fscarmen/sba/main/sba.sh) -$L; exit; } + ACTION[8]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://tcp.hy2.sh/); exit; } fi [ "${#OPTION[@]}" -ge '10' ] && OPTION[0]="0 . $(text 35)" || OPTION[0]="0. $(text 35)" @@ -2966,7 +3006,7 @@ for z in ${!ALL_PARAMETER[@]}; do check_arch; version; exit 0 ;; -B ) - bash <(wget --no-check-certificate -qO- "https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh"); exit + bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh); exit ;; -R ) change_protocols; exit 0