├── README.md ├── socks5_awt.sh ├── argo_socks5.sh └── sb_00.sh /README.md: -------------------------------------------------------------------------------- 1 | # shell-scripts 2 | test purpose (个人测试用) 3 | 4 | 虽然是个人测试,有的还是得说一下 5 | sb_00.sh是为了解决s14的YouTube播放卡59秒问题,这个脚本是魔改老王的,所以有事不要找他。 6 | 7 | 由于是魔改,所以现在很多地方不一样了,包括变量。 8 | 9 | 比起老王的版本,这个你只需要面板里开启一个TCP端口和一个UDP端口,给你节省一个端口,你可以留着干别的去用。 10 | 11 | 脚本去掉了哪吒,换成了Beszel的监控客户端,所以多了一个BESZEL_KEY的变量,但是注意这个变量的值并不是Beszel面板里直接复制的那串,而是去掉了前面ssh-ed25519只需要后面的部分,如果你要用,要注意。 12 | 13 | 还有一个需要注意的是,这个脚本在开始运行的时候会对当前serv00服务器的三个入口做连通性检测,必须起码有两个IP连通性检测结果是(通),这个脚本才会运行正常,不过我的serv00都是有两个入口国内是通的,所以我就没有在脚本里写不满足条件时候的判断(懒)。 14 | 15 | 魔改版本去掉了vmess改成了vless,所以脚本运行后提供的所有协议为 socks5|vless-ws-tls(argo)|hysteria2|tuic 16 | 17 | 如需保活,我推荐外部VPS保活,脚本可以去用老王的保活脚本就行。 18 | 19 | 这个魔改脚本所有的变量是`TCP_PORT` `UDP_PORT` 可选变量: `UUID` `BESZEL_KEY` `SOCKSU` `SOCKSP` `ARGO_DOMAIN` `ARGO_AUTH` `CFIP` `CFPORT` 20 | 21 | ``` 22 | TCP_PORT=TCP端口号 UDP_PORT=UDP端口号 bash <(curl -Ls https://github.com/Neomanbeta/shell-scripts/raw/refs/heads/main/sb_00.sh) 23 | ``` 24 | -------------------------------------------------------------------------------- /socks5_awt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | re="\033[0m" 4 | red="\033[1;91m" 5 | green="\e[1;32m" 6 | yellow="\e[1;33m" 7 | purple="\e[1;35m" 8 | red() { echo -e "\e[1;91m$1\033[0m"; } 9 | green() { echo -e "\e[1;32m$1\033[0m"; } 10 | yellow() { echo -e "\e[1;33m$1\033[0m"; } 11 | purple() { echo -e "\e[1;35m$1\033[0m"; } 12 | reading() { read -p "$(red "$1")" "$2"; } 13 | export LC_ALL=C 14 | USERNAME=$(whoami) 15 | HOSTNAME=$(hostname) 16 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b9'} 17 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} 18 | export ARGO_AUTH=${ARGO_AUTH:-''} 19 | export TUIC_PORT=${TUIC_PORT:-'50000'} 20 | export SOCKSU=${SOCKSU:-'oneforall'} 21 | export SOCKSP=${SOCKSP:-'allforone'} 22 | export STCP=${STCP:-'0000'} 23 | export WTCP=${WTCP:-'0000'} 24 | 25 | [[ "$HOSTNAME" == "s1.ct8.pl" ]] && WORKDIR="domains/${USERNAME}.ct8.pl/logs" || WORKDIR="domains/${USERNAME}.serv00.net/logs" 26 | [ -d "$WORKDIR" ] || (mkdir -p "$WORKDIR" && chmod 777 "$WORKDIR") 27 | ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk '{print $2}' | xargs -r kill -9 2>/dev/null 28 | 29 | argo_configure() { 30 | clear 31 | purple "正在安装中,请稍等..." 32 | if [[ $ARGO_AUTH =~ TunnelSecret ]]; then 33 | echo $ARGO_AUTH > tunnel.json 34 | cat > tunnel.yml << EOF 35 | tunnel: $(cut -d\" -f12 <<< "$ARGO_AUTH") 36 | credentials-file: tunnel.json 37 | protocol: http2 38 | 39 | ingress: 40 | - hostname: $ARGO_DOMAIN 41 | service: http://localhost:$WTCP 42 | originRequest: 43 | noTLSVerify: true 44 | - service: http_status:404 45 | EOF 46 | else 47 | green "ARGO_AUTH mismatch TunnelSecret,use token connect to tunnel" 48 | fi 49 | } 50 | 51 | generate_config() { 52 | 53 | openssl ecparam -genkey -name prime256v1 -out "private.key" 54 | openssl req -new -x509 -days 3650 -key "private.key" -out "cert.pem" -subj "/CN=$USERNAME.serv00.net" 55 | 56 | cat > config.json << EOF 57 | { 58 | "log": { 59 | "disabled": true, 60 | "level": "info", 61 | "timestamp": true 62 | }, 63 | "dns": { 64 | "servers": [ 65 | { 66 | "tag": "google", 67 | "address": "tls://8.8.8.8", 68 | "strategy": "ipv4_only", 69 | "detour": "direct" 70 | } 71 | ], 72 | "rules": [ 73 | { 74 | "rule_set": [ 75 | "geosite-openai" 76 | ], 77 | "server": "wireguard" 78 | }, 79 | { 80 | "rule_set": [ 81 | "geosite-netflix" 82 | ], 83 | "server": "wireguard" 84 | }, 85 | { 86 | "rule_set": [ 87 | "geosite-category-ads-all" 88 | ], 89 | "server": "block" 90 | } 91 | ], 92 | "final": "google", 93 | "strategy": "", 94 | "disable_cache": false, 95 | "disable_expire": false 96 | }, 97 | "inbounds": [ 98 | { 99 | "tag": "socks-in", 100 | "type": "socks", 101 | "listen": "::", 102 | "listen_port": $STCP, 103 | "users": [ 104 | { 105 | "username": "$SOCKSU", 106 | "password": "$SOCKSP" 107 | } 108 | ] 109 | }, 110 | { 111 | "tag": "tuic-in", 112 | "type": "tuic", 113 | "listen": "::", 114 | "listen_port": $TUIC_PORT, 115 | "users": [ 116 | { 117 | "uuid": "$UUID", 118 | "password": "admin123" 119 | } 120 | ], 121 | "congestion_control": "bbr", 122 | "tls": { 123 | "enabled": true, 124 | "alpn": [ 125 | "h3" 126 | ], 127 | "certificate_path": "cert.pem", 128 | "key_path": "private.key" 129 | } 130 | } 131 | 132 | ], 133 | "outbounds": [ 134 | { 135 | "type": "direct", 136 | "tag": "direct" 137 | }, 138 | { 139 | "type": "block", 140 | "tag": "block" 141 | }, 142 | { 143 | "type": "dns", 144 | "tag": "dns-out" 145 | }, 146 | { 147 | "type": "wireguard", 148 | "tag": "wireguard-out", 149 | "server": "162.159.195.100", 150 | "server_port": 4500, 151 | "local_address": [ 152 | "172.16.0.2/32", 153 | "2606:4700:110:83c7:b31f:5858:b3a8:c6b1/128" 154 | ], 155 | "private_key": "mPZo+V9qlrMGCZ7+E6z2NI6NOV34PD++TpAR09PtCWI=", 156 | "peer_public_key": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=", 157 | "reserved": [ 158 | 26, 159 | 21, 160 | 228 161 | ] 162 | } 163 | ], 164 | "route": { 165 | "rules": [ 166 | { 167 | "protocol": "dns", 168 | "outbound": "dns-out" 169 | }, 170 | { 171 | "ip_is_private": true, 172 | "outbound": "direct" 173 | }, 174 | { 175 | "rule_set": [ 176 | "geosite-openai" 177 | ], 178 | "outbound": "wireguard-out" 179 | }, 180 | { 181 | "rule_set": [ 182 | "geosite-netflix" 183 | ], 184 | "outbound": "wireguard-out" 185 | }, 186 | { 187 | "rule_set": [ 188 | "geosite-category-ads-all" 189 | ], 190 | "outbound": "block" 191 | } 192 | ], 193 | "rule_set": [ 194 | { 195 | "tag": "geosite-netflix", 196 | "type": "remote", 197 | "format": "binary", 198 | "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-netflix.srs", 199 | "download_detour": "direct" 200 | }, 201 | { 202 | "tag": "geosite-openai", 203 | "type": "remote", 204 | "format": "binary", 205 | "url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/openai.srs", 206 | "download_detour": "direct" 207 | }, 208 | { 209 | "tag": "geosite-category-ads-all", 210 | "type": "remote", 211 | "format": "binary", 212 | "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-category-ads-all.srs", 213 | "download_detour": "direct" 214 | } 215 | ], 216 | "final": "direct" 217 | }, 218 | "experimental": { 219 | "cache_file": { 220 | "path": "cache.db", 221 | "cache_id": "mycacheid", 222 | "store_fakeip": true 223 | } 224 | } 225 | } 226 | EOF 227 | } 228 | 229 | download_singbox() { 230 | ARCH=$(uname -m) && DOWNLOAD_DIR="." && mkdir -p "$DOWNLOAD_DIR" && FILE_INFO=() 231 | if [ "$ARCH" == "arm" ] || [ "$ARCH" == "arm64" ] || [ "$ARCH" == "aarch64" ]; then 232 | FILE_INFO=("https://github.com/eooce/test/releases/download/arm64/sb web" "https://github.com/eooce/test/releases/download/arm64/bot13 bot" "https://github.com/eooce/test/releases/download/ARM/swith npm") 233 | elif [ "$ARCH" == "amd64" ] || [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "x86" ]; then 234 | FILE_INFO=("https://github.com/eooce/test/releases/download/freebsd/sb web" "https://github.com/eooce/test/releases/download/freebsd/server bot" "https://github.com/vi/websocat/releases/download/v1.13.0/websocat.x86_64-unknown-freebsd cat") 235 | else 236 | echo "Unsupported architecture: $ARCH" 237 | exit 1 238 | fi 239 | declare -A FILE_MAP 240 | generate_random_name() { 241 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 242 | local name="" 243 | for i in {1..6}; do 244 | name="$name${chars:RANDOM%${#chars}:1}" 245 | done 246 | echo "$name" 247 | } 248 | 249 | download_with_fallback() { 250 | local URL=$1 251 | local NEW_FILENAME=$2 252 | 253 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" & 254 | CURL_PID=$! 255 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 256 | 257 | sleep 1 258 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 259 | 260 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then 261 | kill $CURL_PID 2>/dev/null 262 | wait $CURL_PID 2>/dev/null 263 | wget -q -O "$NEW_FILENAME" "$URL" 264 | echo -e "\e[1;32mDownloading $NEW_FILENAME by wget\e[0m" 265 | else 266 | wait $CURL_PID 267 | echo -e "\e[1;32mDownloading $NEW_FILENAME by curl\e[0m" 268 | fi 269 | } 270 | 271 | for entry in "${FILE_INFO[@]}"; do 272 | URL=$(echo "$entry" | cut -d ' ' -f 1) 273 | RANDOM_NAME=$(generate_random_name) 274 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME" 275 | 276 | if [ -e "$NEW_FILENAME" ]; then 277 | echo -e "\e[1;32m$NEW_FILENAME already exists, Skipping download\e[0m" 278 | else 279 | download_with_fallback "$URL" "$NEW_FILENAME" 280 | fi 281 | 282 | chmod +x "$NEW_FILENAME" 283 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME" 284 | done 285 | wait 286 | 287 | if [ -e "$(basename ${FILE_MAP[cat]})" ]; then 288 | nohup ./"$(basename ${FILE_MAP[cat]})" -E -b ws-l:127.0.0.1:$WTCP tcp:127.0.0.1:$STCP >/dev/null 2>&1 & 289 | sleep 2 290 | pgrep -x "$(basename ${FILE_MAP[cat]})" > /dev/null && green "$(basename ${FILE_MAP[cat]}) is running" || { red "$(basename ${FILE_MAP[cat]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[cat]})" && nohup ./"$(basename ${FILE_MAP[cat]})" -E -b ws-l:127.0.0.1:$WTCP tcp:127.0.0.1:$STCP >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[cat]}) restarted"; } 291 | fi 292 | 293 | if [ -e "$(basename ${FILE_MAP[web]})" ]; then 294 | nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & 295 | sleep 2 296 | pgrep -x "$(basename ${FILE_MAP[web]})" > /dev/null && green "$(basename ${FILE_MAP[web]}) is running" || { red "$(basename ${FILE_MAP[web]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[web]})" && nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[web]}) restarted"; } 297 | fi 298 | 299 | if [ -e "$(basename ${FILE_MAP[bot]})" ]; then 300 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then 301 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}" 302 | elif [[ $ARGO_AUTH =~ TunnelSecret ]]; then 303 | args="tunnel --edge-ip-version auto --config tunnel.yml run" 304 | else 305 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$VMESS_PORT" 306 | fi 307 | nohup ./"$(basename ${FILE_MAP[bot]})" $args >/dev/null 2>&1 & 308 | sleep 2 309 | pgrep -x "$(basename ${FILE_MAP[bot]})" > /dev/null && green "$(basename ${FILE_MAP[bot]}) is running" || { red "$(basename ${FILE_MAP[bot]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[bot]})" && nohup ./"$(basename ${FILE_MAP[bot]})" "${args}" >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[bot]}) restarted"; } 310 | fi 311 | sleep 5 312 | rm -f "$(basename ${FILE_MAP[cat]})" "$(basename ${FILE_MAP[web]})" "$(basename ${FILE_MAP[bot]})" 313 | } 314 | 315 | get_argodomain() { 316 | if [[ -n $ARGO_AUTH ]]; then 317 | echo "$ARGO_DOMAIN" 318 | else 319 | grep -oE 'https://[[:alnum:]+\.-]+\.trycloudflare\.com' boot.log | sed 's@https://@@' 320 | fi 321 | } 322 | 323 | get_ip() { 324 | ip=$(curl -s --max-time 2 ipv4.ip.sb) 325 | if [ -z "$ip" ]; then 326 | ip=$( [[ "$HOSTNAME" =~ s[0-9]\.serv00\.com ]] && echo "${HOSTNAME/s/web}" || echo "$HOSTNAME" ) 327 | else 328 | url="https://www.toolsdaquan.com/toolapi/public/ipchecking/$ip/443" 329 | response=$(curl -s --location --max-time 3.5 --request GET "$url" --header 'Referer: https://www.toolsdaquan.com/ipcheck') 330 | if [ -z "$response" ] || ! echo "$response" | grep -q '"icmp":"success"'; then 331 | accessible=false 332 | else 333 | accessible=true 334 | fi 335 | if [ "$accessible" = false ]; then 336 | ip=$( [[ "$HOSTNAME" =~ s[0-9]\.serv00\.com ]] && echo "${HOSTNAME/s/web}" || echo "$ip" ) 337 | fi 338 | fi 339 | echo "$ip" 340 | } 341 | 342 | get_links(){ 343 | argodomain=$(get_argodomain) 344 | echo -e "\e[1;32mArgoDomain:\e[1;35m${argodomain}\e[0m\n" 345 | sleep 1 346 | IP=$(get_ip) 347 | ISP=$(curl -s https://speed.cloudflare.com/meta | awk -F\" '{print $26"-"$18}' | sed -e 's/ /_/g') 348 | sleep 1 349 | yellow "注意:v2ray或其他软件的跳过证书验证需设置为true,tuic节点可能不通\n" 350 | cat > list.txt </dev/null 32 | 33 | argo_configure() { 34 | clear 35 | purple "正在安装中,请稍等..." 36 | if [[ -z $ARGO_AUTH || -z $ARGO_DOMAIN ]]; then 37 | green "ARGO_DOMAIN or ARGO_AUTH is empty,use quick tunnel" 38 | return 39 | fi 40 | 41 | if [[ $ARGO_AUTH =~ TunnelSecret ]]; then 42 | echo $ARGO_AUTH > tunnel.json 43 | cat > tunnel.yml << EOF 44 | tunnel: $(cut -d\" -f12 <<< "$ARGO_AUTH") 45 | credentials-file: tunnel.json 46 | protocol: http2 47 | 48 | ingress: 49 | - hostname: $ARGO_DOMAIN 50 | service: http://localhost:$VMESS_PORT 51 | originRequest: 52 | noTLSVerify: true 53 | - service: http_status:404 54 | EOF 55 | else 56 | green "ARGO_AUTH mismatch TunnelSecret,use token connect to tunnel" 57 | fi 58 | } 59 | 60 | generate_config() { 61 | 62 | cat > config.json << EOF 63 | { 64 | "log": { 65 | "disabled": true, 66 | "level": "info", 67 | "timestamp": true 68 | }, 69 | "dns": { 70 | "servers": [ 71 | { 72 | "tag": "google", 73 | "address": "tls://8.8.8.8", 74 | "strategy": "ipv4_only", 75 | "detour": "direct" 76 | } 77 | ], 78 | "rules": [ 79 | { 80 | "rule_set": [ 81 | "geosite-openai" 82 | ], 83 | "server": "wireguard" 84 | }, 85 | { 86 | "rule_set": [ 87 | "geosite-netflix" 88 | ], 89 | "server": "wireguard" 90 | }, 91 | { 92 | "rule_set": [ 93 | "geosite-category-ads-all" 94 | ], 95 | "server": "block" 96 | } 97 | ], 98 | "final": "google", 99 | "strategy": "", 100 | "disable_cache": false, 101 | "disable_expire": false 102 | }, 103 | "inbounds": [ 104 | { 105 | "tag": "vmess-ws-in", 106 | "type": "vmess", 107 | "listen": "::", 108 | "listen_port": $VMESS_PORT, 109 | "users": [ 110 | { 111 | "uuid": "$UUID" 112 | } 113 | ], 114 | "transport": { 115 | "type": "ws", 116 | "path": "/vmess", 117 | "early_data_header_name": "Sec-WebSocket-Protocol" 118 | } 119 | }, 120 | { 121 | "tag": "socks-in", 122 | "type": "socks", 123 | "listen": "::", 124 | "listen_port": $SOCKS_PORT, 125 | "users": [ 126 | { 127 | "username": "$SOCKSU", 128 | "password": "$SOCKSP" 129 | } 130 | ] 131 | } 132 | 133 | ], 134 | "outbounds": [ 135 | { 136 | "type": "direct", 137 | "tag": "direct" 138 | }, 139 | { 140 | "type": "block", 141 | "tag": "block" 142 | }, 143 | { 144 | "type": "dns", 145 | "tag": "dns-out" 146 | }, 147 | { 148 | "type": "wireguard", 149 | "tag": "wireguard-out", 150 | "server": "162.159.195.100", 151 | "server_port": 4500, 152 | "local_address": [ 153 | "172.16.0.2/32", 154 | "2606:4700:110:83c7:b31f:5858:b3a8:c6b1/128" 155 | ], 156 | "private_key": "mPZo+V9qlrMGCZ7+E6z2NI6NOV34PD++TpAR09PtCWI=", 157 | "peer_public_key": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=", 158 | "reserved": [ 159 | 26, 160 | 21, 161 | 228 162 | ] 163 | } 164 | ], 165 | "route": { 166 | "rules": [ 167 | { 168 | "protocol": "dns", 169 | "outbound": "dns-out" 170 | }, 171 | { 172 | "ip_is_private": true, 173 | "outbound": "direct" 174 | }, 175 | { 176 | "rule_set": [ 177 | "geosite-openai" 178 | ], 179 | "outbound": "wireguard-out" 180 | }, 181 | { 182 | "rule_set": [ 183 | "geosite-netflix" 184 | ], 185 | "outbound": "wireguard-out" 186 | }, 187 | { 188 | "rule_set": [ 189 | "geosite-category-ads-all" 190 | ], 191 | "outbound": "block" 192 | } 193 | ], 194 | "rule_set": [ 195 | { 196 | "tag": "geosite-netflix", 197 | "type": "remote", 198 | "format": "binary", 199 | "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-netflix.srs", 200 | "download_detour": "direct" 201 | }, 202 | { 203 | "tag": "geosite-openai", 204 | "type": "remote", 205 | "format": "binary", 206 | "url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/openai.srs", 207 | "download_detour": "direct" 208 | }, 209 | { 210 | "tag": "geosite-category-ads-all", 211 | "type": "remote", 212 | "format": "binary", 213 | "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-category-ads-all.srs", 214 | "download_detour": "direct" 215 | } 216 | ], 217 | "final": "direct" 218 | }, 219 | "experimental": { 220 | "cache_file": { 221 | "path": "cache.db", 222 | "cache_id": "mycacheid", 223 | "store_fakeip": true 224 | } 225 | } 226 | } 227 | EOF 228 | } 229 | 230 | download_singbox() { 231 | ARCH=$(uname -m) && DOWNLOAD_DIR="." && mkdir -p "$DOWNLOAD_DIR" && FILE_INFO=() 232 | if [ "$ARCH" == "arm" ] || [ "$ARCH" == "arm64" ] || [ "$ARCH" == "aarch64" ]; then 233 | FILE_INFO=("https://github.com/eooce/test/releases/download/arm64/sb web" "https://github.com/eooce/test/releases/download/arm64/bot13 bot" "https://github.com/eooce/test/releases/download/ARM/swith npm") 234 | elif [ "$ARCH" == "amd64" ] || [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "x86" ]; then 235 | FILE_INFO=("https://github.com/eooce/test/releases/download/freebsd/sb web" "https://github.com/eooce/test/releases/download/freebsd/server bot" "https://github.com/eooce/test/releases/download/freebsd/npm npm") 236 | else 237 | echo "Unsupported architecture: $ARCH" 238 | exit 1 239 | fi 240 | declare -A FILE_MAP 241 | generate_random_name() { 242 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 243 | local name="" 244 | for i in {1..6}; do 245 | name="$name${chars:RANDOM%${#chars}:1}" 246 | done 247 | echo "$name" 248 | } 249 | 250 | download_with_fallback() { 251 | local URL=$1 252 | local NEW_FILENAME=$2 253 | 254 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" & 255 | CURL_PID=$! 256 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 257 | 258 | sleep 1 259 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 260 | 261 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then 262 | kill $CURL_PID 2>/dev/null 263 | wait $CURL_PID 2>/dev/null 264 | wget -q -O "$NEW_FILENAME" "$URL" 265 | echo -e "\e[1;32mDownloading $NEW_FILENAME by wget\e[0m" 266 | else 267 | wait $CURL_PID 268 | echo -e "\e[1;32mDownloading $NEW_FILENAME by curl\e[0m" 269 | fi 270 | } 271 | 272 | for entry in "${FILE_INFO[@]}"; do 273 | URL=$(echo "$entry" | cut -d ' ' -f 1) 274 | RANDOM_NAME=$(generate_random_name) 275 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME" 276 | 277 | if [ -e "$NEW_FILENAME" ]; then 278 | echo -e "\e[1;32m$NEW_FILENAME already exists, Skipping download\e[0m" 279 | else 280 | download_with_fallback "$URL" "$NEW_FILENAME" 281 | fi 282 | 283 | chmod +x "$NEW_FILENAME" 284 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME" 285 | done 286 | wait 287 | 288 | if [ -e "$(basename ${FILE_MAP[npm]})" ]; then 289 | tlsPorts=("443" "8443" "2096" "2087" "2083" "2053") 290 | if [[ "${tlsPorts[*]}" =~ "${NEZHA_PORT}" ]]; then 291 | NEZHA_TLS="--tls" 292 | else 293 | NEZHA_TLS="" 294 | fi 295 | if [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_PORT" ] && [ -n "$NEZHA_KEY" ]; then 296 | export TMPDIR=$(pwd) 297 | nohup ./"$(basename ${FILE_MAP[npm]})" -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} >/dev/null 2>&1 & 298 | sleep 2 299 | pgrep -x "$(basename ${FILE_MAP[npm]})" > /dev/null && green "$(basename ${FILE_MAP[npm]}) is running" || { red "$(basename ${FILE_MAP[npm]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[npm]})" && nohup ./"$(basename ${FILE_MAP[npm]})" -s "${NEZHA_SERVER}:${NEZHA_PORT}" -p "${NEZHA_KEY}" ${NEZHA_TLS} >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[npm]}) restarted"; } 300 | else 301 | purple "NEZHA variable is empty, skipping running" 302 | fi 303 | fi 304 | 305 | if [ -e "$(basename ${FILE_MAP[web]})" ]; then 306 | nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & 307 | sleep 2 308 | pgrep -x "$(basename ${FILE_MAP[web]})" > /dev/null && green "$(basename ${FILE_MAP[web]}) is running" || { red "$(basename ${FILE_MAP[web]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[web]})" && nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[web]}) restarted"; } 309 | fi 310 | 311 | if [ -e "$(basename ${FILE_MAP[bot]})" ]; then 312 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then 313 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}" 314 | elif [[ $ARGO_AUTH =~ TunnelSecret ]]; then 315 | args="tunnel --edge-ip-version auto --config tunnel.yml run" 316 | else 317 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$VMESS_PORT" 318 | fi 319 | nohup ./"$(basename ${FILE_MAP[bot]})" $args >/dev/null 2>&1 & 320 | sleep 2 321 | pgrep -x "$(basename ${FILE_MAP[bot]})" > /dev/null && green "$(basename ${FILE_MAP[bot]}) is running" || { red "$(basename ${FILE_MAP[bot]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[bot]})" && nohup ./"$(basename ${FILE_MAP[bot]})" "${args}" >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[bot]}) restarted"; } 322 | fi 323 | sleep 5 324 | rm -f "$(basename ${FILE_MAP[npm]})" "$(basename ${FILE_MAP[web]})" "$(basename ${FILE_MAP[bot]})" 325 | } 326 | 327 | get_argodomain() { 328 | if [[ -n $ARGO_AUTH ]]; then 329 | echo "$ARGO_DOMAIN" 330 | else 331 | grep -oE 'https://[[:alnum:]+\.-]+\.trycloudflare\.com' boot.log | sed 's@https://@@' 332 | fi 333 | } 334 | 335 | get_ip() { 336 | ip=$(curl -s --max-time 2 ipv4.ip.sb) 337 | if [ -z "$ip" ]; then 338 | ip=$( [[ "$HOSTNAME" =~ s[0-9]\.serv00\.com ]] && echo "${HOSTNAME/s/web}" || echo "$HOSTNAME" ) 339 | else 340 | url="https://www.toolsdaquan.com/toolapi/public/ipchecking/$ip/443" 341 | response=$(curl -s --location --max-time 3.5 --request GET "$url" --header 'Referer: https://www.toolsdaquan.com/ipcheck') 342 | if [ -z "$response" ] || ! echo "$response" | grep -q '"icmp":"success"'; then 343 | accessible=false 344 | else 345 | accessible=true 346 | fi 347 | if [ "$accessible" = false ]; then 348 | ip=$( [[ "$HOSTNAME" =~ s[0-9]\.serv00\.com ]] && echo "${HOSTNAME/s/web}" || echo "$ip" ) 349 | fi 350 | fi 351 | echo "$ip" 352 | } 353 | 354 | get_links(){ 355 | argodomain=$(get_argodomain) 356 | echo -e "\e[1;32mArgoDomain:\e[1;35m${argodomain}\e[0m\n" 357 | sleep 1 358 | IP=$(get_ip) 359 | ISP=$(curl -s https://speed.cloudflare.com/meta | awk -F\" '{print $26"-"$18}' | sed -e 's/ /_/g') 360 | sleep 1 361 | yellow "注意:这是魔改老王的版本\n" 362 | cat > list.txt </dev/null 2>&1' >/dev/null 2>&1 30 | # devil binexec on > /dev/null 2>&1 31 | 32 | argo_configure() { 33 | clear 34 | purple "正在安装中,请稍等..." 35 | if [[ -z $ARGO_AUTH || -z $ARGO_DOMAIN ]]; then 36 | green "ARGO_DOMAIN or ARGO_AUTH is empty,use quick tunnel" 37 | return 38 | fi 39 | 40 | if [[ $ARGO_AUTH =~ TunnelSecret ]]; then 41 | echo $ARGO_AUTH > tunnel.json 42 | cat > tunnel.yml << EOF 43 | tunnel: $(cut -d\" -f12 <<< "$ARGO_AUTH") 44 | credentials-file: tunnel.json 45 | protocol: http2 46 | 47 | ingress: 48 | - hostname: $ARGO_DOMAIN 49 | service: http://localhost:$TCP_PORT 50 | originRequest: 51 | noTLSVerify: true 52 | - service: http_status:404 53 | EOF 54 | else 55 | green "ARGO_AUTH mismatch TunnelSecret,use token connect to tunnel" 56 | fi 57 | } 58 | 59 | generate_config() { 60 | # 生成证书和私钥 61 | openssl ecparam -genkey -name prime256v1 -out "private.key" 62 | openssl req -new -x509 -days 3650 -key "private.key" -out "cert.pem" -subj "/CN=$USERNAME.serv00.net" 63 | 64 | yellow "正在进行连通性测试,请稍等..." 65 | get_ip 66 | 67 | cat > config.json << EOF 68 | { 69 | "log": { 70 | "disabled": true, 71 | "level": "info", 72 | "timestamp": true 73 | }, 74 | "dns": { 75 | "servers": [ 76 | { 77 | "address": "8.8.8.8", 78 | "address_resolver": "local" 79 | }, 80 | { 81 | "tag": "local", 82 | "address": "local" 83 | } 84 | ] 85 | }, 86 | "inbounds": [ 87 | { 88 | "tag": "hysteria-in", 89 | "type": "hysteria2", 90 | "listen": "$IP3", 91 | "listen_port": $UDP_PORT, 92 | "users": [ 93 | { 94 | "password": "$UUID" 95 | } 96 | ], 97 | "masquerade": "https://bing.com", 98 | "tls": { 99 | "enabled": true, 100 | "alpn": [ 101 | "h3" 102 | ], 103 | "certificate_path": "cert.pem", 104 | "key_path": "private.key" 105 | } 106 | }, 107 | { 108 | "tag": "vless-ws-in", 109 | "type": "vless", 110 | "listen": "127.0.0.1", 111 | "listen_port": $TCP_PORT, 112 | "users": [ 113 | { 114 | "uuid": "$UUID" 115 | } 116 | ], 117 | "transport": { 118 | "type": "ws", 119 | "path": "/vless-argo", 120 | "early_data_header_name": "Sec-WebSocket-Protocol" 121 | } 122 | }, 123 | { 124 | "tag": "socks-in", 125 | "type": "socks", 126 | "listen": "$IP2", 127 | "listen_port": $TCP_PORT, 128 | "users": [ 129 | { 130 | "username": "$SOCKSU", 131 | "password": "$SOCKSP" 132 | } 133 | ] 134 | }, 135 | { 136 | "tag": "tuic-in", 137 | "type": "tuic", 138 | "listen": "$IP4", 139 | "listen_port": $UDP_PORT, 140 | "users": [ 141 | { 142 | "uuid": "$UUID", 143 | "password": "admin123" 144 | } 145 | ], 146 | "congestion_control": "bbr", 147 | "tls": { 148 | "enabled": true, 149 | "alpn": [ 150 | "h3" 151 | ], 152 | "certificate_path": "cert.pem", 153 | "key_path": "private.key" 154 | } 155 | } 156 | ], 157 | "outbounds": [ 158 | { 159 | "type": "wireguard", 160 | "tag": "wireguard-out", 161 | "server": "engage.cloudflareclient.com", 162 | "server_port": 2408, 163 | "local_address": [ 164 | "172.16.0.2/32", 165 | "2606:4700:110:812a:4929:7d2a:af62:351c/128" 166 | ], 167 | "private_key": "gBthRjevHDGyV0KvYwYE52NIPy29sSrVr6rcQtYNcXA=", 168 | "peer_public_key": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=", 169 | "reserved": [ 170 | 6, 171 | 146, 172 | 6 173 | ] 174 | }, 175 | { 176 | "tag": "direct", 177 | "type": "direct" 178 | }, 179 | { 180 | "tag": "block", 181 | "type": "block" 182 | } 183 | ], 184 | "route": { 185 | "rules": [ 186 | { 187 | "domain": [ 188 | "jnn-pa.googleapis.com" 189 | ], 190 | "outbound": "wireguard-out" 191 | } 192 | ], 193 | "final": "direct" 194 | } 195 | } 196 | EOF 197 | } 198 | 199 | download_singbox() { 200 | DOWNLOAD_DIR="." && mkdir -p "$DOWNLOAD_DIR" && FILE_INFO=() 201 | FILE_INFO=("https://github.com/eooce/test/releases/download/freebsd/sb web" \ 202 | "https://github.com/eooce/test/releases/download/freebsd/server bot" \ 203 | "https://github.com/henrygd/beszel/releases/latest/download/beszel-agent_freebsd_amd64.tar.gz npm") 204 | 205 | declare -A FILE_MAP 206 | 207 | generate_random_name() { 208 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 209 | local name="" 210 | for i in {1..6}; do 211 | name="$name${chars:RANDOM%${#chars}:1}" 212 | done 213 | echo "$name" 214 | } 215 | 216 | download_with_fallback() { 217 | local URL=$1 218 | local NEW_FILENAME=$2 219 | 220 | curl -L -sS --max-time 3 -o "$NEW_FILENAME" "$URL" & 221 | CURL_PID=$! 222 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 223 | 224 | sleep 1 225 | 226 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 227 | 228 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then 229 | kill $CURL_PID 2>/dev/null 230 | wait $CURL_PID 2>/dev/null 231 | wget -q -O "$NEW_FILENAME" "$URL" 232 | echo -e "\e[1;32mDownloading $NEW_FILENAME by wget\e[0m" 233 | else 234 | wait $CURL_PID 235 | echo -e "\e[1;32mDownloading $NEW_FILENAME by curl\e[0m" 236 | fi 237 | } 238 | 239 | for entry in "${FILE_INFO[@]}"; do 240 | URL=$(echo "$entry" | cut -d ' ' -f 1) 241 | LOGIC_NAME=$(echo "$entry" | cut -d ' ' -f 2) 242 | RANDOM_NAME=$(generate_random_name) 243 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME" 244 | 245 | if [ -e "$NEW_FILENAME" ]; then 246 | echo -e "\e[1;32m$NEW_FILENAME already exists, Skipping download\e[0m" 247 | else 248 | download_with_fallback "$URL" "$NEW_FILENAME" 249 | fi 250 | 251 | if [[ "$URL" == *.tar.gz ]]; then 252 | tar -xzf "$NEW_FILENAME" -C "$DOWNLOAD_DIR" 253 | rm -f "$NEW_FILENAME" 254 | 255 | EXTRACTED_FILE="$DOWNLOAD_DIR/beszel-agent" 256 | if [ ! -f "$EXTRACTED_FILE" ]; then 257 | echo -e "\e[1;31mError: Expected file 'beszel-agent' not found in archive\e[0m" 258 | continue 259 | fi 260 | 261 | mv "$EXTRACTED_FILE" "$NEW_FILENAME" 262 | fi 263 | 264 | chmod +x "$NEW_FILENAME" 265 | FILE_MAP[$LOGIC_NAME]="$NEW_FILENAME" 266 | done 267 | wait 268 | 269 | if [ -e "$(basename ${FILE_MAP[npm]})" ]; then 270 | if [ -n "$TCP_PORT" ] && [ -n "$BESZEL_KEY" ]; then 271 | nohup env PORT=$IP1:$TCP_PORT KEY="ssh-ed25519 $BESZEL_KEY" ./"$(basename ${FILE_MAP[npm]})" > /dev/null 2>&1 & 272 | sleep 2 273 | pgrep -x "$(basename ${FILE_MAP[npm]})" > /dev/null && green "$(basename ${FILE_MAP[npm]}) is running" || { red "$(basename ${FILE_MAP[npm]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[npm]})" && nohup env PORT=$IP1:$TCP_PORT KEY="ssh-ed25519 $BESZEL_KEY" ./"$(basename ${FILE_MAP[npm]})" > /dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[npm]}) restarted"; } 274 | else 275 | purple "BESZEL variable is empty, skipping running" 276 | fi 277 | fi 278 | 279 | if [ -e "$(basename ${FILE_MAP[web]})" ]; then 280 | nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & 281 | sleep 2 282 | pgrep -x "$(basename ${FILE_MAP[web]})" > /dev/null && green "$(basename ${FILE_MAP[web]}) is running" || { red "$(basename ${FILE_MAP[web]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[web]})" && nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[web]}) restarted"; } 283 | fi 284 | 285 | if [ -e "$(basename ${FILE_MAP[bot]})" ]; then 286 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then 287 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}" 288 | elif [[ $ARGO_AUTH =~ TunnelSecret ]]; then 289 | args="tunnel --edge-ip-version auto --config tunnel.yml run" 290 | else 291 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$TCP_PORT" 292 | fi 293 | nohup ./"$(basename ${FILE_MAP[bot]})" $args >/dev/null 2>&1 & 294 | sleep 2 295 | pgrep -x "$(basename ${FILE_MAP[bot]})" > /dev/null && green "$(basename ${FILE_MAP[bot]}) is running" || { red "$(basename ${FILE_MAP[bot]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[bot]})" && nohup ./"$(basename ${FILE_MAP[bot]})" "${args}" >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[bot]}) restarted"; } 296 | fi 297 | sleep 2 298 | rm -f "$(basename ${FILE_MAP[npm]})" "$(basename ${FILE_MAP[web]})" "$(basename ${FILE_MAP[bot]})" 299 | } 300 | 301 | get_argodomain() { 302 | if [[ -n $ARGO_AUTH ]]; then 303 | echo "$ARGO_DOMAIN" 304 | else 305 | local retry=0 306 | local max_retries=6 307 | local argodomain="" 308 | while [[ $retry -lt $max_retries ]]; do 309 | ((retry++)) 310 | argodomain=$(grep -oE 'https://[[:alnum:]+\.-]+\.trycloudflare\.com' boot.log | sed 's@https://@@') 311 | if [[ -n $argodomain ]]; then 312 | break 313 | fi 314 | sleep 1 315 | done 316 | echo "$argodomain" 317 | fi 318 | } 319 | 320 | get_ip() { 321 | API_URL="https://status.eooce.com/api" 322 | IP_LIST=($(devil vhost list | awk '/^[0-9]+/ {print $1}')) 323 | AVAILABLE_IPS="" 324 | RESPONSIVE_IPS=() 325 | IP1="" 326 | IP2="" 327 | IP3="" 328 | IP4="" 329 | 330 | MAX_RETRIES=2 331 | for IP in "${IP_LIST[@]}"; do 332 | SUCCESS=false 333 | for ((i = 1; i <= MAX_RETRIES; i++)); do 334 | RESPONSE=$(curl -s "$API_URL/$IP") 335 | STATUS=$(echo "$RESPONSE" | jq -r '.status') 336 | if [[ "$STATUS" == "Available" ]]; then 337 | SUCCESS=true 338 | break 339 | elif [[ "$STATUS" == "Blocked" ]]; then 340 | break 341 | fi 342 | done 343 | 344 | if $SUCCESS; then 345 | RESPONSIVE_IPS+=($IP) 346 | AVAILABLE_IPS+=" $IP(通)" 347 | else 348 | AVAILABLE_IPS+=" $IP(不通)" 349 | fi 350 | done 351 | 352 | IP1=${IP_LIST[0]:-""} 353 | IP2=${IP_LIST[1]:-""} 354 | 355 | UNRESPONSIVE_IPS=() 356 | for ip in "${IP_LIST[@]}"; do 357 | if [[ ! " ${RESPONSIVE_IPS[@]} " =~ " $ip " ]]; then 358 | UNRESPONSIVE_IPS+=("$ip") 359 | fi 360 | done 361 | 362 | if [ ${#RESPONSIVE_IPS[@]} -eq 0 ]; then 363 | IP3=$IP1 364 | IP4=$IP2 365 | elif [ ${#RESPONSIVE_IPS[@]} -ge 1 ]; then 366 | IP3=${RESPONSIVE_IPS[0]} 367 | if [ ${#RESPONSIVE_IPS[@]} -ge 2 ]; then 368 | IP4=${RESPONSIVE_IPS[1]} 369 | else 370 | IP4=${UNRESPONSIVE_IPS[0]:-""} 371 | fi 372 | fi 373 | 374 | purple "$AVAILABLE_IPS" 375 | } 376 | 377 | 378 | get_links(){ 379 | argodomain=$(get_argodomain) 380 | echo -e "\e[1;32mArgoDomain:\e[1;35m${argodomain}\e[0m\n" 381 | ISP=$(curl -s --max-time 1.5 https://speed.cloudflare.com/meta | awk -F\" '{print $26}' | sed -e 's/ /_/g' || echo "0") 382 | get_name() { if [ "$HOSTNAME" = "s1.ct8.pl" ]; then SERVER="CT8"; else SERVER=$(echo "$HOSTNAME" | cut -d '.' -f 1); fi; echo "$SERVER"; } 383 | NAME="$ISP-$(get_name)" 384 | 385 | yellow "注意:v2ray或其他软件的跳过证书验证需设置为true,否则hy2或tuic节点可能不通\n" 386 | purple "Beszel探针的IP是$IP1端口是$TCP_PORT\n" 387 | cat > list.txt <