Add Github proxy and translation api; Renew CF CDN; Optimize code.

This commit is contained in:
fscarmen
2024-05-21 09:50:46 +00:00
parent d74115d209
commit 7159e0d5b1
3 changed files with 147 additions and 97 deletions
+10 -10
View File
@@ -126,7 +126,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
### 方式2. KV 传参,举例 ### 方式2. KV 传参,举例
<details> <details>
<summary> 使用 Origin Rule + 订阅</summary> <summary> 使用 Origin Rule + 订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -148,7 +148,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Origin Rule ,不要订阅 </summary> <summary> 使用 Origin Rule ,不要订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -168,7 +168,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Argo 临时隧道 + 订阅 </summary> <summary> 使用 Argo 临时隧道 + 订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -188,7 +188,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Argo 临时隧道,不要订阅 </summary> <summary> 使用 Argo 临时隧道,不要订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -207,7 +207,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Argo Json 隧道 + 订阅 </summary> <summary> 使用 Argo Json 隧道 + 订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -229,7 +229,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Argo Json 隧道,不要订阅 </summary> <summary> 使用 Argo Json 隧道,不要订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -250,7 +250,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Argo Token 隧道 + 订阅 </summary> <summary> 使用 Argo Token 隧道 + 订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -272,7 +272,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
</details> </details>
<details> <details>
<summary> 使用 Argo Token 隧道,不要订阅 </summary> <summary> 使用 Argo Token 隧道,不要订阅(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -338,7 +338,7 @@ bash <(wget -qO- https://raw.githubusercontent.com/fscarmen/sing-box/main/sing-b
* 需要20个连续可用的端口,以 `START_PORT` 开始第一个 * 需要20个连续可用的端口,以 `START_PORT` 开始第一个
<details> <details>
<summary> Docker 部署 </summary> <summary> Docker 部署(点击即可展开或收起)</summary>
<br> <br>
``` ```
@@ -369,7 +369,7 @@ docker run -dit \
</details> </details>
<details> <details>
<summary> Docker Compose 部署 </summary> <summary> Docker Compose 部署(点击即可展开或收起)</summary>
<br> <br>
``` ```
+14 -4
View File
@@ -67,7 +67,7 @@ install() {
local CDN=${CDN:-"skk.moe"} local CDN=${CDN:-"skk.moe"}
# 检测是否解锁 chatGPT # 检测是否解锁 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 ; } [[ "${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 配置 # 生成 dns 配置
@@ -612,6 +612,7 @@ EOF
# 生成 supervisord 配置文件 # 生成 supervisord 配置文件
mkdir -p /etc/supervisor.d mkdir -p /etc/supervisor.d
SUPERVISORD_CONF="[supervisord] SUPERVISORD_CONF="[supervisord]
user=root
nodaemon=true nodaemon=true
logfile=/dev/null logfile=/dev/null
pidfile=/run/supervisord.pid pidfile=/run/supervisord.pid
@@ -751,6 +752,15 @@ stdout_logfile=/dev/null
echo "$NGINX_CONF" > /etc/nginx/nginx.conf 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 订阅文件 # 生成 Clash proxy providers 订阅文件
local CLASH_SUBSCRIBE='proxies:' 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} 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}" = '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}" = '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 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_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+=" [ "${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' ] && [ "${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 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' ] && [ "${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\" } }," && 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\" } }," &&
+117 -77
View File
@@ -4,7 +4,7 @@
VERSION='v1.2.4 (2024.05.09)' VERSION='v1.2.4 (2024.05.09)'
# 各变量默认值 # 各变量默认值
GH_PROXY='' GH_PROXY='https://ghproxy.agrayman.gay/'
TEMP_DIR='/tmp/sing-box' TEMP_DIR='/tmp/sing-box'
WORK_DIR='/etc/sing-box' WORK_DIR='/etc/sing-box'
START_PORT_DEFAULT='8881' 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") 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") NODE_TAG=("xtls-reality" "hysteria2" "tuic" "ShadowTLS" "shadowsocks" "trojan" "vmess-ws" "vless-ws-tls" "h2-reality" "grpc-reality")
CONSECUTIVE_PORTS=${#PROTOCOL_LIST[@]} 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" 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 trap "rm -rf $TEMP_DIR >/dev/null 2>&1 ; echo -e '\n' ;exit 1" INT QUIT TERM EXIT
mkdir -p $TEMP_DIR 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 默认不使用该功能" 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:" E[98]="Enter the port range, e.g. 50000:51000. Leave blank to disable:"
C[98]="请输入端口范围,例如 50000:51000,如要禁用请留空:" C[98]="请输入端口范围,例如 50000:51000,如要禁用请留空:"
E[99]="The \${SING_BOX_SCRIPT} is detected to be installed. Script exits."
C[99]="检测到已安装 \${SING_BOX_SCRIPT},脚本退出!"
# 自定义字体彩色,read 函数 # 自定义字体彩色,read 函数
warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色 warning() { echo -e "\033[31m\033[01m$*\033[0m"; } # 红色
@@ -230,11 +234,12 @@ hint() { echo -e "\033[33m\033[01m$*\033[0m"; } # 黄色
reading() { read -rp "$(info "$1")" "$2"; } reading() { read -rp "$(info "$1")" "$2"; }
text() { grep -q '\$' <<< "${E[$*]}" && eval echo "\$(eval echo "\${${L}[$*]}")" || eval echo "\${${L}[$*]}"; } text() { grep -q '\$' <<< "${E[$*]}" && eval echo "\$(eval echo "\${${L}[$*]}")" || eval echo "\${${L}[$*]}"; }
# 自定义谷歌翻译函数 # 自定义谷歌翻译函数,使用两个翻译 api,如均不能翻译,则返回原英文
translate() { translate() {
[ -n "$@" ] && EN="$@" [ -n "$@" ] && local 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) [ -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}')
[[ "$ZH" =~ ^\[\".+\"\]$ ]] && awk -F '"' '{print $2}' <<< "$ZH" [ -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,如能直接连通,则不使用 # 检测是否需要启用 Github CDN,如能直接连通,则不使用
@@ -245,7 +250,7 @@ check_cdn() {
# 检测是否解锁 chatGPT,以决定是否使用 warp 链式代理或者是 direct out # 检测是否解锁 chatGPT,以决定是否使用 warp 链式代理或者是 direct out
check_chatgpt() { check_chatgpt() {
local CHECK_STACK=$1 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' [[ "${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() { select_language() {
if [ -z "$L" ]; then if [ -z "$L" ]; then
case $(cat $WORK_DIR/language 2>&1) in if [ -s $WORK_DIR/language ]; then
E ) L=E ;; L=$(cat $WORK_DIR/language)
C ) L=C ;; else
* ) [ -z "$L" ] && L=E && hint "\n $(text 0) \n" && reading " $(text 24) " LANGUAGE L=E && hint "\n $(text 0) \n" && reading " $(text 24) " LANGUAGE
[ "$LANGUAGE" = 2 ] && L=C ;; [ "$LANGUAGE" = 2 ] && L=C
esac fi
fi fi
} }
@@ -277,8 +282,8 @@ asc() {
fi fi
} }
# 收录一些热心网友和官网的 cdn
input_cdn() { input_cdn() {
# 提供网上热心网友的anycast域名
echo "" echo ""
for c in "${!CDN_DOMAIN[@]}"; do for c in "${!CDN_DOMAIN[@]}"; do
hint " $[c+1]. ${CDN_DOMAIN[c]} " hint " $[c+1]. ${CDN_DOMAIN[c]} "
@@ -476,16 +481,42 @@ check_install() {
check_port_hopping_nat check_port_hopping_nat
[ -n "$PORT_HOPPING_END" ] && IS_HOPPING=is_hopping || IS_HOPPING=no_hopping [ -n "$PORT_HOPPING_END" ] && IS_HOPPING=is_hopping || IS_HOPPING=no_hopping
fi 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 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 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 -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 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.14'} 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 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 [ -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/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 fi
@@ -502,7 +533,7 @@ check_install() {
ARGO_TYPE=is_quicktunnel_argo ARGO_TYPE=is_quicktunnel_argo
fi fi
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 的状态 # 检测 sing-box 的状态
@@ -571,17 +602,17 @@ EOF
check_system_info() { check_system_info() {
# 判断虚拟化 # 判断虚拟化
if [ $(type -p systemd-detect-virt) ]; then if [ -x "$(type -p systemd-detect-virt)" ]; then
VIRT=$(systemd-detect-virt) VIRT=$(systemd-detect-virt)
elif [ $(type -p hostnamectl) ]; then elif [ -x "$(type -p hostnamectl)" ]; then
VIRT=$(hostnamectl | awk '/Virtualization/{print $NF}') VIRT=$(hostnamectl | awk '/Virtualization/{print $NF}')
elif [ $(type -p virt-what) ]; then elif [ -x "$(type -p virt-what)" ]; then
VIRT=$(virt-what) VIRT=$(virt-what)
fi fi
[ -s /etc/os-release ] && SYS="$(awk -F '"' 'tolower($0) ~ /pretty_name/{print $2}' /etc/os-release)" [ -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" && -x "$(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 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/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/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')" [[ -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=("") EXCLUDE=("")
MAJOR=("9" "16" "7" "3" "" "37") 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_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") 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 for int in "${!REGEX[@]}"; do
@@ -600,7 +631,7 @@ check_system_info() {
# 针对各厂商的订制系统 # 针对各厂商的订制系统
if [ -z "$SYSTEM" ]; then 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 fi
# 先排除 EXCLUDE 里包括的特定系统,其他系统需要作大发行版本的比较 # 先排除 EXCLUDE 里包括的特定系统,其他系统需要作大发行版本的比较
@@ -648,7 +679,8 @@ add_port_hopping_nat() {
rc-service iptables save >/dev/null 2>&1 rc-service iptables save >/dev/null 2>&1
rc-service ip6tables 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 if [ "$(firewall-cmd --query-masquerade --permanent)" != 'yes' ] ; then
firewall-cmd --add-masquerade --permanent >/dev/null 2>&1 firewall-cmd --add-masquerade --permanent >/dev/null 2>&1
firewall-cmd --reload >/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 firewall-cmd --reload >/dev/null 2>&1
else else
if ! [ -x "$(type -p netfilter-persistent)" ]; then if [ ! -x "$(type -p netfilter-persistent)" ]; then
info "\n $(text 7) iptables-persistent" info "\n $(text 7) iptables-persistent"
${PACKAGE_INSTALL[int]} iptables-persistent >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} iptables-persistent >/dev/null 2>&1
fi fi
@@ -679,36 +711,39 @@ add_port_hopping_nat() {
check_port_hopping_nat() { check_port_hopping_nat() {
PORT_HOPPING_TARGET=$(awk -F [:,] '/"listen_port"/{print $2}' $WORK_DIR/conf/*${NODE_TAG[1]}_inbounds.json) PORT_HOPPING_TARGET=$(awk -F [:,] '/"listen_port"/{print $2}' $WORK_DIR/conf/*${NODE_TAG[1]}_inbounds.json)
if [ "$SYSTEM" = 'Alpine' ]; then 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<NF; i++) if ($i=="--dport") {print $(i+1); exit}}') && PORT_HOPPING_TARGET=$(iptables --table nat -S PREROUTING 2>/dev/null | awk '/Sing-box Family Bucket/ {for (i=0; i<NF; i++) if ($i=="to") {print $(i+1); exit}}') local IPTABLES_PREROUTING_LIST=$(iptables --table nat --list-rules PREROUTING 2>/dev/null | grep 'Sing-box Family Bucket')
[ -n "$IPTABLES_PREROUTING_LIST" ] && PORT_HOPPING_RANGE=$(awk '{for (i=0; i<NF; i++) if ($i=="--dport") {print $(i+1); exit}}' <<< "$IPTABLES_PREROUTING_LIST") && PORT_HOPPING_TARGET=$(awk '{for (i=0; i<NF; i++) if ($i=="to") {print $(i+1); exit}}' <<< "$IPTABLES_PREROUTING_LIST")
[ -n "$PORT_HOPPING_RANGE" ] && PORT_HOPPING_START=${PORT_HOPPING_RANGE%:*} && PORT_HOPPING_END=${PORT_HOPPING_RANGE#*:} [ -n "$PORT_HOPPING_RANGE" ] && PORT_HOPPING_START=${PORT_HOPPING_RANGE%:*} && PORT_HOPPING_END=${PORT_HOPPING_RANGE#*:}
elif [ "$(systemctl is-active firewalld)" = 'active' ]; then elif [ "$(systemctl is-active firewalld)" = 'active' ]; then
local FIREWALL_LIST=$(firewall-cmd --list-all --permanent | grep "toport=${PORT_HOPPING_TARGET}") local FIREWALL_LIST=$(firewall-cmd --list-all --permanent | grep "toport=${PORT_HOPPING_TARGET}")
[ -n "$FIREWALL_LIST" ] && PORT_HOPPING_START=$(sed "s/.* port=\([^-]\+\)-.*/\1/" <<< "$FIREWALL_LIST") && [ -n "$FIREWALL_LIST" ] && PORT_HOPPING_START=$(sed "s/.*port=\([^-]\+\)-.*toport.*/\1/" <<< "$FIREWALL_LIST") &&
PORT_HOPPING_END=$(sed "s/.* port=$PORT_HOPPING_START-\([^:]\+\):.*/\1/" <<< "$FIREWALL_LIST") && PORT_HOPPING_END=$(sed "s/.*port=$PORT_HOPPING_START-\([^:]\+\):.*toport.*/\1/" <<< "$FIREWALL_LIST") &&
PORT_HOPPING_TARGET=$(sed "s/.*toport=\([^:]\+\):.*/\1/" <<< "$FIREWALL_LIST") PORT_HOPPING_TARGET=$(sed "s/.*toport=\([^:]\+\):.*/\1/" <<< "$FIREWALL_LIST")
else else
[[ $(iptables --list --table nat) =~ 'Sing-box Family Bucket' ]] && PORT_HOPPING_RANGE=$(iptables --table nat -S PREROUTING | awk '/Sing-box Family Bucket/ {for (i=0; i<NF; i++) if ($i=="--dport") {print $(i+1); exit}}') && PORT_HOPPING_TARGET=$(iptables --table nat -S PREROUTING | awk '/Sing-box Family Bucket/ {for (i=0; i<NF; i++) if ($i=="to") {print $(i+1); exit}}') local IPTABLES_PREROUTING_LIST=$(iptables --table nat --list-rules PREROUTING 2>/dev/null | grep 'Sing-box Family Bucket')
[ -n "$IPTABLES_PREROUTING_LIST" ] && PORT_HOPPING_RANGE=$(awk '{for (i=0; i<NF; i++) if ($i=="--dport") {print $(i+1); exit}}' <<< "$IPTABLES_PREROUTING_LIST") && PORT_HOPPING_TARGET=$(awk '{for (i=0; i<NF; i++) if ($i=="to") {print $(i+1); exit}}' <<< "$IPTABLES_PREROUTING_LIST")
[ -n "$PORT_HOPPING_RANGE" ] && PORT_HOPPING_START=${PORT_HOPPING_RANGE%:*} && PORT_HOPPING_END=${PORT_HOPPING_RANGE#*:} [ -n "$PORT_HOPPING_RANGE" ] && PORT_HOPPING_START=${PORT_HOPPING_RANGE%:*} && PORT_HOPPING_END=${PORT_HOPPING_RANGE#*:}
fi fi
} }
# 检测 IPv4 IPv6 信息 # 检测 IPv4 IPv6 信息
check_system_ip() { check_system_ip() {
local DEFAULT_LOCAL_INTERFACE=$(ip route show default | awk '/default/ {for (i=0; i<NF; i++) if ($i=="dev") {print $(i+1); exit}}') local DEFAULT_LOCAL_INTERFACE4=$(ip -4 route show default | awk '/default/ {for (i=0; i<NF; i++) if ($i=="dev") {print $(i+1); exit}}')
local DEFAULT_LOCAL_INTERFACE6=$(ip -6 route show default | awk '/default/ {for (i=0; i<NF; i++) if ($i=="dev") {print $(i+1); exit}}')
if [ -n "$DEFAULT_LOCAL_INTERFACE" ]; then if [ -n "$DEFAULT_LOCAL_INTERFACE" ]; then
local DEFAULT_LOCAL_IP4=$(ip addr show $DEFAULT_LOCAL_INTERFACE | sed -n 's#.*inet \([^/]\+\)/[0-9]\+.*global.*#\1#gp') local DEFAULT_LOCAL_IP4=$(ip -4 addr show $DEFAULT_LOCAL_INTERFACE | sed -n 's#.*inet \([^/]\+\)/[0-9]\+.*global.*#\1#gp')
local DEFAULT_LOCAL_IP6=$(ip addr show $DEFAULT_LOCAL_INTERFACE | sed -n 's#.*inet6 \([^/]\+\)/[0-9]\+.*global.*#\1#gp') local DEFAULT_LOCAL_IP6=$(ip -6 addr show $DEFAULT_LOCAL_INTERFACE | sed -n 's#.*inet6 \([^/]\+\)/[0-9]\+.*global.*#\1#gp')
[ -n "$DEFAULT_LOCAL_IP4" ] && local BIND_ADDRESS4="--bind-address=$DEFAULT_LOCAL_IP4" [ -n "$DEFAULT_LOCAL_IP4" ] && local BIND_ADDRESS4="--bind-address=$DEFAULT_LOCAL_IP4"
[ -n "$DEFAULT_LOCAL_IP6" ] && local BIND_ADDRESS6="--bind-address=$DEFAULT_LOCAL_IP6" [ -n "$DEFAULT_LOCAL_IP6" ] && local BIND_ADDRESS6="--bind-address=$DEFAULT_LOCAL_IP6"
fi fi
IP4=$(wget -4 $BIND_ADDRESS4 -qO- $BIND_ADDRESS4 --no-check-certificate --user-agent=Mozilla --tries=2 --timeout=1 http://ip-api.com/json/) && IP4=$(wget -4 $BIND_ADDRESS4 -qO- --no-check-certificate --user-agent=Mozilla --tries=2 --timeout=1 http://ip-api.com/json/) &&
WAN4=$(expr "$IP4" : '.*query\":[ ]*\"\([^"]*\).*') && WAN4=$(expr "$IP4" : '.*query\":[ ]*\"\([^"]*\).*') &&
COUNTRY4=$(expr "$IP4" : '.*country\":[ ]*\"\([^"]*\).*') && COUNTRY4=$(expr "$IP4" : '.*country\":[ ]*\"\([^"]*\).*') &&
ASNORG4=$(expr "$IP4" : '.*isp\":[ ]*\"\([^"]*\).*') && ASNORG4=$(expr "$IP4" : '.*isp\":[ ]*\"\([^"]*\).*') &&
[[ "$L" = C && -n "$COUNTRY4" ]] && COUNTRY4=$(translate "$COUNTRY4") [[ "$L" = C && -n "$COUNTRY4" ]] && COUNTRY4=$(translate "$COUNTRY4")
IP6=$(wget -6 $BIND_ADDRESS6 -qO- $BIND_ADDRESS6 --no-check-certificate --user-agent=Mozilla --tries=2 --timeout=1 https://api.ip.sb/geoip) && IP6=$(wget -6 $BIND_ADDRESS6 -qO- --no-check-certificate --user-agent=Mozilla --tries=2 --timeout=1 https://api.ip.sb/geoip) &&
WAN6=$(expr "$IP6" : '.*ip\":[ ]*\"\([^"]*\).*') && WAN6=$(expr "$IP6" : '.*ip\":[ ]*\"\([^"]*\).*') &&
COUNTRY6=$(expr "$IP6" : '.*country\":[ ]*\"\([^"]*\).*') && COUNTRY6=$(expr "$IP6" : '.*country\":[ ]*\"\([^"]*\).*') &&
ASNORG6=$(expr "$IP6" : '.*isp\":[ ]*\"\([^"]*\).*') && ASNORG6=$(expr "$IP6" : '.*isp\":[ ]*\"\([^"]*\).*') &&
@@ -846,7 +881,7 @@ sing-box_variables() {
# 输入节点名,以系统的 hostname 作为默认 # 输入节点名,以系统的 hostname 作为默认
if [ -z "$NODE_NAME_CONFIRM" ]; then if [ -z "$NODE_NAME_CONFIRM" ]; then
if [ $(type -p hostname) ]; then if [ -x "$(type -p hostname)" ]; then
NODE_NAME_DEFAULT="$(hostname)" NODE_NAME_DEFAULT="$(hostname)"
elif [ -s /etc/hostname ]; then elif [ -s /etc/hostname ]; then
NODE_NAME_DEFAULT="$(cat /etc/hostname)" NODE_NAME_DEFAULT="$(cat /etc/hostname)"
@@ -863,34 +898,41 @@ check_dependencies() {
if [ "$SYSTEM" = 'Alpine' ]; then if [ "$SYSTEM" = 'Alpine' ]; then
local CHECK_WGET=$(wget 2>&1 | head -n 1) local CHECK_WGET=$(wget 2>&1 | head -n 1)
grep -qi 'busybox' <<< "$CHECK_WGET" && ${PACKAGE_INSTALL[int]} wget >/dev/null 2>&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_CHECK=("bash" "rc-update" "virt-what" "python3" "iptables" "ip6tables")
local DEPS_INSTALL=("bash" "openrc" "virt-what" "python3") local DEPS_INSTALL=("bash" "openrc" "virt-what" "python3" "iptables" "ip6tables")
for g in "${!DEPS_CHECK[@]}"; do 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 done
if [ "${#DEPS_ALPINE[@]}" -ge 1 ]; then if [ "${#DEPS_ALPINE[@]}" -ge 1 ]; then
info "\n $(text 7) $(sed "s/ /,&/g" <<< ${DEPS_ALPINE[@]}) \n" info "\n $(text 7) $(sed "s/ /,&/g" <<< ${DEPS_ALPINE[@]}) \n"
${PACKAGE_UPDATE[int]} >/dev/null 2>&1 ${PACKAGE_UPDATE[int]} >/dev/null 2>&1
${PACKAGE_INSTALL[int]} ${DEPS_ALPINE[@]} >/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 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 fi
# 检测 Linux 系统的依赖,升级库并重新安装依赖 # 检测 Linux 系统的依赖,升级库并重新安装依赖
local DEPS_CHECK=("wget" "tar" "systemctl" "ss" "bash" "openssl" "iptables" "ip6tables") local DEPS_CHECK=("wget" "tar" "systemctl" "ss" "bash" "openssl")
local DEPS_INSTALL=("wget" "tar" "systemctl" "iproute2" "bash" "openssl" "iptables" "ip6tables") local DEPS_INSTALL=("wget" "tar" "systemctl" "iproute2" "bash" "openssl")
for g in "${!DEPS_CHECK[@]}"; do 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 done
if [ "${#DEPS[@]}" -ge 1 ]; then
info "\n $(text 7) $(sed "s/ /,&/g" <<< ${DEPS[@]}) \n"
if [ "$IS_CENTOS" = 'CentOS7' ]; then if [ "$IS_CENTOS" = 'CentOS7' ]; then
yum repolist | grep -q epef || ${PACKAGE_INSTALL[int]} epel-release >/dev/null 2>&1 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 else
${PACKAGE_UPDATE[int]} >/dev/null 2>&1 [ ! -x "$(type -p iptables)" ] && DEPS+=(iptables)
[ ! -x "$(type -p ip6tables)" ] && DEPS+=(ip6tables)
fi fi
# 如需要安装的依赖大于0,就更新库并安装
if [[ "${#DEPS[@]}" > 0 ]]; then
[[ ! "$SYSTEM" =~ Alpine|CentOS ]] && ${PACKAGE_UPDATE[int]} >/dev/null 2>&1
${PACKAGE_INSTALL[int]} ${DEPS[@]} >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} ${DEPS[@]} >/dev/null 2>&1
else else
info "\n $(text 8) \n" info "\n $(text 8) \n"
@@ -899,7 +941,7 @@ check_dependencies() {
# 检查并安装 nginx # 检查并安装 nginx
check_nginx() { check_nginx() {
if [ ! $(type -p nginx) ]; then if [ ! -x "$(type -p nginx)" ]; then
info "\n $(text 7) nginx \n" info "\n $(text 7) nginx \n"
${PACKAGE_UPDATE[int]} >/dev/null 2>&1 ${PACKAGE_UPDATE[int]} >/dev/null 2>&1
${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1
@@ -932,7 +974,7 @@ ssl_certificate() {
# 处理防火墙规则 # 处理防火墙规则
check_firewall_configuration() { 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) " hint "\n $(text 84) "
setenforce 0 setenforce 0
sed -i 's/^SELINUX=.*/# &/; /SELINUX=/a\SELINUX=disabled' /etc/selinux/config sed -i 's/^SELINUX=.*/# &/; /SELINUX=/a\SELINUX=disabled' /etc/selinux/config
@@ -942,7 +984,7 @@ check_firewall_configuration() {
# Nginx 配置文件 # Nginx 配置文件
export_nginx_conf_file() { export_nginx_conf_file() {
# 在添加协议,需要用到 nginx 的时候,先检测是否已经安装 # 在添加协议,需要用到 nginx 的时候,先检测是否已经安装
if ! [ -x "$(type -p nginx)" ]; then if [ ! -x "$(type -p nginx)" ]; then
info "\n $(text 7) nginx" info "\n $(text 7) nginx"
${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1 ${PACKAGE_INSTALL[int]} nginx >/dev/null 2>&1
fi fi
@@ -1771,13 +1813,11 @@ fetch_nodes_value() {
# 获取 Argo 临时隧道域名 # 获取 Argo 临时隧道域名
fetch_quicktunnel_domain() { fetch_quicktunnel_domain() {
unset CLOUDFLARED_PID METRICS_ADDRESS ARGO_DOMAIN unset CLOUDFLARED_PID METRICS_ADDRESS ARGO_DOMAIN
local QUICKTUNNEL_ERROR_TIME=10 local QUICKTUNNEL_ERROR_TIME=20
until [ -n "$ARGO_DOMAIN" ]; do until [ -n "$ARGO_DOMAIN" ]; do
if [ -z "$CLOUDFLARED_PID" ]; then [ "$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}')
[ "$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
[[ -z "$METRICS_ADDRESS" && "$CLOUDFLARED_PID" =~ ^[0-9]+$ ]] && METRICS_ADDRESS=$(ss -nltp | grep "pid=$CLOUDFLARED_PID" | awk '{print $4}') [[ -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 [[ ! "$ARGO_DOMAIN" =~ trycloudflare\.com$ ]] && (( QUICKTUNNEL_ERROR_TIME-- )) && sleep 2 || break
[ "$QUICKTUNNEL_ERROR_TIME" = '0' ] && error " $(text 93) " [ "$QUICKTUNNEL_ERROR_TIME" = '0' ] && error " $(text 93) "
done done
@@ -1844,7 +1884,7 @@ export_list() {
[[ ! -s $WORK_DIR/jq && -s /usr/bin/jq ]] && cp /usr/bin/jq $WORK_DIR/ [[ ! -s $WORK_DIR/jq && -s /usr/bin/jq ]] && cp /usr/bin/jq $WORK_DIR/
if [ ! -s $WORK_DIR/qrencode ]; then if [ ! -s $WORK_DIR/qrencode ]; then
check_arch 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
fi fi
@@ -1970,7 +2010,7 @@ vless://$(echo -n "auto:${UUID[11]}@${SERVER_IP_2}:${PORT_XTLS_REALITY}" | base6
if [ -n "$PORT_HYSTERIA2" ]; then 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}" [[ -n "$PORT_HOPPING_START" && -n "$PORT_HOPPING_END" ]] && local SHADOWROCKET_HOPPING="&mport=${PORT_HYSTERIA2},${PORT_HOPPING_START}-${PORT_HOPPING_END}"
local SHADOWROCKET_SUBSCRIBE+=" 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 fi
@@ -2017,7 +2057,7 @@ vless://$(echo -n "auto:${UUID[18]}@${CDN[18]}:443" | base64 -w0)?remarks=${NODE
else else
WS_SERVER_IP_SHOW=${WS_SERVER_IP[18]} && TYPE_HOST_DOMAIN=$VLESS_HOST_DOMAIN && TYPE_PORT_WS=$PORT_VLESS_WS && local SHADOWROCKET_SUBSCRIBE+=" 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) # $(text 52)
" "
@@ -2568,6 +2608,9 @@ change_protocols() {
done done
done done
# 如有需要,删除 hysteria2 跳跃端口,待后面添加回来
[ "$IS_HOPPING" = 'is_hopping' ] && del_port_hopping_nat
# 删除不需要的协议配置文件 # 删除不需要的协议配置文件
[ "${#REMOVE_FILE[@]}" -gt 0 ] && for t in "${REMOVE_FILE[@]}"; do [ "${#REMOVE_FILE[@]}" -gt 0 ] && for t in "${REMOVE_FILE[@]}"; do
rm -f $WORK_DIR/conf/*${t} 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[*]}") 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]} PORT_GRPC_REALITY=${REINSTALL_PORTS[POSITION]}
else else
PORT_GRPC_REALITY unset PORT_GRPC_REALITY
fi fi
# 停止 sing-box 服务 # 停止 sing-box 服务
@@ -2763,9 +2806,6 @@ change_protocols() {
[ -s $WORK_DIR/tunnel.json ] && rm -f $WORK_DIR/tunnel.* [ -s $WORK_DIR/tunnel.json ] && rm -f $WORK_DIR/tunnel.*
fi fi
# 如有需要,删除 hysteria2 跳跃端口
! ls $WORK_DIR/conf/*${NODE_TAG[1]}_inbounds.json >/dev/null 2>&1 && del_port_hopping_nat
# 如有需要,删除 nginx 配置文件 # 如有需要,删除 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 ! 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 的最新版本 # Sing-box 的最新版本
version() { 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 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- "https://api.github.com/repos/SagerNet/sing-box/releases" | awk -F '["v]' -v var="tag_name.*$VERSION_LATEST" '$0 ~ var {print $5; exit}') 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}') local LOCAL=$($WORK_DIR/sing-box version | awk '/version/{print $NF}')
info "\n $(text 40) " info "\n $(text 40) "
[[ -n "$ONLINE" && "$ONLINE" != "$LOCAL" ]] && reading "\n $(text 9) " UPDATE || info " $(text 41) " [[ -n "$ONLINE" && "$ONLINE" != "$LOCAL" ]] && reading "\n $(text 9) " UPDATE || info " $(text 41) "
@@ -2848,7 +2888,7 @@ menu_setting() {
fi fi
# 查 Nginx 版本号 # 查 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}') [ "$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" [[ "$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[4]() { change_argo; exit; }
ACTION[5]() { change_start_port; exit; } ACTION[5]() { change_start_port; exit; }
ACTION[6]() { version; 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[8]() { change_protocols; exit; }
ACTION[9]() { uninstall; 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[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- https://raw.githubusercontent.com/fscarmen/sba/main/sba.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; } ACTION[12]() { bash <(wget --no-check-certificate -qO- https://tcp.hy2.sh/); exit; }
else else
OPTION[1]="1. $(text 34) + Argo + $(text 80) $(text 89)" 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[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[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[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[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- https://raw.githubusercontent.com/fscarmen/argox/main/argox.sh) -$L; 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- https://raw.githubusercontent.com/fscarmen/sba/main/sba.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- https://tcp.hy2.sh/); exit; } ACTION[8]() { bash <(wget --no-check-certificate -qO- ${GH_PROXY}https://tcp.hy2.sh/); exit; }
fi fi
[ "${#OPTION[@]}" -ge '10' ] && OPTION[0]="0 . $(text 35)" || OPTION[0]="0. $(text 35)" [ "${#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 check_arch; version; exit 0
;; ;;
-B ) -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 ) -R )
change_protocols; exit 0 change_protocols; exit 0