├── LICENSE ├── README.md ├── go ├── go.mod ├── main.go └── start.sh ├── java ├── server.jar └── start.sh ├── keep.sh ├── keep_00.sh ├── nodejs ├── index.js ├── package.json └── start.sh ├── python ├── app.py └── start.sh ├── sb4.sh ├── sb_00.sh ├── sb_serv00.sh └── sing-box.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 eooce 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 1:vps一键命令,已集成到ssh工具箱中 2 | * 一键四协议安装脚本,支持纯v6 VPS,支持订阅,默认解锁GPT和奈飞 3 | * 最好用的四协议组合vless-reality|vmess-ws-tls(argo)|hysteria2|tuic5 4 | * 支持的系统:Ubuntu/Debian/CentOS/Alpine/Fedora/Rocky/Almalinux/kail 5 | * 注意nat小鸡安装完一键脚本之后需手动更改订阅端口和节点端口在允许范围内的端口,否则节点不通 6 | * 可在脚本前添加PORT变量,随脚本一起运行,即可定义端口,需确保PORT端口后面的3个端口可用,否则节点不通 7 | * 可选环境变量PORT CFIP CFPORT 8 | 9 | ## VPS一键四协议安装脚本 10 | ``` 11 | bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sing-box.sh) 12 | ``` 13 | ## vps带端口变量运行示列 14 | PORT=开放的端口 确保后面3个端口可用 CFIP为优选IP或优选域名,CFPORT为优选ip或优选域名对应的端口 15 | ``` 16 | PORT=你的端口 CFIP=www.visa.com.tw CFPORT=443 bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sing-box.sh) 17 | ``` 18 | 19 | 20 | ## ssh综合工具箱一键脚本 21 | ``` 22 | curl -fsSL https://raw.githubusercontent.com/eooce/ssh_tool/main/ssh_tool.sh -o ssh_tool.sh && chmod +x ssh_tool.sh && ./ssh_tool.sh 23 | ``` 24 | 25 | # 2:Serv00|CT8一键安装脚本,集成哪吒探针,全自动安装 26 | * 一键四协议安装脚本,vmess-ws|vmess-ws-tls(argo)|hy2|tuic5默认解锁GPT和奈飞 27 | * 支持自定义哪吒参数、Argo等参数随脚本一起运行 28 | * 列如:UUID=123456 ARGO_DOMAIN=2go.admin.com ARGO_AUTH=abc123 UPLOAD_URL=https://merge.serv00.net 29 | * v0哪吒变量形式:NEZHA_SERVER=nezha.abc.com v1哪吒变量形式:NEZHA_SERVER=nezha.abc.com:8008,v1不需要NEZHA_PORT变量 30 | * 需要订阅自动上传到汇聚订阅器,需先部署Merge-sub项目,部署时填写UPLOAD_URL环境变量为部署的首页地址,例如:UPLOAD_URL=https://merge.serv00.net 31 | * 客户端跳过证书验证需设置为true,否则hy2和tuic不通 32 | 33 | ## Serv00|CT8一键四协议安装脚本vmess-ws|vmess-ws-tls(argo)|hy2|tuic5 34 | * 交互式4合1中加入全自动保活服务,只安装1没有保活,安装1和2或者直接安装2 35 | ``` 36 | bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sb_serv00.sh) 37 | ``` 38 | 39 | ## Serv00|CT8一键四协议无交互安装脚本vmess-ws|vmess-ws-tls(argo)|hy2|tuic5,全自动安装节点+全自动保活 40 | * 默认不安装哪吒和TG提醒,如需要,在脚本前添加环境变量随脚本一起运行即可 41 | * 可选环境变量:CHAT_ID BOT_TOKEN UUID NEZHA_SERVER NEZHA_PORT NEZHA_KEY ARGO_DOMAIN ARGO_AUTH CFIP CFPORT SUB_TOKEN 42 | * v0哪吒变量形式:NEZHA_SERVER=nezha.abc.com v1哪吒变量形式:NEZHA_SERVER=nezha.abc.com:8008,v1不需要NEZHA_PORT变量 43 | * 需要订阅自动上传到汇聚订阅器,需先部署Merge-sub项目,部署时填写UPLOAD_URL环境变量为部署的首页地址,例如:UPLOAD_URL=https://merge.serv00.net 44 | * ARGO_AUTH变量使用json时,ARGO_AUTH=‘json’ 需用英文输入状态下的单引号包裹,例如:ARGO_AUTH='{"AccountTag":"123","TunnelSecret":"123","TunnelID":"123"}' 45 | ``` 46 | bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sb4.sh) 47 | ``` 48 | 49 | * 带TG提醒、哪吒v1、argo固定隧道运行示列,里面的参数替换为自己的,不需要的变量直接删除,固定隧道密钥可以为token或json 50 | ``` 51 | CHAT_ID=12345 BOT_TOKEN=5678:AA812jqIA NEZHA_SERVER=nezha.abc.com:8008 NEZHA_KEY=abc123 ARGO_DOMAIN=abc.2go.com ARGO_AUTH='{"AccountTag":"123","TunnelSecret":"123","TunnelID":"123"}' bash <(curl -Ls https://github.com/eooce/Sing-box/releases/download/00/sb4.sh) 52 | ``` 53 | 54 | 55 | ## Serv00|CT8一键三协议安装脚本vless-reality|hy2|tuic5 56 | ``` 57 | bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/test/sb_00.sh) 58 | ``` 59 | 60 | ## Serv00|CT8 hysteria2无交互一键安装脚本 61 | * 复制脚本回车全自动安装节点+全自动保活 62 | * 默认不安装哪吒和TG提醒,如需要,在脚本前添加环境变量随脚本一起运行即可,v1不需要NEZHA_PORT变量 63 | * v0哪吒变量形式:NEZHA_SERVER=nezha.abc.com v1哪吒变量形式:NEZHA_SERVER=nezha.abc.com:8008 64 | * 可选变量:CHAT_ID BOT_TOKEN UUID NEZHA_SERVER NEZHA_PORT NEZHA_KEY SUB_TOKEN 65 | ``` 66 | bash <(curl -Ls https://github.com/eooce/Sing-box/releases/download/00/2.sh) 67 | ``` 68 | 69 | ## Serv00|CT8 tuic无交互一键安装脚本 70 | * 复制脚本回车全自动安装节点+全自动保活 71 | * 默认不安装哪吒和TG提醒,如需要,在脚本前添加环境变量随脚本一起运行即可,v1不需要NEZHA_PORT变量 72 | * v0哪吒变量形式:NEZHA_SERVER=nezha.abc.com v1哪吒变量形式:NEZHA_SERVER=nezha.abc.com:8008 73 | * 可选变量:CHAT_ID BOT_TOKEN UUID NEZHA_SERVER NEZHA_PORT NEZHA_KEY SUB_TOKEN 74 | 75 | ``` 76 | bash <(curl -Ls https://github.com/eooce/Sing-box/releases/download/00/tu.sh) 77 | ``` 78 | 79 | ## Serv00|CT8 vmess-ws-tls(argo)一键脚本 80 | * 复制脚本回车全自动安装节点+全自动保活 81 | * 默认不安装哪吒和TG提醒,如需要,在脚本前添加环境变量随脚本一起运行即可,v1不需要NEZHA_PORT变量 82 | * v0哪吒变量形式:NEZHA_SERVER=nezha.abc.com v1哪吒变量形式:NEZHA_SERVER=nezha.abc.com:8008 83 | * 可选变量:CHAT_ID BOT_TOKEN UUID ARGO_DOMAIN ARGO_AUTH NEZHA_SERVER NEZHA_PORT NEZHA_KEY CFIP CFPORT SUB_TOKEN 84 | 85 | ``` 86 | bash <(curl -Ls https://github.com/eooce/Sing-box/releases/download/00/00_vm.sh) 87 | ``` 88 | 89 | 90 | 91 | 92 | # 3:游戏机hosting 93 | ## sing-box玩具四合一,默认解锁GPT和奈飞 94 | * node,python,java,go环境的游戏玩具搭建singbox节点,集成哪吒探针服务 95 | * 玩具默认vmess-argo ,支持多端口的玩具可自行添加端口变量同时开启4协议节点 96 | * 对应文件夹即对应环境请下载对应文件夹里的文件上传并赋予权限,修改变量后运行 97 | * ARGO_DOMAIN和ARGO_AUTH两个变量其中之一为空即启用临时隧道,反之则使用固定隧道 98 | * 无需设置NEZHA_TLS,当哪吒端口为{443,8443,2096,2087,2083,2053}其中之一时,自动开启tls 99 | 100 | ## 游戏机hosting可选变量 101 | | 变量名 | 是否必须 | 默认值 | 备注 | 102 | | ------------ | ------ | ------ | ------ | 103 | | PORT | 否 | 3000 |http订阅端口,对应的主运行文件中修改,列如:index.js,app.py中 | 104 | | ARGO_PORT | 否 | 8001 |argo隧道端口,固定隧道token需和cloudflare后台设置的一致 | 105 | | UUID | 否 | bc97f674-c578-4940-9234-0a1da46041b9|节点UUID和哪吒v1的UUID | 106 | | NEZHA_SERVER | 否 | | 哪吒服务端域名,v0:nz.aaa.com v1: nz.aaa.com:8008 | 107 | | NEZHA_PORT | 否 | 5555 | 哪吒端口为{443,8443,2096,2087,2083,2053}其中之一时,开启tls| 108 | | NEZHA_KEY | 否 | | 哪吒客户端KEY 或v1的NZ_CLIENT_SECRET | 109 | | ARGO_DOMAIN | 否 | | argo固定隧道域名,留空即启用临时隧道 | 110 | | ARGO_AUTH | 否 | | argo固定隧道json或token,留空即启用临时隧道 | 111 | | CFIP | 否 |skk.moe | 节点优选域名或ip | 112 | | CFPORT | 否 | 8443 |节点端口 | 113 | | HY2_PORT | 否 | | hy2端口,支持多端口的玩具可以填写,不填写该节点不通 | 114 | | REALITY_PORT | 否 | | vless-reality端口,支持多端口的玩具可以填写,不填写该节点不通 | 115 | | TUIC_PORT | 否 | | tuic-v5端口,支持多端口的玩具可以填写,不填写该节点不通 | 116 | 117 | ## 游戏机hostong节点输出 118 | * 输出sub.txt节点文件,可直接导入V2ray,nekbox,小火箭等代理软中 119 | * 订阅:默认不开启,多端口玩具可开启:分配的域名:http端口/sub,前缀不是https,而是http,例如http://www.google.com:1234/sub 120 | 121 | ## ⚠️ 免责声明 122 | * 本程序仅供学习了解, 非盈利目的,请于下载后 24 小时内删除, 不得用作任何商业用途, 文字、数据及图片均有所属版权, 如转载须注明来源。 123 | * 使用本程序必循遵守部署免责声明,使用本程序必循遵守部署服务器所在地、所在国家和用户所在国家的法律法规, 程序作者不对使用者任何不当行为负责。 124 | 125 | ## 赞助 126 | * 感谢[YXVM](https://yxvm.com/aff.php?aff=764)提供赞助 127 | * [NodeSupport](https://github.com/NodeSeekDev/NodeSupport) 128 | 129 | ## ⭐ Star History 130 | 131 | 感谢所有为本项目点亮 Star 的朋友们!🌟 132 | 133 | [![Star History Chart](https://api.star-history.com/svg?repos=eooce/Sing-box&type=Date)](https://star-history.com/#eooce/Sing-box&Date) 134 | -------------------------------------------------------------------------------- /go/go.mod: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "os" 8 | "os/exec" 9 | ) 10 | 11 | const ( 12 | httpPort = 3000 13 | ) 14 | 15 | func main() { 16 | go startHTTPServer() 17 | 18 | shellCommand := "chmod +x start.sh && ./start.sh &" 19 | 20 | cmd := exec.Command("bash", "-c", shellCommand) 21 | 22 | cmd.Stdout = os.Stdout 23 | cmd.Stderr = os.Stderr 24 | 25 | err := cmd.Run() 26 | if err != nil { 27 | fmt.Printf("error: %v\n", err) 28 | } else { 29 | fmt.Printf("Server is running on port: %d\n", httpPort) 30 | } 31 | 32 | select {} 33 | } 34 | 35 | func startHTTPServer() { 36 | http.HandleFunc("/", rootHandler) 37 | http.HandleFunc("/sub", subHandler) 38 | err := http.ListenAndServe(fmt.Sprintf(":%d", httpPort), nil) 39 | if err != nil { 40 | fmt.Printf("HTTP server error: %v\n", err) 41 | } 42 | } 43 | 44 | func rootHandler(w http.ResponseWriter, r *http.Request) { 45 | fmt.Fprint(w, "Hello, World!") 46 | } 47 | 48 | func subHandler(w http.ResponseWriter, r *http.Request) { 49 | content, err := ioutil.ReadFile("./temp/sub.txt") 50 | if err != nil { 51 | http.Error(w, fmt.Sprintf("Error reading file: %v", err), http.StatusInternalServerError) 52 | return 53 | } 54 | 55 | w.Header().Set("Content-Type", "text/plain; charset=utf-8") 56 | 57 | w.Write(content) 58 | } 59 | -------------------------------------------------------------------------------- /go/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b9'} # 哪吒v1,在不同的平台部署需要改UUID,否则会覆盖 3 | export NEZHA_SERVER=${NEZHA_SERVER:-''} # v1哪吒填写形式:nezha.abc.com:8008,v0哪吒填写形式:nezha.abc.com 4 | export NEZHA_PORT=${NEZHA_PORT:-''} # v1哪吒不要填写这个,v0哪吒agent端口为{443,8443,2053,2083,2087,2096}其中之一时自动开启tls 5 | export NEZHA_KEY=${NEZHA_KEY:-''} # v1的NZ_CLIENT_SECRET或v0的agent密钥 6 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} # 固定隧道域名,留空即启用临时隧道 7 | export ARGO_AUTH=${ARGO_AUTH:-''} # 固定隧道token或json,留空即启用临时隧道 8 | export CFIP=${CFIP:-'www.visa.com.tw'} # argo节点优选域名或优选ip 9 | export CFPORT=${CFPORT:-'443'} # argo节点端口 10 | export NAME=${NAME:-'Vls'} # 节点名称 11 | export FILE_PATH=${FILE_PATH:-'./temp'} # sub 路径 12 | export ARGO_PORT=${ARGO_PORT:-'8001'} # argo端口 使用固定隧道token,cloudflare后台设置的端口需和这里对应 13 | export TUIC_PORT=${TUIC_PORT:-'40000'} # Tuic 端口,支持多端口玩具可填写,否则不动 14 | export HY2_PORT=${HY2_PORT:-'50000'} # Hy2 端口,支持多端口玩具可填写,否则不动 15 | export REALITY_PORT=${REALITY_PORT:-'60000'} # reality 端口,支持多端口玩具可填写,否则不动 16 | export CHAT_ID=${CHAT_ID:-''} # TG chat_id,可在https://t.me/laowang_serv00_bot 获取 17 | export BOT_TOKEN=${BOT_TOKEN:-''} # TG bot_token, 使用自己的bot需要填写,使用上方的bot不用填写,不会给别人发送 18 | export UPLOAD_URL=${UPLOAD_URL:-''} # 订阅自动上传地址,没有可不填,需要填部署Merge-sub项目后的首页地址,例如:https://merge.serv00.net 19 | 20 | echo "ZGVsZXRlX29sZF9ub2RlcygpIHsKICBbWyAteiAkVVBMT0FEX1VSTCB8fCAhIC1mICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgXV0gJiYgcmV0dXJuCiAgb2xkX25vZGVzPSQoYmFzZTY0IC1kICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgfCBncmVwIC1FICcodmxlc3N8dm1lc3N8dHJvamFufGh5c3RlcmlhMnx0dWljKTovLycpCiAgW1sgLXogJG9sZF9ub2RlcyBdXSAmJiByZXR1cm4KCiAganNvbl9kYXRhPSd7Im5vZGVzIjogWycKICBmb3Igbm9kZSBpbiAkb2xkX25vZGVzOyBkbwogICAgICBqc29uX2RhdGErPSJcIiRub2RlXCIsIgogIGRvbmUKICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0gIAogIGpzb25fZGF0YSs9J119JwoKICBjdXJsIC1YIERFTEVURSAiJFVQTE9BRF9VUkwvYXBpL2RlbGV0ZS1ub2RlcyIgXAogICAgICAgIC1IICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAgICAgICAtZCAiJGpzb25fZGF0YSIgPiAvZGV2L251bGwgMj4mMQp9CmRlbGV0ZV9vbGRfbm9kZXMKClsgISAtZCAiJHtGSUxFX1BBVEh9IiBdICYmIG1rZGlyIC1wICIke0ZJTEVfUEFUSH0iICYmIHJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiB0dW5uZWwuanNvbiB0dW5uZWwueW1sICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgPi9kZXYvbnVsbCAyPiYxCgoKYXJnb19jb25maWd1cmUoKSB7CiAgaWYgW1sgLXogJEFSR09fQVVUSCB8fCAteiAkQVJHT19ET01BSU4gXV07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzE7MzJtQVJHT19ET01BSU4gb3IgQVJHT19BVVRIIHZhcmlhYmxlIGlzIGVtcHR5LCB1c2UgcXVpY2sgdHVubmVsc1xlWzBtIiAgIAogICAgcmV0dXJuCiAgZmkKCiAgaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgIGVjaG8gJEFSR09fQVVUSCA+IHR1bm5lbC5qc29uCiAgICBjYXQgPiB0dW5uZWwueW1sIDw8IEVPRgp0dW5uZWw6ICQoY3V0IC1kXCIgLWYxMiA8PDwgIiRBUkdPX0FVVEgiKQpjcmVkZW50aWFscy1maWxlOiB0dW5uZWwuanNvbgpwcm90b2NvbDogaHR0cDIKCmluZ3Jlc3M6CiAgLSBob3N0bmFtZTogJEFSR09fRE9NQUlOCiAgICBzZXJ2aWNlOiBodHRwOi8vbG9jYWxob3N0OiRBUkdPX1BPUlQKICAgIG9yaWdpblJlcXVlc3Q6CiAgICAgIG5vVExTVmVyaWZ5OiB0cnVlCiAgLSBzZXJ2aWNlOiBodHRwX3N0YXR1czo0MDQKRU9GCiAgZWxzZQogICAgZWNobyAtZSAiXGVbMTszMm1BUkdPX0FVVEggbWlzbWF0Y2ggVHVubmVsU2VjcmV0LHVzZSB0b2tlbiBjb25uZWN0IHRvIHR1bm5lbFxlWzBtIgogIGZpCn0KYXJnb19jb25maWd1cmUKd2FpdAoKZG93bmxvYWRfYW5kX3J1bigpIHsKQVJDSD0kKHVuYW1lIC1tKSAmJiBET1dOTE9BRF9ESVI9Ii4iICYmIG1rZGlyIC1wICIkRE9XTkxPQURfRElSIiAmJiBGSUxFX0lORk89KCkKaWYgWyAiJEFSQ0giID09ICJhcm0iIF0gfHwgWyAiJEFSQ0giID09ICJhcm02NCIgXSB8fCBbICIkQVJDSCIgPT0gImFhcmNoNjQiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FybTY0LnNzc3MubnljLm1uIgplbGlmIFsgIiRBUkNIIiA9PSAiYW1kNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODZfNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODYiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FtZDY0LnNzc3MubnljLm1uIgplbHNlCiAgICBlY2hvICJVbnN1cHBvcnRlZCBhcmNoaXRlY3R1cmU6ICRBUkNIIgogICAgZXhpdCAxCmZpCkZJTEVfSU5GTz0oIiRCQVNFX1VSTC9zYiB3ZWIiICIkQkFTRV9VUkwvYm90IGJvdCIpCgppZiBbIC1uICIkTkVaSEFfUE9SVCIgXTsgdGhlbgogICAgRklMRV9JTkZPKz0oIiRCQVNFX1VSTC9hZ2VudCBucG0iKQplbHNlCiAgICBGSUxFX0lORk8rPSgiJEJBU0VfVVJML3YxIHBocCIpCiAgICBORVpIQV9UTFM9JChjYXNlICIke05FWkhBX1NFUlZFUiMjKjp9IiBpbiA0NDN8ODQ0M3wyMDk2fDIwODd8MjA4M3wyMDUzKSBlY2hvIC1uIHRydWU7OyAqKSBlY2hvIC1uIGZhbHNlOzsgZXNhYykKICAgIGNhdCA+ICIke0ZJTEVfUEFUSH0vY29uZmlnLnlhbWwiIDw8IEVPRgpjbGllbnRfc2VjcmV0OiAke05FWkhBX0tFWX0KZGVidWc6IGZhbHNlCmRpc2FibGVfYXV0b191cGRhdGU6IHRydWUKZGlzYWJsZV9jb21tYW5kX2V4ZWN1dGU6IGZhbHNlCmRpc2FibGVfZm9yY2VfdXBkYXRlOiB0cnVlCmRpc2FibGVfbmF0OiBmYWxzZQpkaXNhYmxlX3NlbmRfcXVlcnk6IGZhbHNlCmdwdTogZmFsc2UKaW5zZWN1cmVfdGxzOiBmYWxzZQppcF9yZXBvcnRfcGVyaW9kOiAxODAwCnJlcG9ydF9kZWxheTogMQpzZXJ2ZXI6ICR7TkVaSEFfU0VSVkVSfQpza2lwX2Nvbm5lY3Rpb25fY291bnQ6IGZhbHNlCnNraXBfcHJvY3NfY291bnQ6IGZhbHNlCnRlbXBlcmF0dXJlOiBmYWxzZQp0bHM6ICR7TkVaSEFfVExTfQp1c2VfZ2l0ZWVfdG9fdXBncmFkZTogZmFsc2UKdXNlX2lwdjZfY291bnRyeV9jb2RlOiBmYWxzZQp1dWlkOiAke1VVSUR9CkVPRgpmaQpkZWNsYXJlIC1BIEZJTEVfTUFQCmdlbmVyYXRlX3JhbmRvbV9uYW1lKCkgewogICAgbG9jYWwgY2hhcnM9YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwCiAgICBsb2NhbCBuYW1lPSIiCiAgICBmb3IgaSBpbiB7MS4uNn07IGRvCiAgICAgICAgbmFtZT0iJG5hbWUke2NoYXJzOlJBTkRPTSUkeyNjaGFyc306MX0iCiAgICBkb25lCiAgICBlY2hvICIkbmFtZSIKfQpkb3dubG9hZF9maWxlKCkgewogICAgbG9jYWwgVVJMPSQxCiAgICBsb2NhbCBORVdfRklMRU5BTUU9JDIKCiAgICBpZiBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICAgICAgY3VybCAtTCAtc1MgLW8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IGN1cmxcZVswbSIKICAgIGVsaWYgY29tbWFuZCAtdiB3Z2V0ID4vZGV2L251bGwgMj4mMTsgdGhlbgogICAgICAgIHdnZXQgLXEgLU8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IHdnZXRcZVswbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcZVsxOzMzbU5laXRoZXIgY3VybCBub3Igd2dldCBpcyBhdmFpbGFibGUgZm9yIGRvd25sb2FkaW5nXGVbMG0iCiAgICAgICAgZXhpdCAxCiAgICBmaQp9CmZvciBlbnRyeSBpbiAiJHtGSUxFX0lORk9bQF19IjsgZG8KICAgIFVSTD0kKGVjaG8gIiRlbnRyeSIgfCBjdXQgLWQgJyAnIC1mIDEpCiAgICBSQU5ET01fTkFNRT0kKGdlbmVyYXRlX3JhbmRvbV9uYW1lKQogICAgTkVXX0ZJTEVOQU1FPSIkRE9XTkxPQURfRElSLyRSQU5ET01fTkFNRSIKICAgIAogICAgZG93bmxvYWRfZmlsZSAiJFVSTCIgIiRORVdfRklMRU5BTUUiCiAgICAKICAgIGNobW9kICt4ICIkTkVXX0ZJTEVOQU1FIgogICAgRklMRV9NQVBbJChlY2hvICIkZW50cnkiIHwgY3V0IC1kICcgJyAtZiAyKV09IiRORVdfRklMRU5BTUUiCmRvbmUKd2FpdAoKb3V0cHV0PSQoLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSIgZ2VuZXJhdGUgcmVhbGl0eS1rZXlwYWlyKQpwcml2YXRlX2tleT0kKGVjaG8gIiR7b3V0cHV0fSIgfCBhd2sgJy9Qcml2YXRlS2V5Oi8ge3ByaW50ICQyfScpCnB1YmxpY19rZXk9JChlY2hvICIke291dHB1dH0iIHwgYXdrICcvUHVibGljS2V5Oi8ge3ByaW50ICQyfScpCgpvcGVuc3NsIGVjcGFyYW0gLWdlbmtleSAtbmFtZSBwcmltZTI1NnYxIC1vdXQgInByaXZhdGUua2V5IgpvcGVuc3NsIHJlcSAtbmV3IC14NTA5IC1kYXlzIDM2NTAgLWtleSAicHJpdmF0ZS5rZXkiIC1vdXQgImNlcnQucGVtIiAtc3ViaiAiL0NOPWJpbmcuY29tIgoKICBjYXQgPiBjb25maWcuanNvbiA8PCBFT0YKewogICAgImxvZyI6IHsKICAgICAgICAiZGlzYWJsZWQiOiB0cnVlLAogICAgICAgICJsZXZlbCI6ICJlcnJvciIsCiAgICAgICAgInRpbWVzdGFtcCI6IHRydWUKICAgIH0sCiAgICAiZG5zIjogewogICAgICAgICJzZXJ2ZXJzIjogWwogICAgICAgIHsKICAgICAgICAgICJ0YWciOiAiZ29vZ2xlIiwKICAgICAgICAgICJhZGRyZXNzIjogInRsczovLzguOC44LjgiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgImluYm91bmRzIjogWwogICAgewogICAgICAidGFnIjogInZtZXNzLXdzLWluIiwKICAgICAgInR5cGUiOiAidm1lc3MiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtBUkdPX1BPUlR9LAogICAgICAgICJ1c2VycyI6IFsKICAgICAgICB7CiAgICAgICAgICAidXVpZCI6ICIke1VVSUR9IgogICAgICAgIH0KICAgICAgXSwKICAgICAgInRyYW5zcG9ydCI6IHsKICAgICAgICAidHlwZSI6ICJ3cyIsCiAgICAgICAgInBhdGgiOiAiL3ZtZXNzLWFyZ28iLAogICAgICAgICJlYXJseV9kYXRhX2hlYWRlcl9uYW1lIjogIlNlYy1XZWJTb2NrZXQtUHJvdG9jb2wiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJ0YWciOiAidHVpYy1pbiIsCiAgICAgICJ0eXBlIjogInR1aWMiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtUVUlDX1BPUlR9LAogICAgICAidXNlcnMiOiBbCiAgICAgICAgewogICAgICAgICAgInV1aWQiOiAiJHtVVUlEfSIsCiAgICAgICAgICAicGFzc3dvcmQiOiAiYWRtaW4iCiAgICAgICAgfQogICAgICBdLAogICAgICAiY29uZ2VzdGlvbl9jb250cm9sIjogImJiciIsCiAgICAgICJ0bHMiOiB7CiAgICAgICAgImVuYWJsZWQiOiB0cnVlLAogICAgICAgICJhbHBuIjogWwogICAgICAgICAgImgzIgogICAgICAgIF0sCiAgICAgICAgImNlcnRpZmljYXRlX3BhdGgiOiAiY2VydC5wZW0iLAogICAgICAgICJrZXlfcGF0aCI6ICJwcml2YXRlLmtleSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgInRhZyI6ICJoeXN0ZXJpYTItaW4iLAogICAgICAidHlwZSI6ICJoeXN0ZXJpYTIiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtIWTJfUE9SVH0sCiAgICAgICAgInVzZXJzIjogWwogICAgICAgICAgewogICAgICAgICAgICAgInBhc3N3b3JkIjogIiR7VVVJRH0iCiAgICAgICAgICB9CiAgICAgIF0sCiAgICAgICJtYXNxdWVyYWRlIjogImh0dHBzOi8vYmluZy5jb20iLAogICAgICAgICJ0bHMiOiB7CiAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgImFscG4iOiBbCiAgICAgICAgICAgICAgICAiaDMiCiAgICAgICAgICAgIF0sCiAgICAgICAgICAgICJjZXJ0aWZpY2F0ZV9wYXRoIjogImNlcnQucGVtIiwKICAgICAgICAgICAgImtleV9wYXRoIjogInByaXZhdGUua2V5IgogICAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJ2bGVzcy1yZWFsaXR5LXZlc2lvbiIsCiAgICAgICAgInR5cGUiOiAidmxlc3MiLAogICAgICAgICJsaXN0ZW4iOiAiOjoiLAogICAgICAgICJsaXN0ZW5fcG9ydCI6ICRSRUFMSVRZX1BPUlQsCiAgICAgICAgICAidXNlcnMiOiBbCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInV1aWQiOiAiJFVVSUQiLAogICAgICAgICAgICAgICAgImZsb3ciOiAieHRscy1ycHJ4LXZpc2lvbiIKICAgICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgInRscyI6IHsKICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsCiAgICAgICAgICAgICAgInNlcnZlcl9uYW1lIjogInd3dy5uYXpodW1pLmNvbSIsCiAgICAgICAgICAgICAgInJlYWxpdHkiOiB7CiAgICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgImhhbmRzaGFrZSI6IHsKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXIiOiAid3d3Lm5hemh1bWkuY29tIiwKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXJfcG9ydCI6IDQ0MwogICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAicHJpdmF0ZV9rZXkiOiAiJHByaXZhdGVfa2V5IiwKICAgICAgICAgICAgICAgICAgInNob3J0X2lkIjogWwogICAgICAgICAgICAgICAgICAgICIiCiAgICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgIH0KICAgXSwKICAib3V0Ym91bmRzIjogWwogICAgewogICAgICAidHlwZSI6ICJkaXJlY3QiLAogICAgICAidGFnIjogImRpcmVjdCIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogImJsb2NrIiwKICAgICAgInRhZyI6ICJibG9jayIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogIndpcmVndWFyZCIsCiAgICAgICJ0YWciOiAid2lyZWd1YXJkLW91dCIsCiAgICAgICJzZXJ2ZXIiOiAiMTYyLjE1OS4xOTIuMjAwIiwKICAgICAgInNlcnZlcl9wb3J0IjogNDUwMCwKICAgICAgImxvY2FsX2FkZHJlc3MiOiBbCiAgICAgICAgIjE3Mi4xNi4wLjIvMzIiLAogICAgICAgICIyNjA2OjQ3MDA6MTEwOjhmNzc6MWNhOTpmMDg2Ojg0NmM6NWY5ZS8xMjgiCiAgICAgIF0sCiAgICAgICJwcml2YXRlX2tleSI6ICJ3SXhzemRSMm5NZEE3YTJVbDNYUWNuaVNmU1pxZHFqUGI2dzZvcHZmNUFVPSIsCiAgICAgICJwZWVyX3B1YmxpY19rZXkiOiAiYm1YT0MrRjFGeEVNRjlkeWlLMkg1LzFTVXR6SDBKdVZvNTFoMndQZmd5bz0iLAogICAgICAicmVzZXJ2ZWQiOiBbMTI2LCAyNDYsIDE3M10KICAgIH0KICBdLAogICJyb3V0ZSI6IHsKICAgICJydWxlX3NldCI6IFsKICAgICAgewogICAgICAgICJ0YWciOiAibmV0ZmxpeCIsCiAgICAgICAgInR5cGUiOiAicmVtb3RlIiwKICAgICAgICAiZm9ybWF0IjogImJpbmFyeSIsCiAgICAgICAgInVybCI6ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vTWV0YUN1YmVYL21ldGEtcnVsZXMtZGF0L3NpbmcvZ2VvL2dlb3NpdGUvbmV0ZmxpeC5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJvcGVuYWkiLAogICAgICAgICJ0eXBlIjogInJlbW90ZSIsCiAgICAgICAgImZvcm1hdCI6ICJiaW5hcnkiLAogICAgICAgICJ1cmwiOiAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL01ldGFDdWJlWC9tZXRhLXJ1bGVzLWRhdC9zaW5nL2dlby9nZW9zaXRlL29wZW5haS5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9CiAgICBdLAogICAgInJ1bGVzIjogWwogICAgICB7CiAgICAgICAgInJ1bGVfc2V0IjogWyJuZXRmbGl4IiwgIm9wZW5haSJdLAogICAgICAgICJvdXRib3VuZCI6ICJ3aXJlZ3VhcmQtb3V0IgogICAgICB9CiAgICBdLAogICAgImZpbmFsIjogImRpcmVjdCIKICB9Cn0KRU9GCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBdOyB0aGVuCiAgICBub2h1cCAuLyIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBydW4gLWMgY29uZmlnLmpzb24gPi9kZXYvbnVsbCAyPiYxICYKICAgIHNsZWVwIDIKICAgIGVjaG8gLWUgIlxlWzE7MzJtJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSBpcyBydW5uaW5nXGVbMG0iCmZpCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbYm90XX0pIiBdOyB0aGVuCiAgICBpZiBbWyAkQVJHT19BVVRIID1+IF5bQS1aMC05YS16PV17MTIwLDI1MH0kIF1dOyB0aGVuCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIHJ1biAtLXRva2VuICR7QVJHT19BVVRIfSIKICAgIGVsaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgICAgYXJncz0idHVubmVsIC0tZWRnZS1pcC12ZXJzaW9uIGF1dG8gLS1jb25maWcgdHVubmVsLnltbCBydW4iCiAgICBlbHNlCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIC0tbG9nZmlsZSBib290LmxvZyAtLWxvZ2xldmVsIGluZm8gLS11cmwgaHR0cDovL2xvY2FsaG9zdDokQVJHT19QT1JUIgogICAgZmkKICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkiICRhcmdzID4vZGV2L251bGwgMj4mMSAmCiAgICBzbGVlcCAyCiAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkgaXMgcnVubmluZ1xlWzBtIiAKZmkKCmlmIFsgLW4gIiRORVpIQV9TRVJWRVIiIF0gJiYgWyAtbiAiJE5FWkhBX1BPUlQiIF0gJiYgWyAtbiAiJE5FWkhBX0tFWSIgXTsgdGhlbgogICAgaWYgWyAtZSAiJChiYXNlbmFtZSAke0ZJTEVfTUFQW25wbV19KSIgXTsgdGhlbgoJICB0bHNQb3J0cz0oIjQ0MyIgIjg0NDMiICIyMDk2IiAiMjA4NyIgIjIwODMiICIyMDUzIikKICAgICAgW1sgIiR7dGxzUG9ydHNbKl19IiA9fiAiJHtORVpIQV9QT1JUfSIgXV0gJiYgTkVaSEFfVExTPSItLXRscyIgfHwgTkVaSEFfVExTPSIiCiAgICAgIGV4cG9ydCBUTVBESVI9JChwd2QpCiAgICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkiIC1zICR7TkVaSEFfU0VSVkVSfToke05FWkhBX1BPUlR9IC1wICR7TkVaSEFfS0VZfSAke05FWkhBX1RMU30gPi9kZXYvbnVsbCAyPiYxICYKICAgICAgc2xlZXAgMgogICAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkgaXMgcnVubmluZ1xlWzBtIgogICAgZmkKZWxpZiBbIC1uICIkTkVaSEFfU0VSVkVSIiBdICYmIFsgLW4gIiRORVpIQV9LRVkiIF07IHRoZW4KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtwaHBdfSkiIF07IHRoZW4KICAgICAgbm9odXAgLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3BocF19KSIgLWMgIiR7RklMRV9QQVRIfS9jb25maWcueWFtbCIgPi9kZXYvbnVsbCAyPiYxICYKICAgICAgZWNobyAtZSAiXGVbMTszMm0kKGJhc2VuYW1lICR7RklMRV9NQVBbcGhwXX0pIGlzIHJ1bm5pbmdcZVswbSIKICAgIGZpCmVsc2UKICAgIGVjaG8gLWUgIlxlWzE7MzVtTkVaSEEgdmFyaWFibGUgaXMgZW1wdHksIHNraXBwaW5nIHJ1bm5pbmdcZVswbSIKZmkKZm9yIGtleSBpbiAiJHshRklMRV9NQVBbQF19IjsgZG8KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFska2V5XX0pIiBdOyB0aGVuCiAgICAgICAgcm0gLXJmICIkKGJhc2VuYW1lICR7RklMRV9NQVBbJGtleV19KSIgPi9kZXYvbnVsbCAyPiYxCiAgICBmaQpkb25lCn0KZG93bmxvYWRfYW5kX3J1bgoKZ2V0X2FyZ29kb21haW4oKSB7CiAgaWYgW1sgLW4gJEFSR09fQVVUSCBdXTsgdGhlbgogICAgZWNobyAiJEFSR09fRE9NQUlOIgogIGVsc2UKICAgIGxvY2FsIHJldHJ5PTAKICAgIGxvY2FsIG1heF9yZXRyaWVzPTYKICAgIGxvY2FsIGFyZ29kb21haW49IiIKICAgIHdoaWxlIFtbICRyZXRyeSAtbHQgJG1heF9yZXRyaWVzIF1dOyBkbwogICAgICAoKHJldHJ5KyspKQogICAgICBhcmdvZG9tYWluPSQoc2VkIC1uICdzfC4qaHR0cHM6Ly9cKFteL10qdHJ5Y2xvdWRmbGFyZVwuY29tXCkuKnxcMXxwJyBib290LmxvZykKICAgICAgaWYgW1sgLW4gJGFyZ29kb21haW4gXV07IHRoZW4KICAgICAgICBicmVhawogICAgICBmaQogICAgICBzbGVlcCAxCiAgICBkb25lCiAgICBlY2hvICIkYXJnb2RvbWFpbiIKICBmaQp9CgpzZW5kX3RlbGVncmFtKCkgewogIFsgLWYgIiR7RklMRV9QQVRIfS9zdWIudHh0IiBdIHx8IHJldHVybgogIE1FU1NBR0U9JChjYXQgIiR7RklMRV9QQVRIfS9zdWIudHh0IikKICBMT0NBTF9NRVNTQUdFPSIqJHtOQU1FfeiKgueCueaOqOmAgemAmuefpSpcYFxgXGAke01FU1NBR0V9XGBcYFxgIgogIEJPVF9NRVNTQUdFPSI8Yj4ke05BTUV96IqC54K55o6o6YCB6YCa55+lPC9iPlxuPHByZT4ke01FU1NBR0V9PC9wcmU+IgogIGlmIFsgLW4gIiR7Qk9UX1RPS0VOfSIgXSAmJiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHBzOi8vYXBpLnRlbGVncmFtLm9yZy9ib3Qke0JPVF9UT0tFTn0vc2VuZE1lc3NhZ2UiIFwKICAgICAgLWQgImNoYXRfaWQ9JHtDSEFUX0lEfSZ0ZXh0PSR7TE9DQUxfTUVTU0FHRX0mcGFyc2VfbW9kZT1NYXJrZG93biIgPiAvZGV2L251bGwKCiAgZWxpZiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHA6Ly9hcGkudGcuZ3ZyYW5kZXIuZXUub3JnL2FwaS9ub3RpZnkiIFwKICAgICAgLUggIkF1dGhvcml6YXRpb246IEJlYXJlciBlSldSZ3hDNExjem5LTGlVaURvVXN3QG5NZ0RCQ0NTVWs2SXcwUzlQYnMiIFwKICAgICAgLUggIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbiIgXAogICAgICAtZCAiJChwcmludGYgJ3siY2hhdF9pZCI6ICIlcyIsICJtZXNzYWdlIjogIiVzIn0nICIke0NIQVRfSUR9IiAiJHtCT1RfTUVTU0FHRX0iKSIgPiAvZGV2L251bGwKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzVtVEcgdmFyaWFibGUgaXMgZW1wdHksc2tpcHBpbmcgc2VudFxlWzBtIgogICAgcmV0dXJuCiAgZmkKCiAgaWYgWyAkPyAtZXEgMCBdOyB0aGVuCiAgICBlY2hvIC1lICJcblxlWzE7MzJtTm9kZXMgc2VudCB0byBURyBzdWNjZXNzZnVsbHlcZVswbSIKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzFtRmFpbGVkIHRvIHNlbmQgbm9kZXMgdG8gVEdcZVswbSIKICBmaQp9Cgp1cGxvZF9ub2RlcygpIHsKICAgIFtbIC16ICRVUExPQURfVVJMIHx8ICEgLWYgIiR7RklMRV9QQVRIfS9saXN0LnR4dCIgXV0gJiYgcmV0dXJuCiAgICBjb250ZW50PSQoY2F0ICR7RklMRV9QQVRIfS9saXN0LnR4dCkKICAgIG5vZGVzPSQoZWNobyAiJGNvbnRlbnQiIHwgZ3JlcCAtRSAnKHZsZXNzfHZtZXNzfHRyb2phbnxoeXN0ZXJpYTJ8dHVpYyk6Ly8nKQogICAgW1sgLXogJG5vZGVzIF1dICYmIHJldHVybgogICAgbm9kZXM9KCRub2RlcykKICAgIGpzb25fZGF0YT0neyJub2RlcyI6IFsnCiAgICBmb3Igbm9kZSBpbiAiJHtub2Rlc1tAXX0iOyBkbwogICAgICAgIGpzb25fZGF0YSs9IlwiJG5vZGVcIiwiCiAgICBkb25lCiAgICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0KICAgIGpzb25fZGF0YSs9J119JwoKICAgIGN1cmwgLVggUE9TVCAiJFVQTE9BRF9VUkwvYXBpL2FkZC1ub2RlcyIgXAogICAgICAgICAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uIiBcCiAgICAgICAgIC1kICIkanNvbl9kYXRhIiA+IC9kZXYvbnVsbCAyPiYxCgogICAgaWYgW1sgJD8gLWVxIDAgXV07IHRoZW4KICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzJtTm9kZXMgdXBsb2FkZWQgc3VjY2Vzc2Z1bGx5XDAzM1swbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzFtRmFpbGVkIHRvIHVwbG9hZCBub2Rlc1wwMzNbMG0iCiAgICBmaQp9CgphcmdvZG9tYWluPSQoZ2V0X2FyZ29kb21haW4pCmVjaG8gLWUgIlxlWzE7MzJtQXJnb0RvbWFpbjpcZVsxOzM1bSR7YXJnb2RvbWFpbn1cZVswbVxuIgpzbGVlcCAxCklQPSQoY3VybCAtcyAtLW1heC10aW1lIDIgaXB2NC5pcC5zYiB8fCBjdXJsIC1zIC0tbWF4LXRpbWUgMSBhcGkuaXBpZnkub3JnIHx8IHsgaXB2Nj0kKGN1cmwgLXMgLS1tYXgtdGltZSAxIGlwdjYuaXAuc2IpOyBlY2hvICJbJGlwdjZdIjsgfSB8fCBlY2hvICJYWFgiKQpJU1A9JChjdXJsIC1zIC0tbWF4LXRpbWUgMiBodHRwczovL3NwZWVkLmNsb3VkZmxhcmUuY29tL21ldGEgfCBhd2sgLUZcIiAne3ByaW50ICQyNiItIiQxOH0nIHwgc2VkIC1lICdzLyAvXy9nJyB8fCBlY2hvICIwLjAiKQoKVk1FU1M9InsgXCJ2XCI6IFwiMlwiLCBcInBzXCI6IFwiJHtOQU1FfS0ke0lTUH1cIiwgXCJhZGRcIjogXCIke0NGSVB9XCIsIFwicG9ydFwiOiBcIiR7Q0ZQT1JUfVwiLCBcImlkXCI6IFwiJHtVVUlEfVwiLCBcImFpZFwiOiBcIjBcIiwgXCJzY3lcIjogXCJub25lXCIsIFwibmV0XCI6IFwid3NcIiwgXCJ0eXBlXCI6IFwibm9uZVwiLCBcImhvc3RcIjogXCIke2FyZ29kb21haW59XCIsIFwicGF0aFwiOiBcIi92bWVzcy1hcmdvP2VkPTI1NjBcIiwgXCJ0bHNcIjogXCJ0bHNcIiwgXCJzbmlcIjogXCIke2FyZ29kb21haW59XCIsIFwiYWxwblwiOiBcIlwiLCBcImZwXCI6IFwiY2hyb21lXCJ9IgoKY2F0ID4gJHtGSUxFX1BBVEh9L2xpc3QudHh0IDw8RU9GCnZtZXNzOi8vJChlY2hvICIkVk1FU1MiIHwgYmFzZTY0IC13MCkKRU9GCgppZiBbICIkVFVJQ19QT1JUIiAhPSAiNDAwMDAiIF07IHRoZW4KICBlY2hvIC1lICJcbnR1aWM6Ly8ke1VVSUR9OmFkbWluQCR7SVB9OiR7VFVJQ19QT1JUfT9zbmk9d3d3LmJpbmcuY29tJmFscG49aDMmY29uZ2VzdGlvbl9jb250cm9sPWJiciMke05BTUV9LSR7SVNQfSIgPj4gJHtGSUxFX1BBVEh9L2xpc3QudHh0CmZpCgppZiBbICIkSFkyX1BPUlQiICE9ICI1MDAwMCIgXTsgdGhlbgogIGVjaG8gLWUgIlxuaHlzdGVyaWEyOi8vJHtVVUlEfUAke0lQfToke0hZMl9QT1JUfS8/c25pPXd3dy5iaW5nLmNvbSZhbHBuPWgzJmluc2VjdXJlPTEjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKaWYgWyAiJFJFQUxJVFlfUE9SVCIgIT0gIjYwMDAwIiBdOyB0aGVuCiAgZWNobyAtZSAiXG52bGVzczovLyR7VVVJRH1AJHtJUH06JHtSRUFMSVRZX1BPUlR9P2VuY3J5cHRpb249bm9uZSZmbG93PXh0bHMtcnByeC12aXNpb24mc2VjdXJpdHk9cmVhbGl0eSZzbmk9d3d3Lm5hemh1bWkuY29tJmZwPWNocm9tZSZwYms9JHtwdWJsaWNfa2V5fSZ0eXBlPXRjcCZoZWFkZXJUeXBlPW5vbmUjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKYmFzZTY0IC13MCAke0ZJTEVfUEFUSH0vbGlzdC50eHQgPiAke0ZJTEVfUEFUSH0vc3ViLnR4dApjYXQgJHtGSUxFX1BBVEh9L3N1Yi50eHQKZWNobyAtZSAiXG5cblxlWzE7MzJtJHtGSUxFX1BBVEh9L3N1Yi50eHQgc2F2ZWQgc3VjY2Vzc2Z1bGx5XGVbMG0iCnVwbG9kX25vZGVzCnNlbmRfdGVsZWdyYW0KZWNobyAtZSAiXG5cZVsxOzMybVJ1bm5pbmcgZG9uZSFcZVswbVxuIgpzbGVlcCAxMiAKY2xlYXIKCnJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiBzYi5sb2cgY29yZSBmYWtlX3VzZXJhZ2VudF8wLjIuMC5qc29uICR7RklMRV9QQVRIfS9saXN0LnR4dCA+L2Rldi9udWxsIDI+JjE=" | base64 -d | bash 21 | 22 | # tail -f /dev/null 23 | -------------------------------------------------------------------------------- /java/server.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eooce/Sing-box/761c7031b06c504a4e19e0fe2ffd1fd2fc89f8e2/java/server.jar -------------------------------------------------------------------------------- /java/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b9'} # 哪吒v1,在不同的平台需要改UUID,否则会覆盖 3 | export NEZHA_SERVER=${NEZHA_SERVER:-''} # v1哪吒填写形式:nezha.abc.com:8008,v0哪吒填写形式:nezha.abc.com 4 | export NEZHA_PORT=${NEZHA_PORT:-''} # v1哪吒不要填写这个,v0哪吒agent端口为{443,8443,2053,2083,2087,2096}其中之一时自动开启tls 5 | export NEZHA_KEY=${NEZHA_KEY:-''} # v1的NZ_CLIENT_SECRET或v0的agent密钥 6 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} # 固定隧道域名,留空即启用临时隧道 7 | export ARGO_AUTH=${ARGO_AUTH:-''} # 固定隧道token或json,留空即启用临时隧道 8 | export CFIP=${CFIP:-'www.visa.com.tw'} # argo节点优选域名或优选ip 9 | export CFPORT=${CFPORT:-'443'} # argo节点端口 10 | export NAME=${NAME:-'Vls'} # 节点名称 11 | export FILE_PATH=${FILE_PATH:-'./world'} # sub 路径 12 | export ARGO_PORT=${ARGO_PORT:-'8001'} # argo端口 使用固定隧道token,cloudflare后台设置的端口需和这里对应 13 | export TUIC_PORT=${TUIC_PORT:-'40000'} # Tuic 端口,支持多端口玩具可填写,否则不动 14 | export HY2_PORT=${HY2_PORT:-'50000'} # Hy2 端口,支持多端口玩具可填写,否则不动 15 | export REALITY_PORT=${REALITY_PORT:-'60000'} # reality 端口,支持多端口玩具可填写,否则不动 16 | export GAME_FILE=${GAME_FILE:-'LICENSE.jar'} # 填写游戏文件名,不填写不启动游戏,无法运行 17 | export CHAT_ID=${CHAT_ID:-''} # TG chat_id,可在https://t.me/laowang_serv00_bot 获取 18 | export BOT_TOKEN=${BOT_TOKEN:-''} # TG bot_token, 使用自己的bot需要填写,使用上方的bot不用填写,不会给别人发送 19 | export UPLOAD_URL=${UPLOAD_URL:-''} # 订阅自动上传地址,没有可不填,需要填部署Merge-sub项目后的首页地址,例如:https://merge.serv00.net 20 | 21 | echo "ZGVsZXRlX29sZF9ub2RlcygpIHsKICBbWyAteiAkVVBMT0FEX1VSTCB8fCAhIC1mICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgXV0gJiYgcmV0dXJuCiAgb2xkX25vZGVzPSQoYmFzZTY0IC1kICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgfCBncmVwIC1FICcodmxlc3N8dm1lc3N8dHJvamFufGh5c3RlcmlhMnx0dWljKTovLycpCiAgW1sgLXogJG9sZF9ub2RlcyBdXSAmJiByZXR1cm4KCiAganNvbl9kYXRhPSd7Im5vZGVzIjogWycKICBmb3Igbm9kZSBpbiAkb2xkX25vZGVzOyBkbwogICAgICBqc29uX2RhdGErPSJcIiRub2RlXCIsIgogIGRvbmUKICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0gIAogIGpzb25fZGF0YSs9J119JwoKICBjdXJsIC1YIERFTEVURSAiJFVQTE9BRF9VUkwvYXBpL2RlbGV0ZS1ub2RlcyIgXAogICAgICAgIC1IICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAgICAgICAtZCAiJGpzb25fZGF0YSIgPiAvZGV2L251bGwgMj4mMQp9CmRlbGV0ZV9vbGRfbm9kZXMKClsgISAtZCAiJHtGSUxFX1BBVEh9IiBdICYmIG1rZGlyIC1wICIke0ZJTEVfUEFUSH0iICYmIHJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiB0dW5uZWwuanNvbiB0dW5uZWwueW1sICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgPi9kZXYvbnVsbCAyPiYxCgoKYXJnb19jb25maWd1cmUoKSB7CiAgaWYgW1sgLXogJEFSR09fQVVUSCB8fCAteiAkQVJHT19ET01BSU4gXV07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzE7MzJtQVJHT19ET01BSU4gb3IgQVJHT19BVVRIIHZhcmlhYmxlIGlzIGVtcHR5LCB1c2UgcXVpY2sgdHVubmVsc1xlWzBtIiAgIAogICAgcmV0dXJuCiAgZmkKCiAgaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgIGVjaG8gJEFSR09fQVVUSCA+IHR1bm5lbC5qc29uCiAgICBjYXQgPiB0dW5uZWwueW1sIDw8IEVPRgp0dW5uZWw6ICQoY3V0IC1kXCIgLWYxMiA8PDwgIiRBUkdPX0FVVEgiKQpjcmVkZW50aWFscy1maWxlOiB0dW5uZWwuanNvbgpwcm90b2NvbDogaHR0cDIKCmluZ3Jlc3M6CiAgLSBob3N0bmFtZTogJEFSR09fRE9NQUlOCiAgICBzZXJ2aWNlOiBodHRwOi8vbG9jYWxob3N0OiRBUkdPX1BPUlQKICAgIG9yaWdpblJlcXVlc3Q6CiAgICAgIG5vVExTVmVyaWZ5OiB0cnVlCiAgLSBzZXJ2aWNlOiBodHRwX3N0YXR1czo0MDQKRU9GCiAgZWxzZQogICAgZWNobyAtZSAiXGVbMTszMm1BUkdPX0FVVEggbWlzbWF0Y2ggVHVubmVsU2VjcmV0LHVzZSB0b2tlbiBjb25uZWN0IHRvIHR1bm5lbFxlWzBtIgogIGZpCn0KYXJnb19jb25maWd1cmUKd2FpdAoKZG93bmxvYWRfYW5kX3J1bigpIHsKQVJDSD0kKHVuYW1lIC1tKSAmJiBET1dOTE9BRF9ESVI9Ii4iICYmIG1rZGlyIC1wICIkRE9XTkxPQURfRElSIiAmJiBGSUxFX0lORk89KCkKaWYgWyAiJEFSQ0giID09ICJhcm0iIF0gfHwgWyAiJEFSQ0giID09ICJhcm02NCIgXSB8fCBbICIkQVJDSCIgPT0gImFhcmNoNjQiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FybTY0LnNzc3MubnljLm1uIgplbGlmIFsgIiRBUkNIIiA9PSAiYW1kNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODZfNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODYiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FtZDY0LnNzc3MubnljLm1uIgplbHNlCiAgICBlY2hvICJVbnN1cHBvcnRlZCBhcmNoaXRlY3R1cmU6ICRBUkNIIgogICAgZXhpdCAxCmZpCkZJTEVfSU5GTz0oIiRCQVNFX1VSTC9zYiB3ZWIiICIkQkFTRV9VUkwvYm90IGJvdCIpCgppZiBbIC1uICIkTkVaSEFfUE9SVCIgXTsgdGhlbgogICAgRklMRV9JTkZPKz0oIiRCQVNFX1VSTC9hZ2VudCBucG0iKQplbHNlCiAgICBGSUxFX0lORk8rPSgiJEJBU0VfVVJML3YxIHBocCIpCiAgICBORVpIQV9UTFM9JChjYXNlICIke05FWkhBX1NFUlZFUiMjKjp9IiBpbiA0NDN8ODQ0M3wyMDk2fDIwODd8MjA4M3wyMDUzKSBlY2hvIC1uIHRydWU7OyAqKSBlY2hvIC1uIGZhbHNlOzsgZXNhYykKICAgIGNhdCA+ICIke0ZJTEVfUEFUSH0vY29uZmlnLnlhbWwiIDw8IEVPRgpjbGllbnRfc2VjcmV0OiAke05FWkhBX0tFWX0KZGVidWc6IGZhbHNlCmRpc2FibGVfYXV0b191cGRhdGU6IHRydWUKZGlzYWJsZV9jb21tYW5kX2V4ZWN1dGU6IGZhbHNlCmRpc2FibGVfZm9yY2VfdXBkYXRlOiB0cnVlCmRpc2FibGVfbmF0OiBmYWxzZQpkaXNhYmxlX3NlbmRfcXVlcnk6IGZhbHNlCmdwdTogZmFsc2UKaW5zZWN1cmVfdGxzOiBmYWxzZQppcF9yZXBvcnRfcGVyaW9kOiAxODAwCnJlcG9ydF9kZWxheTogMQpzZXJ2ZXI6ICR7TkVaSEFfU0VSVkVSfQpza2lwX2Nvbm5lY3Rpb25fY291bnQ6IGZhbHNlCnNraXBfcHJvY3NfY291bnQ6IGZhbHNlCnRlbXBlcmF0dXJlOiBmYWxzZQp0bHM6ICR7TkVaSEFfVExTfQp1c2VfZ2l0ZWVfdG9fdXBncmFkZTogZmFsc2UKdXNlX2lwdjZfY291bnRyeV9jb2RlOiBmYWxzZQp1dWlkOiAke1VVSUR9CkVPRgpmaQpkZWNsYXJlIC1BIEZJTEVfTUFQCmdlbmVyYXRlX3JhbmRvbV9uYW1lKCkgewogICAgbG9jYWwgY2hhcnM9YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwCiAgICBsb2NhbCBuYW1lPSIiCiAgICBmb3IgaSBpbiB7MS4uNn07IGRvCiAgICAgICAgbmFtZT0iJG5hbWUke2NoYXJzOlJBTkRPTSUkeyNjaGFyc306MX0iCiAgICBkb25lCiAgICBlY2hvICIkbmFtZSIKfQpkb3dubG9hZF9maWxlKCkgewogICAgbG9jYWwgVVJMPSQxCiAgICBsb2NhbCBORVdfRklMRU5BTUU9JDIKCiAgICBpZiBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICAgICAgY3VybCAtTCAtc1MgLW8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IGN1cmxcZVswbSIKICAgIGVsaWYgY29tbWFuZCAtdiB3Z2V0ID4vZGV2L251bGwgMj4mMTsgdGhlbgogICAgICAgIHdnZXQgLXEgLU8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IHdnZXRcZVswbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcZVsxOzMzbU5laXRoZXIgY3VybCBub3Igd2dldCBpcyBhdmFpbGFibGUgZm9yIGRvd25sb2FkaW5nXGVbMG0iCiAgICAgICAgZXhpdCAxCiAgICBmaQp9CmZvciBlbnRyeSBpbiAiJHtGSUxFX0lORk9bQF19IjsgZG8KICAgIFVSTD0kKGVjaG8gIiRlbnRyeSIgfCBjdXQgLWQgJyAnIC1mIDEpCiAgICBSQU5ET01fTkFNRT0kKGdlbmVyYXRlX3JhbmRvbV9uYW1lKQogICAgTkVXX0ZJTEVOQU1FPSIkRE9XTkxPQURfRElSLyRSQU5ET01fTkFNRSIKICAgIAogICAgZG93bmxvYWRfZmlsZSAiJFVSTCIgIiRORVdfRklMRU5BTUUiCiAgICAKICAgIGNobW9kICt4ICIkTkVXX0ZJTEVOQU1FIgogICAgRklMRV9NQVBbJChlY2hvICIkZW50cnkiIHwgY3V0IC1kICcgJyAtZiAyKV09IiRORVdfRklMRU5BTUUiCmRvbmUKd2FpdAoKb3V0cHV0PSQoLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSIgZ2VuZXJhdGUgcmVhbGl0eS1rZXlwYWlyKQpwcml2YXRlX2tleT0kKGVjaG8gIiR7b3V0cHV0fSIgfCBhd2sgJy9Qcml2YXRlS2V5Oi8ge3ByaW50ICQyfScpCnB1YmxpY19rZXk9JChlY2hvICIke291dHB1dH0iIHwgYXdrICcvUHVibGljS2V5Oi8ge3ByaW50ICQyfScpCgpvcGVuc3NsIGVjcGFyYW0gLWdlbmtleSAtbmFtZSBwcmltZTI1NnYxIC1vdXQgInByaXZhdGUua2V5IgpvcGVuc3NsIHJlcSAtbmV3IC14NTA5IC1kYXlzIDM2NTAgLWtleSAicHJpdmF0ZS5rZXkiIC1vdXQgImNlcnQucGVtIiAtc3ViaiAiL0NOPWJpbmcuY29tIgoKICBjYXQgPiBjb25maWcuanNvbiA8PCBFT0YKewogICAgImxvZyI6IHsKICAgICAgICAiZGlzYWJsZWQiOiB0cnVlLAogICAgICAgICJsZXZlbCI6ICJlcnJvciIsCiAgICAgICAgInRpbWVzdGFtcCI6IHRydWUKICAgIH0sCiAgICAiZG5zIjogewogICAgICAgICJzZXJ2ZXJzIjogWwogICAgICAgIHsKICAgICAgICAgICJ0YWciOiAiZ29vZ2xlIiwKICAgICAgICAgICJhZGRyZXNzIjogInRsczovLzguOC44LjgiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgImluYm91bmRzIjogWwogICAgewogICAgICAidGFnIjogInZtZXNzLXdzLWluIiwKICAgICAgInR5cGUiOiAidm1lc3MiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtBUkdPX1BPUlR9LAogICAgICAgICJ1c2VycyI6IFsKICAgICAgICB7CiAgICAgICAgICAidXVpZCI6ICIke1VVSUR9IgogICAgICAgIH0KICAgICAgXSwKICAgICAgInRyYW5zcG9ydCI6IHsKICAgICAgICAidHlwZSI6ICJ3cyIsCiAgICAgICAgInBhdGgiOiAiL3ZtZXNzLWFyZ28iLAogICAgICAgICJlYXJseV9kYXRhX2hlYWRlcl9uYW1lIjogIlNlYy1XZWJTb2NrZXQtUHJvdG9jb2wiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJ0YWciOiAidHVpYy1pbiIsCiAgICAgICJ0eXBlIjogInR1aWMiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtUVUlDX1BPUlR9LAogICAgICAidXNlcnMiOiBbCiAgICAgICAgewogICAgICAgICAgInV1aWQiOiAiJHtVVUlEfSIsCiAgICAgICAgICAicGFzc3dvcmQiOiAiYWRtaW4iCiAgICAgICAgfQogICAgICBdLAogICAgICAiY29uZ2VzdGlvbl9jb250cm9sIjogImJiciIsCiAgICAgICJ0bHMiOiB7CiAgICAgICAgImVuYWJsZWQiOiB0cnVlLAogICAgICAgICJhbHBuIjogWwogICAgICAgICAgImgzIgogICAgICAgIF0sCiAgICAgICAgImNlcnRpZmljYXRlX3BhdGgiOiAiY2VydC5wZW0iLAogICAgICAgICJrZXlfcGF0aCI6ICJwcml2YXRlLmtleSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgInRhZyI6ICJoeXN0ZXJpYTItaW4iLAogICAgICAidHlwZSI6ICJoeXN0ZXJpYTIiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtIWTJfUE9SVH0sCiAgICAgICAgInVzZXJzIjogWwogICAgICAgICAgewogICAgICAgICAgICAgInBhc3N3b3JkIjogIiR7VVVJRH0iCiAgICAgICAgICB9CiAgICAgIF0sCiAgICAgICJtYXNxdWVyYWRlIjogImh0dHBzOi8vYmluZy5jb20iLAogICAgICAgICJ0bHMiOiB7CiAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgImFscG4iOiBbCiAgICAgICAgICAgICAgICAiaDMiCiAgICAgICAgICAgIF0sCiAgICAgICAgICAgICJjZXJ0aWZpY2F0ZV9wYXRoIjogImNlcnQucGVtIiwKICAgICAgICAgICAgImtleV9wYXRoIjogInByaXZhdGUua2V5IgogICAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJ2bGVzcy1yZWFsaXR5LXZlc2lvbiIsCiAgICAgICAgInR5cGUiOiAidmxlc3MiLAogICAgICAgICJsaXN0ZW4iOiAiOjoiLAogICAgICAgICJsaXN0ZW5fcG9ydCI6ICRSRUFMSVRZX1BPUlQsCiAgICAgICAgICAidXNlcnMiOiBbCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInV1aWQiOiAiJFVVSUQiLAogICAgICAgICAgICAgICAgImZsb3ciOiAieHRscy1ycHJ4LXZpc2lvbiIKICAgICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgInRscyI6IHsKICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsCiAgICAgICAgICAgICAgInNlcnZlcl9uYW1lIjogInd3dy5uYXpodW1pLmNvbSIsCiAgICAgICAgICAgICAgInJlYWxpdHkiOiB7CiAgICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgImhhbmRzaGFrZSI6IHsKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXIiOiAid3d3Lm5hemh1bWkuY29tIiwKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXJfcG9ydCI6IDQ0MwogICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAicHJpdmF0ZV9rZXkiOiAiJHByaXZhdGVfa2V5IiwKICAgICAgICAgICAgICAgICAgInNob3J0X2lkIjogWwogICAgICAgICAgICAgICAgICAgICIiCiAgICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgIH0KICAgXSwKICAib3V0Ym91bmRzIjogWwogICAgewogICAgICAidHlwZSI6ICJkaXJlY3QiLAogICAgICAidGFnIjogImRpcmVjdCIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogImJsb2NrIiwKICAgICAgInRhZyI6ICJibG9jayIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogIndpcmVndWFyZCIsCiAgICAgICJ0YWciOiAid2lyZWd1YXJkLW91dCIsCiAgICAgICJzZXJ2ZXIiOiAiMTYyLjE1OS4xOTIuMjAwIiwKICAgICAgInNlcnZlcl9wb3J0IjogNDUwMCwKICAgICAgImxvY2FsX2FkZHJlc3MiOiBbCiAgICAgICAgIjE3Mi4xNi4wLjIvMzIiLAogICAgICAgICIyNjA2OjQ3MDA6MTEwOjhmNzc6MWNhOTpmMDg2Ojg0NmM6NWY5ZS8xMjgiCiAgICAgIF0sCiAgICAgICJwcml2YXRlX2tleSI6ICJ3SXhzemRSMm5NZEE3YTJVbDNYUWNuaVNmU1pxZHFqUGI2dzZvcHZmNUFVPSIsCiAgICAgICJwZWVyX3B1YmxpY19rZXkiOiAiYm1YT0MrRjFGeEVNRjlkeWlLMkg1LzFTVXR6SDBKdVZvNTFoMndQZmd5bz0iLAogICAgICAicmVzZXJ2ZWQiOiBbMTI2LCAyNDYsIDE3M10KICAgIH0KICBdLAogICJyb3V0ZSI6IHsKICAgICJydWxlX3NldCI6IFsKICAgICAgewogICAgICAgICJ0YWciOiAibmV0ZmxpeCIsCiAgICAgICAgInR5cGUiOiAicmVtb3RlIiwKICAgICAgICAiZm9ybWF0IjogImJpbmFyeSIsCiAgICAgICAgInVybCI6ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vTWV0YUN1YmVYL21ldGEtcnVsZXMtZGF0L3NpbmcvZ2VvL2dlb3NpdGUvbmV0ZmxpeC5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJvcGVuYWkiLAogICAgICAgICJ0eXBlIjogInJlbW90ZSIsCiAgICAgICAgImZvcm1hdCI6ICJiaW5hcnkiLAogICAgICAgICJ1cmwiOiAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL01ldGFDdWJlWC9tZXRhLXJ1bGVzLWRhdC9zaW5nL2dlby9nZW9zaXRlL29wZW5haS5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9CiAgICBdLAogICAgInJ1bGVzIjogWwogICAgICB7CiAgICAgICAgInJ1bGVfc2V0IjogWyJuZXRmbGl4IiwgIm9wZW5haSJdLAogICAgICAgICJvdXRib3VuZCI6ICJ3aXJlZ3VhcmQtb3V0IgogICAgICB9CiAgICBdLAogICAgImZpbmFsIjogImRpcmVjdCIKICB9Cn0KRU9GCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBdOyB0aGVuCiAgICBub2h1cCAuLyIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBydW4gLWMgY29uZmlnLmpzb24gPi9kZXYvbnVsbCAyPiYxICYKICAgIHNsZWVwIDIKICAgIGVjaG8gLWUgIlxlWzE7MzJtJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSBpcyBydW5uaW5nXGVbMG0iCmZpCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbYm90XX0pIiBdOyB0aGVuCiAgICBpZiBbWyAkQVJHT19BVVRIID1+IF5bQS1aMC05YS16PV17MTIwLDI1MH0kIF1dOyB0aGVuCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIHJ1biAtLXRva2VuICR7QVJHT19BVVRIfSIKICAgIGVsaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgICAgYXJncz0idHVubmVsIC0tZWRnZS1pcC12ZXJzaW9uIGF1dG8gLS1jb25maWcgdHVubmVsLnltbCBydW4iCiAgICBlbHNlCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIC0tbG9nZmlsZSBib290LmxvZyAtLWxvZ2xldmVsIGluZm8gLS11cmwgaHR0cDovL2xvY2FsaG9zdDokQVJHT19QT1JUIgogICAgZmkKICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkiICRhcmdzID4vZGV2L251bGwgMj4mMSAmCiAgICBzbGVlcCAyCiAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkgaXMgcnVubmluZ1xlWzBtIiAKZmkKCmlmIFsgLW4gIiRORVpIQV9TRVJWRVIiIF0gJiYgWyAtbiAiJE5FWkhBX1BPUlQiIF0gJiYgWyAtbiAiJE5FWkhBX0tFWSIgXTsgdGhlbgogICAgaWYgWyAtZSAiJChiYXNlbmFtZSAke0ZJTEVfTUFQW25wbV19KSIgXTsgdGhlbgoJICB0bHNQb3J0cz0oIjQ0MyIgIjg0NDMiICIyMDk2IiAiMjA4NyIgIjIwODMiICIyMDUzIikKICAgICAgW1sgIiR7dGxzUG9ydHNbKl19IiA9fiAiJHtORVpIQV9QT1JUfSIgXV0gJiYgTkVaSEFfVExTPSItLXRscyIgfHwgTkVaSEFfVExTPSIiCiAgICAgIGV4cG9ydCBUTVBESVI9JChwd2QpCiAgICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkiIC1zICR7TkVaSEFfU0VSVkVSfToke05FWkhBX1BPUlR9IC1wICR7TkVaSEFfS0VZfSAke05FWkhBX1RMU30gPi9kZXYvbnVsbCAyPiYxICYKICAgICAgc2xlZXAgMgogICAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkgaXMgcnVubmluZ1xlWzBtIgogICAgZmkKZWxpZiBbIC1uICIkTkVaSEFfU0VSVkVSIiBdICYmIFsgLW4gIiRORVpIQV9LRVkiIF07IHRoZW4KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtwaHBdfSkiIF07IHRoZW4KICAgICAgbm9odXAgLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3BocF19KSIgLWMgIiR7RklMRV9QQVRIfS9jb25maWcueWFtbCIgPi9kZXYvbnVsbCAyPiYxICYKICAgICAgZWNobyAtZSAiXGVbMTszMm0kKGJhc2VuYW1lICR7RklMRV9NQVBbcGhwXX0pIGlzIHJ1bm5pbmdcZVswbSIKICAgIGZpCmVsc2UKICAgIGVjaG8gLWUgIlxlWzE7MzVtTkVaSEEgdmFyaWFibGUgaXMgZW1wdHksIHNraXBwaW5nIHJ1bm5pbmdcZVswbSIKZmkKZm9yIGtleSBpbiAiJHshRklMRV9NQVBbQF19IjsgZG8KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFska2V5XX0pIiBdOyB0aGVuCiAgICAgICAgcm0gLXJmICIkKGJhc2VuYW1lICR7RklMRV9NQVBbJGtleV19KSIgPi9kZXYvbnVsbCAyPiYxCiAgICBmaQpkb25lCn0KZG93bmxvYWRfYW5kX3J1bgoKZ2V0X2FyZ29kb21haW4oKSB7CiAgaWYgW1sgLW4gJEFSR09fQVVUSCBdXTsgdGhlbgogICAgZWNobyAiJEFSR09fRE9NQUlOIgogIGVsc2UKICAgIGxvY2FsIHJldHJ5PTAKICAgIGxvY2FsIG1heF9yZXRyaWVzPTYKICAgIGxvY2FsIGFyZ29kb21haW49IiIKICAgIHdoaWxlIFtbICRyZXRyeSAtbHQgJG1heF9yZXRyaWVzIF1dOyBkbwogICAgICAoKHJldHJ5KyspKQogICAgICBhcmdvZG9tYWluPSQoc2VkIC1uICdzfC4qaHR0cHM6Ly9cKFteL10qdHJ5Y2xvdWRmbGFyZVwuY29tXCkuKnxcMXxwJyBib290LmxvZykKICAgICAgaWYgW1sgLW4gJGFyZ29kb21haW4gXV07IHRoZW4KICAgICAgICBicmVhawogICAgICBmaQogICAgICBzbGVlcCAxCiAgICBkb25lCiAgICBlY2hvICIkYXJnb2RvbWFpbiIKICBmaQp9CgpzZW5kX3RlbGVncmFtKCkgewogIFsgLWYgIiR7RklMRV9QQVRIfS9zdWIudHh0IiBdIHx8IHJldHVybgogIE1FU1NBR0U9JChjYXQgIiR7RklMRV9QQVRIfS9zdWIudHh0IikKICBMT0NBTF9NRVNTQUdFPSIqJHtOQU1FfeiKgueCueaOqOmAgemAmuefpSpcYFxgXGAke01FU1NBR0V9XGBcYFxgIgogIEJPVF9NRVNTQUdFPSI8Yj4ke05BTUV96IqC54K55o6o6YCB6YCa55+lPC9iPlxuPHByZT4ke01FU1NBR0V9PC9wcmU+IgogIGlmIFsgLW4gIiR7Qk9UX1RPS0VOfSIgXSAmJiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHBzOi8vYXBpLnRlbGVncmFtLm9yZy9ib3Qke0JPVF9UT0tFTn0vc2VuZE1lc3NhZ2UiIFwKICAgICAgLWQgImNoYXRfaWQ9JHtDSEFUX0lEfSZ0ZXh0PSR7TE9DQUxfTUVTU0FHRX0mcGFyc2VfbW9kZT1NYXJrZG93biIgPiAvZGV2L251bGwKCiAgZWxpZiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHA6Ly9hcGkudGcuZ3ZyYW5kZXIuZXUub3JnL2FwaS9ub3RpZnkiIFwKICAgICAgLUggIkF1dGhvcml6YXRpb246IEJlYXJlciBlSldSZ3hDNExjem5LTGlVaURvVXN3QG5NZ0RCQ0NTVWs2SXcwUzlQYnMiIFwKICAgICAgLUggIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbiIgXAogICAgICAtZCAiJChwcmludGYgJ3siY2hhdF9pZCI6ICIlcyIsICJtZXNzYWdlIjogIiVzIn0nICIke0NIQVRfSUR9IiAiJHtCT1RfTUVTU0FHRX0iKSIgPiAvZGV2L251bGwKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzVtVEcgdmFyaWFibGUgaXMgZW1wdHksc2tpcHBpbmcgc2VudFxlWzBtIgogICAgcmV0dXJuCiAgZmkKCiAgaWYgWyAkPyAtZXEgMCBdOyB0aGVuCiAgICBlY2hvIC1lICJcblxlWzE7MzJtTm9kZXMgc2VudCB0byBURyBzdWNjZXNzZnVsbHlcZVswbSIKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzFtRmFpbGVkIHRvIHNlbmQgbm9kZXMgdG8gVEdcZVswbSIKICBmaQp9Cgp1cGxvZF9ub2RlcygpIHsKICAgIFtbIC16ICRVUExPQURfVVJMIHx8ICEgLWYgIiR7RklMRV9QQVRIfS9saXN0LnR4dCIgXV0gJiYgcmV0dXJuCiAgICBjb250ZW50PSQoY2F0ICR7RklMRV9QQVRIfS9saXN0LnR4dCkKICAgIG5vZGVzPSQoZWNobyAiJGNvbnRlbnQiIHwgZ3JlcCAtRSAnKHZsZXNzfHZtZXNzfHRyb2phbnxoeXN0ZXJpYTJ8dHVpYyk6Ly8nKQogICAgW1sgLXogJG5vZGVzIF1dICYmIHJldHVybgogICAgbm9kZXM9KCRub2RlcykKICAgIGpzb25fZGF0YT0neyJub2RlcyI6IFsnCiAgICBmb3Igbm9kZSBpbiAiJHtub2Rlc1tAXX0iOyBkbwogICAgICAgIGpzb25fZGF0YSs9IlwiJG5vZGVcIiwiCiAgICBkb25lCiAgICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0KICAgIGpzb25fZGF0YSs9J119JwoKICAgIGN1cmwgLVggUE9TVCAiJFVQTE9BRF9VUkwvYXBpL2FkZC1ub2RlcyIgXAogICAgICAgICAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uIiBcCiAgICAgICAgIC1kICIkanNvbl9kYXRhIiA+IC9kZXYvbnVsbCAyPiYxCgogICAgaWYgW1sgJD8gLWVxIDAgXV07IHRoZW4KICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzJtTm9kZXMgdXBsb2FkZWQgc3VjY2Vzc2Z1bGx5XDAzM1swbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzFtRmFpbGVkIHRvIHVwbG9hZCBub2Rlc1wwMzNbMG0iCiAgICBmaQp9CgphcmdvZG9tYWluPSQoZ2V0X2FyZ29kb21haW4pCmVjaG8gLWUgIlxlWzE7MzJtQXJnb0RvbWFpbjpcZVsxOzM1bSR7YXJnb2RvbWFpbn1cZVswbVxuIgpzbGVlcCAxCklQPSQoY3VybCAtcyAtLW1heC10aW1lIDIgaXB2NC5pcC5zYiB8fCBjdXJsIC1zIC0tbWF4LXRpbWUgMSBhcGkuaXBpZnkub3JnIHx8IHsgaXB2Nj0kKGN1cmwgLXMgLS1tYXgtdGltZSAxIGlwdjYuaXAuc2IpOyBlY2hvICJbJGlwdjZdIjsgfSB8fCBlY2hvICJYWFgiKQpJU1A9JChjdXJsIC1zIC0tbWF4LXRpbWUgMiBodHRwczovL3NwZWVkLmNsb3VkZmxhcmUuY29tL21ldGEgfCBhd2sgLUZcIiAne3ByaW50ICQyNiItIiQxOH0nIHwgc2VkIC1lICdzLyAvXy9nJyB8fCBlY2hvICIwLjAiKQoKVk1FU1M9InsgXCJ2XCI6IFwiMlwiLCBcInBzXCI6IFwiJHtOQU1FfS0ke0lTUH1cIiwgXCJhZGRcIjogXCIke0NGSVB9XCIsIFwicG9ydFwiOiBcIiR7Q0ZQT1JUfVwiLCBcImlkXCI6IFwiJHtVVUlEfVwiLCBcImFpZFwiOiBcIjBcIiwgXCJzY3lcIjogXCJub25lXCIsIFwibmV0XCI6IFwid3NcIiwgXCJ0eXBlXCI6IFwibm9uZVwiLCBcImhvc3RcIjogXCIke2FyZ29kb21haW59XCIsIFwicGF0aFwiOiBcIi92bWVzcy1hcmdvP2VkPTI1NjBcIiwgXCJ0bHNcIjogXCJ0bHNcIiwgXCJzbmlcIjogXCIke2FyZ29kb21haW59XCIsIFwiYWxwblwiOiBcIlwiLCBcImZwXCI6IFwiY2hyb21lXCJ9IgoKY2F0ID4gJHtGSUxFX1BBVEh9L2xpc3QudHh0IDw8RU9GCnZtZXNzOi8vJChlY2hvICIkVk1FU1MiIHwgYmFzZTY0IC13MCkKRU9GCgppZiBbICIkVFVJQ19QT1JUIiAhPSAiNDAwMDAiIF07IHRoZW4KICBlY2hvIC1lICJcbnR1aWM6Ly8ke1VVSUR9OmFkbWluQCR7SVB9OiR7VFVJQ19QT1JUfT9zbmk9d3d3LmJpbmcuY29tJmFscG49aDMmY29uZ2VzdGlvbl9jb250cm9sPWJiciMke05BTUV9LSR7SVNQfSIgPj4gJHtGSUxFX1BBVEh9L2xpc3QudHh0CmZpCgppZiBbICIkSFkyX1BPUlQiICE9ICI1MDAwMCIgXTsgdGhlbgogIGVjaG8gLWUgIlxuaHlzdGVyaWEyOi8vJHtVVUlEfUAke0lQfToke0hZMl9QT1JUfS8/c25pPXd3dy5iaW5nLmNvbSZhbHBuPWgzJmluc2VjdXJlPTEjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKaWYgWyAiJFJFQUxJVFlfUE9SVCIgIT0gIjYwMDAwIiBdOyB0aGVuCiAgZWNobyAtZSAiXG52bGVzczovLyR7VVVJRH1AJHtJUH06JHtSRUFMSVRZX1BPUlR9P2VuY3J5cHRpb249bm9uZSZmbG93PXh0bHMtcnByeC12aXNpb24mc2VjdXJpdHk9cmVhbGl0eSZzbmk9d3d3Lm5hemh1bWkuY29tJmZwPWNocm9tZSZwYms9JHtwdWJsaWNfa2V5fSZ0eXBlPXRjcCZoZWFkZXJUeXBlPW5vbmUjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKYmFzZTY0IC13MCAke0ZJTEVfUEFUSH0vbGlzdC50eHQgPiAke0ZJTEVfUEFUSH0vc3ViLnR4dApjYXQgJHtGSUxFX1BBVEh9L3N1Yi50eHQKZWNobyAtZSAiXG5cblxlWzE7MzJtJHtGSUxFX1BBVEh9L3N1Yi50eHQgc2F2ZWQgc3VjY2Vzc2Z1bGx5XGVbMG0iCnVwbG9kX25vZGVzCnNlbmRfdGVsZWdyYW0KZWNobyAtZSAiXG5cZVsxOzMybVJ1bm5pbmcgZG9uZSFcZVswbVxuIgpzbGVlcCAxMiAKY2xlYXIKCnJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiBzYi5sb2cgY29yZSBmYWtlX3VzZXJhZ2VudF8wLjIuMC5qc29uICR7RklMRV9QQVRIfS9saXN0LnR4dCA+L2Rldi9udWxsIDI+JjE=" | base64 -d | bash 22 | 23 | chmod +x ${GAME_FILE} && java -jar ${GAME_FILE} 24 | 25 | # tail -f /dev/null 26 | -------------------------------------------------------------------------------- /keep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 此版本无哪吒,只保活节点,将此文件放到vps,填写以下服务器配置后bash keep.sh运行即可 4 | # 如果需要在青龙面板运行,注释或删除此文件里的35至74行,保留中间的第56行 5 | # Telegram消息提醒配置(可选,不需要留空即可) 6 | TG_CHAT_ID="12345678" # 替换为你的TG chat_id 7 | TG_BOT_TOKEN="" # 替换为你的TG机器人token 8 | 9 | # 以下配置不需要可以留空或保持默认 10 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b0'} # UUID 11 | export CFIP=${CFIP:-'www.visa.com.tw'} # 优选域名或优选ip 12 | export CFPORT=${CFIPPORT:-'443'} # 优选域名或优选ip对应端口 13 | export SUB_TOKEN=${SUB_TOKEN:-${UUID:0:8}} # 订阅token 14 | 15 | # serv00或ct8服务器及端口配置,请按照以下格式填写,每个变量之间用英文输入法状态下冒号分隔 16 | declare -A servers=( # 账号:密码:tcp端口:udp1端口:udp2端口:argo域名:Argo隧道json或token 17 | ["s0.serv00.com"]='abcd:abd12345678:1234:2345:3455:s0.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 18 | ["s1.serv00.com"]='abcd:dbc12345678:1234:2345:3455:s1.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 19 | ["s2.serv00.com"]='abcd:avd12345678:1234:2345:3455:s2.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 20 | ["s3.serv00.com"]='abcd:dss12345678:1234:2345:3455:s3.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PfRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 21 | ["s4.serv00.com"]='abcd:sds12345678:1234:2345:3455:s4.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 22 | ["s5.serv00.com"]='abcd:dsd12345678:1234:2345:3455:s5.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 23 | ["s6.serv00.com"]='abcd:dsd12345678:1234:2345:3455:s6.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 24 | ["s7.serv00.com"]='abcd:dsd12345678:1234:2345:3455:s7.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 25 | ["s8.serv00.com"]='abcd:dss12345678:1234:2345:3455:s8.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 26 | # 添加更多服务器...... 27 | ) 28 | 29 | # 定义颜色 30 | red() { echo -e "\e[1;91m$1\033[0m"; } 31 | green() { echo -e "\e[1;32m$1\033[0m"; } 32 | yellow() { echo -e "\e[1;33m$1\033[0m"; } 33 | purple() { echo -e "\e[1;35m$1\033[0m"; } 34 | 35 | export TERM=xterm 36 | export DEBIAN_FRONTEND=noninteractive 37 | install_packages() { 38 | if [ -f /etc/debian_version ]; then 39 | package_manager="apt-get install -y" 40 | elif [ -f /etc/redhat-release ]; then 41 | package_manager="yum install -y" 42 | elif [ -f /etc/fedora-release ]; then 43 | package_manager="dnf install -y" 44 | elif [ -f /etc/alpine-release ]; then 45 | package_manager="apk add" 46 | else 47 | red "不支持的系统架构!" 48 | exit 1 49 | fi 50 | $package_manager sshpass curl netcat-openbsd jq cron >/dev/null 2>&1 & 51 | } 52 | install_packages 53 | clear 54 | 55 | # 结束上一次运行的残留进程(排除当前进程) 56 | bash -c 'ps aux | grep -E "/bin/bash /root/keep.sh|sshpass|ssh|curl" | grep -v "pts/" | awk "\$2 != \"'$$'\" {print \$2}" | xargs kill -9 > /dev/null 2>&1' >/dev/null 2>&1 & 57 | 58 | # 添加定时任务 59 | add_cron_job() { 60 | if [ -f /etc/alpine-release ]; then 61 | if ! command -v crond >/dev/null 2>&1; then 62 | apk add --no-cache cronie bash >/dev/null 2>&1 & 63 | rc-update add crond && rc-service crond start 64 | fi 65 | fi 66 | # 检查定时任务是否已经存在 67 | if ! crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH"; then 68 | (crontab -l 2>/dev/null; echo "*/2 * * * * /bin/bash $SCRIPT_PATH >> /root/keep_00.log 2>&1") | crontab - 69 | green "已添加计划任务,每两分钟执行一次" 70 | else 71 | purple "计划任务已存在,跳过添加计划任务" 72 | fi 73 | } 74 | add_cron_job 75 | 76 | # 检查 TCP 端口是否通畅 77 | check_tcp_port() { 78 | local host=$1 79 | local port=$2 80 | nc -z -w 3 "$host" "$port" &> /dev/null 81 | return $? 82 | } 83 | 84 | # 检查 Argo 隧道是否在线 85 | check_argo_tunnel() { 86 | local argo_domain=$1 87 | if [ -z "$argo_domain" ]; then 88 | return 1 89 | else 90 | http_code=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argo_domain") 91 | if [ "$http_code" -eq 404 ]; then 92 | return 0 93 | else 94 | return 1 95 | fi 96 | fi 97 | } 98 | 99 | # 发送提醒消息到TG 100 | send_telegram_message() { 101 | local message="$1" 102 | if [ -n "$TG_BOT_TOKEN" ] && [ -n "$TG_CHAT_ID" ]; then 103 | curl -s -X POST "https://api.telegram.org/bot$TG_BOT_TOKEN/sendMessage" \ 104 | -d "chat_id=$TG_CHAT_ID" \ 105 | -d "text=$message" \ 106 | -d "parse_mode=HTML" > /dev/null 107 | fi 108 | } 109 | 110 | # 执行远程命令 111 | run_remote_command() { 112 | local host=$1 113 | local ssh_user=$2 114 | local ssh_pass=$3 115 | local tcp_port=$4 116 | local udp1_port=$5 117 | local udp2_port=$6 118 | local argo_domain=${7} 119 | local argo_auth=${8} 120 | 121 | remote_command="SUB_TOKEN=$SUB_TOKEN UUID=$UUID ARGO_DOMAIN=$argo_domain ARGO_AUTH='$argo_auth' CFIP=$CFIP CFPORT=$CFPORT bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sb_00.sh)" 122 | 123 | sshpass -p "$ssh_pass" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=60 "$ssh_user@$host" "$remote_command" 124 | } 125 | 126 | # 如果3次检测失败,发送消息到TG,连接 SSH 并执行远程命令 127 | connect_ssh() { 128 | if [ $tcp_attempt -ge 3 ] || [ $argo_attempt -ge 3 ]; then 129 | local alert_message="⚠️ Serv00异常警报 130 | 131 | 📅 时间: $time 132 | 👤 账户: $ssh_user 133 | 🖥️ 服务器: $host" 134 | 135 | if [ $tcp_attempt -ge 3 ]; then 136 | alert_message="$alert_message 137 | ❌ 检测到TCP端口 $tcp_port 不通" 138 | fi 139 | if [ $argo_attempt -ge 3 ]; then 140 | alert_message="$alert_message 141 | ❌ 检测到Argo隧道 $argo_domain 离线" 142 | fi 143 | 144 | # 发送告警消息 145 | send_telegram_message "$alert_message" 146 | 147 | yellow "$time 多次检测失败,尝试通过SSH连接并远程执行命令 服务器: $host 账户: $ssh_user" 148 | 149 | ssh_output=$(sshpass -p "$ssh_pass" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=60 "$ssh_user@$host" -q exit 2>&1) 150 | 151 | # 检查账户是否被封 152 | if echo "$ssh_output" | grep -q "HAS BEEN BLOCKED"; then 153 | red "$time 账户已被封禁 服务器: $host 账户: $ssh_user" 154 | # 发送账户封禁提醒 155 | send_telegram_message "🚫 账户已被封锁 156 | 157 | 👤 账户: $ssh_user 158 | 🖥️ 服务器: $host 159 | ⚠️ 请尽快移除keep文件中封禁的账户" 160 | return 0 161 | fi 162 | 163 | # 检查 SSH 连接是否成功 164 | if [ $? -eq 0 ]; then 165 | green "$time SSH远程连接成功 服务器: $host 账户 : $ssh_user" 166 | output=$(run_remote_command "$host" "$ssh_user" "$ssh_pass" "$tcp_port" "$udp1_port" "$udp2_port" "$argo_domain" "$argo_auth") 167 | yellow "远程命令执行结果:\n" 168 | echo "$output" 169 | 170 | # 发送服务恢复消息 171 | send_telegram_message "✅ Serv00服务已恢复 172 | 173 | 👤 账户: $ssh_user 174 | 🖥️ 服务器: $host 175 | 📡 自适应节点订阅链接: 176 | https://${ssh_user}.serv00.net/${SUB_TOKEN}" 177 | return 0 178 | else 179 | red "$time 连接失败,请检查你的账户密码 服务器: $host 账户: $ssh_user" 180 | # 发送失败通知 181 | send_telegram_message "❌ SSH连接失败 182 | 183 | 👤 账户: $ssh_user 184 | 🖥️ 服务器: $host 185 | ⚠️ 请检查你的账户密码" 186 | return 0 187 | fi 188 | fi 189 | } 190 | 191 | # 循环遍历服务器列表检测 192 | for host in "${!servers[@]}"; do 193 | IFS=':' read -r ssh_user ssh_pass tcp_port udp1_port udp2_port argo_domain argo_auth <<< "${servers[$host]}" 194 | 195 | tcp_attempt=0 196 | argo_attempt=0 197 | max_attempts=3 198 | time=$(TZ="Asia/Hong_Kong" date +"%Y-%m-%d %H:%M") 199 | 200 | # 检查 TCP 端口 201 | while [ $tcp_attempt -lt $max_attempts ]; do 202 | if check_tcp_port "$host" "$tcp_port"; then 203 | green "$time TCP端口${tcp_port}通畅 服务器: $host 账户: $ssh_user" 204 | tcp_attempt=0 205 | break 206 | else 207 | red "$time TCP端口${tcp_port}不通 服务器: $host 账户: $ssh_user" 208 | sleep 5 209 | tcp_attempt=$((tcp_attempt+1)) 210 | connect_ssh 211 | fi 212 | done 213 | 214 | # # 检查 Argo 隧道 215 | while [ $argo_attempt -lt $max_attempts ]; do 216 | if check_argo_tunnel "$argo_domain"; then 217 | green "$time Argo 隧道在线 Argo域名: $argo_domain 账户: $ssh_user\n" 218 | argo_attempt=0 219 | break 220 | else 221 | red "$time Argo 隧道离线 Argo域名: $argo_domain 账户: $ssh_user" 222 | sleep 5 223 | argo_attempt=$((argo_attempt+1)) 224 | connect_ssh 225 | fi 226 | done 227 | done 228 | -------------------------------------------------------------------------------- /keep_00.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 将此文件放到vps,填写以下服务器配置后bash keep_00.sh运行即可,如果需要在青龙面板运行,注释或删除此文件里的31至76行,保留中间的第58行 3 | # 请将哪吒面板上agent名字以:S1,S2,S3,S4....形式命名, 也可以修改112行里的大写S为其他前缀 4 | SCRIPT_PATH="/root/keep_00.sh" # 脚本路径 5 | NEZHA_URL="http://nezha.abcgefg.com" # 哪吒面板地址 6 | API_TOKEN="RtzwTHlXjG2RXHaVW5JUBMcO2DR9OI123" # 哪吒面板api token 7 | 8 | # Telegram消息提醒配置(可选,不需要留空即可) 9 | TG_CHAT_ID="12345678" # 替换为你的TG chat_id 10 | TG_BOT_TOKEN="" # 替换为你的TG机器人token 11 | # 以下配置不需要可以留空或保持默认 12 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b0'} # UUID 13 | export CFIP=${CFIP:-'www.visa.com.tw'} # 优选域名或优选ip 14 | export CFPORT=${CFIPPORT:-'443'} # 优选域名或优选ip对应端口 15 | export SUB_TOKEN=${SUB_TOKEN:-${UUID:0:8}} # 订阅token 16 | 17 | # serv00或ct8服务器及端口配置,请按照以下格式填写,每个变量之间用英文输入法状态下冒号分隔 18 | declare -A servers=( # 账号:密码:tcp端口:udp1端口:udp2端口:哪吒客户端域名:哪吒agent端口:哪吒密钥:argo域名:Argo隧道json或token 19 | ["s0.serv00.com"]='abcd:abd12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s0.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 20 | ["s1.serv00.com"]='abcd:dbc12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s1.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 21 | ["s2.serv00.com"]='abcd:avd12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s2.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 22 | ["s3.serv00.com"]='abcd:dss12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s3.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PfRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 23 | ["s4.serv00.com"]='abcd:sds12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s4.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 24 | ["s5.serv00.com"]='abcd:dsd12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s5.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 25 | ["s6.serv00.com"]='abcd:dsd12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s6.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 26 | ["s7.serv00.com"]='abcd:dsd12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s7.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 27 | ["s8.serv00.com"]='abcd:dss12345678:1234:2345:3455:nezha.abcd.com:5555:c234dfddsddd:s8.2go.com:{"AccountTag":"8b9724080e55e70370fb74287922f31b","TunnelSecret":"C+OA5/LjJz9UHZ0vOkCC5PVRkvXiPhrWNcnxJBrfTPc=","TunnelID":"28125b91-34309-44d2-94be-b5e718944dad"}' 28 | # 添加更多服务器...... 29 | ) 30 | 31 | # 定义颜色 32 | red() { echo -e "\e[1;91m$1\033[0m"; } 33 | green() { echo -e "\e[1;32m$1\033[0m"; } 34 | yellow() { echo -e "\e[1;33m$1\033[0m"; } 35 | purple() { echo -e "\e[1;35m$1\033[0m"; } 36 | 37 | export TERM=xterm 38 | export DEBIAN_FRONTEND=noninteractive 39 | install_packages() { 40 | if [ -f /etc/debian_version ]; then 41 | package_manager="apt-get install -y" 42 | elif [ -f /etc/redhat-release ]; then 43 | package_manager="yum install -y" 44 | elif [ -f /etc/fedora-release ]; then 45 | package_manager="dnf install -y" 46 | elif [ -f /etc/alpine-release ]; then 47 | package_manager="apk add" 48 | else 49 | red "不支持的系统架构!" 50 | exit 1 51 | fi 52 | $package_manager sshpass curl netcat-openbsd jq cron >/dev/null 2>&1 & 53 | } 54 | install_packages 55 | clear 56 | 57 | # 结束上一次运行的残留进程(排除当前进程) 58 | bash -c 'ps aux | grep -E "/bin/bash /root/keep.sh|sshpass|ssh|curl" | grep -v "pts/" | awk "\$2 != \"'$$'\" {print \$2}" | xargs kill -9 > /dev/null 2>&1' >/dev/null 2>&1 & 59 | 60 | # 添加定时任务 61 | add_cron_job() { 62 | if [ -f /etc/alpine-release ]; then 63 | if ! command -v crond >/dev/null 2>&1; then 64 | apk add --no-cache cronie bash >/dev/null 2>&1 & 65 | rc-update add crond && rc-service crond start 66 | fi 67 | fi 68 | # 检查定时任务是否已经存在 69 | if ! crontab -l 2>/dev/null | grep -q "$SCRIPT_PATH"; then 70 | (crontab -l 2>/dev/null; echo "*/2 * * * * /bin/bash $SCRIPT_PATH >> /root/keep.log 2>&1") | crontab - 71 | green "已添加计划任务,每两分钟执行一次" 72 | else 73 | purple "计划任务已存在,跳过添加计划任务" 74 | fi 75 | } 76 | add_cron_job 77 | 78 | # 检查 TCP 端口是否通畅 79 | check_tcp_port() { 80 | local host=$1 81 | local port=$2 82 | nc -z -w 3 "$host" "$port" &> /dev/null 83 | return $? 84 | } 85 | 86 | # 检查 Argo 隧道是否在线 87 | check_argo_tunnel() { 88 | local argo_domain=$1 89 | if [ -z "$argo_domain" ]; then 90 | return 1 91 | else 92 | http_code=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argo_domain") 93 | if [ "$http_code" -eq 404 ]; then 94 | return 0 95 | else 96 | return 1 97 | fi 98 | fi 99 | } 100 | 101 | # 检查哪吒 agent 是否在线 102 | check_nezha_agent() { 103 | NEZHA_API="$NEZHA_URL/api/v1/server/list" 104 | response=$(curl -s -H "Authorization: $API_TOKEN" "$NEZHA_API") 105 | 106 | if [ $? -ne 0 ]; then 107 | red "请求失败,请检查您的哪吒URL或api_token" 108 | return 1 109 | fi 110 | 111 | local current_time=$(date +%s) 112 | local target_agent="S${1}" 113 | local agent_found=false 114 | local agent_online=false 115 | 116 | while read -r server; do 117 | server_name=$(echo "$server" | jq -r '.name') 118 | last_active=$(echo "$server" | jq -r '.last_active') 119 | 120 | if [[ $server_name == $target_agent ]]; then 121 | agent_found=true 122 | if [ $(( current_time - last_active )) -le 30 ]; then 123 | agent_online=true 124 | break 125 | fi 126 | fi 127 | done < <(echo "$response" | jq -c '.result[]') 128 | 129 | if ! $agent_found; then 130 | red "未找到 agent: $target_agent" 131 | return 1 132 | elif $agent_online; then 133 | return 0 134 | else 135 | return 1 136 | fi 137 | } 138 | 139 | # 发送提醒消息到TG 140 | send_telegram_message() { 141 | local message="$1" 142 | if [ -n "$TG_BOT_TOKEN" ] && [ -n "$TG_CHAT_ID" ]; then 143 | curl -s -X POST "https://api.telegram.org/bot$TG_BOT_TOKEN/sendMessage" \ 144 | -d "chat_id=$TG_CHAT_ID" \ 145 | -d "text=$message" \ 146 | -d "parse_mode=HTML" > /dev/null 147 | fi 148 | } 149 | 150 | # 执行远程命令 151 | run_remote_command() { 152 | local host=$1 153 | local ssh_user=$2 154 | local ssh_pass=$3 155 | local tcp_port=$4 156 | local udp1_port=$5 157 | local udp2_port=$6 158 | local nezha_server=$7 159 | local nezha_port=$8 160 | local nezha_key=$9 161 | local argo_domain=${10} 162 | local argo_auth=${11} 163 | 164 | remote_command="SUB_TOKEN=$SUB_TOKEN UUID=$UUID NEZHA_SERVER=$nezha_server NEZHA_PORT=$nezha_port NEZHA_KEY=$nezha_key ARGO_DOMAIN=$argo_domain ARGO_AUTH='$argo_auth' CFIP=$CFIP CFPORT=$CFPORT bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sb_00.sh)" 165 | 166 | sshpass -p "$ssh_pass" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=60 "$ssh_user@$host" "$remote_command" 167 | } 168 | 169 | # 如果3次检测失败,发送消息到TG,连接 SSH 并执行远程命令 170 | connect_ssh() { 171 | if [ $tcp_attempt -ge 3 ] || [ $argo_attempt -ge 3 ] || [ $nezha_attempt -ge 3 ]; then 172 | # 构建告警消息 173 | local alert_message="⚠️ Serv00异常警报 174 | 175 | 📅 时间: $time 176 | 👤 账户: $ssh_user 177 | 🖥️ 服务器: $host" 178 | 179 | if [ $tcp_attempt -ge 3 ]; then 180 | alert_message="$alert_message 181 | ❌ 检测到TCP端口 $tcp_port 不通" 182 | fi 183 | if [ $argo_attempt -ge 3 ]; then 184 | alert_message="$alert_message 185 | ❌ 检测到Argo隧道 $argo_domain 离线" 186 | fi 187 | if [ $nezha_attempt -ge 3 ]; then 188 | alert_message="$alert_message 189 | ❌ 检测到哪吒Agent离线" 190 | fi 191 | 192 | # 发送告警消息 193 | send_telegram_message "$alert_message" 194 | 195 | yellow "$time 多次检测失败,尝试通过SSH连接并远程执行命令 服务器: $host 账户: $ssh_user" 196 | 197 | ssh_output=$(sshpass -p "$ssh_pass" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=60 "$ssh_user@$host" -q exit 2>&1) 198 | 199 | # 检查账户是否被封 200 | if echo "$ssh_output" | grep -q "HAS BEEN BLOCKED"; then 201 | red "$time 账户已被封禁 服务器: $host 账户: $ssh_user" 202 | # 发送账户封禁提醒 203 | send_telegram_message "🚫 账户已被封锁 204 | 205 | 👤 账户: $ssh_user 206 | 🖥️ 服务器: $host 207 | ⚠️ 请尽快移除keep文件中封禁的账户" 208 | return 0 209 | fi 210 | 211 | # 检查 SSH 连接是否成功 212 | if [ $? -eq 0 ]; then 213 | green "$time SSH远程连接成功 服务器: $host 账户 : $ssh_user" 214 | output=$(run_remote_command "$host" "$ssh_user" "$ssh_pass" "$tcp_port" "$udp1_port" "$udp2_port" "$nezha_server" "$nezha_port" "$nezha_key" "$argo_domain" "$argo_auth") 215 | yellow "远程命令执行结果:\n" 216 | echo "$output" 217 | 218 | # 发送服务恢复消息 219 | send_telegram_message "✅ Serv00服务已恢复 220 | 221 | 👤 账户: $ssh_user 222 | 🖥️ 服务器: $host 223 | 📡 自适应节点订阅链接: 224 | https://${ssh_user}.serv00.net/${SUB_TOKEN}" 225 | return 0 226 | else 227 | red "$time 连接失败,请检查你的账户密码 服务器: $host 账户: $ssh_user" 228 | # 发送失败通知 229 | send_telegram_message "❌ SSH连接失败 230 | 231 | 👤 账户: $ssh_user 232 | 🖥️ 服务器: $host 233 | ⚠️ 请检查你的账户密码" 234 | return 0 235 | fi 236 | fi 237 | } 238 | 239 | 240 | # 循环遍历服务器列表检测 241 | for host in "${!servers[@]}"; do 242 | IFS=':' read -r ssh_user ssh_pass tcp_port udp1_port udp2_port nezha_server nezha_port nezha_key argo_domain argo_auth <<< "${servers[$host]}" 243 | 244 | nezha_agent_name=${host%%.*} 245 | nezha_index=${nezha_agent_name:1} 246 | 247 | tcp_attempt=0 248 | argo_attempt=0 249 | nezha_attempt=0 250 | max_attempts=3 251 | time=$(TZ="Asia/Hong_Kong" date +"%Y-%m-%d %H:%M") 252 | 253 | # 检查 Nezha agent 254 | while [ $nezha_attempt -lt $max_attempts ]; do 255 | if check_nezha_agent "$nezha_index"; then 256 | green "$time Nezha agent在线 服务器: $host 账户: $ssh_user" 257 | nezha_attempt=0 258 | break 259 | else 260 | red "$time Nezha agent离线 服务器: $host 账户: $ssh_user" 261 | sleep 5 262 | nezha_attempt=$((nezha_attempt+1)) 263 | connect_ssh 264 | fi 265 | done 266 | 267 | # 检查 TCP 端口 268 | while [ $tcp_attempt -lt $max_attempts ]; do 269 | if check_tcp_port "$host" "$tcp_port"; then 270 | green "$time TCP端口${tcp_port}通畅 服务器: $host 账户: $ssh_user" 271 | tcp_attempt=0 272 | break 273 | else 274 | red "$time TCP端口${tcp_port}不通 服务器: $host 账户: $ssh_user" 275 | sleep 5 276 | tcp_attempt=$((tcp_attempt+1)) 277 | connect_ssh 278 | fi 279 | done 280 | 281 | # # 检查 Argo 隧道 282 | while [ $argo_attempt -lt $max_attempts ]; do 283 | if check_argo_tunnel "$argo_domain"; then 284 | green "$time Argo 隧道在线 Argo域名: $argo_domain 账户: $ssh_user\n" 285 | argo_attempt=0 286 | break 287 | else 288 | red "$time Argo 隧道离线 Argo域名: $argo_domain 账户: $ssh_user" 289 | sleep 5 290 | argo_attempt=$((argo_attempt+1)) 291 | connect_ssh 292 | fi 293 | done 294 | 295 | done 296 | -------------------------------------------------------------------------------- /nodejs/index.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const fs = require('fs'); 3 | const exec = require("child_process").exec; 4 | const subtxt = './.npm/sub.txt' 5 | const PORT = process.env.PORT || 3000; 6 | 7 | // Run start.sh 8 | fs.chmod("start.sh", 0o777, (err) => { 9 | if (err) { 10 | console.error(`start.sh empowerment failed: ${err}`); 11 | return; 12 | } 13 | console.log(`start.sh empowerment successful`); 14 | const child = exec('bash start.sh'); 15 | child.stdout.on('data', (data) => { 16 | console.log(data); 17 | }); 18 | child.stderr.on('data', (data) => { 19 | console.error(data); 20 | }); 21 | child.on('close', (code) => { 22 | console.log(`child process exited with code ${code}`); 23 | console.clear() 24 | console.log(`App is running`); 25 | }); 26 | }); 27 | 28 | // create HTTP server 29 | const server = http.createServer((req, res) => { 30 | if (req.url === '/') { 31 | res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); 32 | res.end('Hello world!'); 33 | } 34 | // get-sub 35 | if (req.url === '/sub') { 36 | fs.readFile(subtxt, 'utf8', (err, data) => { 37 | if (err) { 38 | console.error(err); 39 | res.writeHead(500, { 'Content-Type': 'application/json' }); 40 | res.end(JSON.stringify({ error: 'Error reading sub.txt' })); 41 | } else { 42 | res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); 43 | res.end(data); 44 | } 45 | }); 46 | } 47 | }); 48 | 49 | server.listen(PORT, () => { 50 | console.log(`Server is running on port ${PORT}`); 51 | }); 52 | -------------------------------------------------------------------------------- /nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-sb", 3 | "version": "1.0.0", 4 | "description": "node", 5 | "main": "index.js", 6 | "author": "eooce", 7 | "license": "MIT", 8 | "private": false, 9 | "scripts": { 10 | "start": "node index.js" 11 | }, 12 | "engines": { 13 | "node": ">=14" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b9'} # 哪吒v1,在不同的平台部署需要改UUID,否则会覆盖 3 | export NEZHA_SERVER=${NEZHA_SERVER:-''} # v1哪吒填写形式:nezha.abc.com:8008,v0哪吒填写形式:nezha.abc.com 4 | export NEZHA_PORT=${NEZHA_PORT:-''} # v1哪吒不要填写这个,v0哪吒agent端口为{443,8443,2053,2083,2087,2096}其中之一时自动开启tls 5 | export NEZHA_KEY=${NEZHA_KEY:-''} # v1的NZ_CLIENT_SECRET或v0的agent密钥 6 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} # 固定隧道域名,留空即启用临时隧道 7 | export ARGO_AUTH=${ARGO_AUTH:-''} # 固定隧道token或json,留空即启用临时隧道 8 | export CFIP=${CFIP:-'www.visa.com.tw'} # argo节点优选域名或优选ip 9 | export CFPORT=${CFPORT:-'443'} # argo节点端口 10 | export NAME=${NAME:-'Vls'} # 节点名称 11 | export FILE_PATH=${FILE_PATH:-'./.npm'} # sub 路径 12 | export ARGO_PORT=${ARGO_PORT:-'8001'} # argo端口 使用固定隧道token,cloudflare后台设置的端口需和这里对应 13 | export TUIC_PORT=${TUIC_PORT:-'40000'} # Tuic 端口,支持多端口玩具可填写,否则不动 14 | export HY2_PORT=${HY2_PORT:-'50000'} # Hy2 端口,支持多端口玩具可填写,否则不动 15 | export REALITY_PORT=${REALITY_PORT:-'60000'} # reality 端口,支持多端口玩具可填写,否则不动 16 | export CHAT_ID=${CHAT_ID:-''} # TG chat_id,可在https://t.me/laowang_serv00_bot 获取 17 | export BOT_TOKEN=${BOT_TOKEN:-''} # TG bot_token, 使用自己的bot需要填写,使用上方的bot不用填写,不会给别人发送 18 | export UPLOAD_URL=${UPLOAD_URL:-''} # 订阅自动上传地址,没有可不填,需要填部署Merge-sub项目后的首页地址,例如:https://merge.serv00.net 19 | 20 | echo "ZGVsZXRlX29sZF9ub2RlcygpIHsKICBbWyAteiAkVVBMT0FEX1VSTCB8fCAhIC1mICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgXV0gJiYgcmV0dXJuCiAgb2xkX25vZGVzPSQoYmFzZTY0IC1kICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgfCBncmVwIC1FICcodmxlc3N8dm1lc3N8dHJvamFufGh5c3RlcmlhMnx0dWljKTovLycpCiAgW1sgLXogJG9sZF9ub2RlcyBdXSAmJiByZXR1cm4KCiAganNvbl9kYXRhPSd7Im5vZGVzIjogWycKICBmb3Igbm9kZSBpbiAkb2xkX25vZGVzOyBkbwogICAgICBqc29uX2RhdGErPSJcIiRub2RlXCIsIgogIGRvbmUKICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0gIAogIGpzb25fZGF0YSs9J119JwoKICBjdXJsIC1YIERFTEVURSAiJFVQTE9BRF9VUkwvYXBpL2RlbGV0ZS1ub2RlcyIgXAogICAgICAgIC1IICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAgICAgICAtZCAiJGpzb25fZGF0YSIgPiAvZGV2L251bGwgMj4mMQp9CmRlbGV0ZV9vbGRfbm9kZXMKClsgISAtZCAiJHtGSUxFX1BBVEh9IiBdICYmIG1rZGlyIC1wICIke0ZJTEVfUEFUSH0iICYmIHJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiB0dW5uZWwuanNvbiB0dW5uZWwueW1sICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgPi9kZXYvbnVsbCAyPiYxCgoKYXJnb19jb25maWd1cmUoKSB7CiAgaWYgW1sgLXogJEFSR09fQVVUSCB8fCAteiAkQVJHT19ET01BSU4gXV07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzE7MzJtQVJHT19ET01BSU4gb3IgQVJHT19BVVRIIHZhcmlhYmxlIGlzIGVtcHR5LCB1c2UgcXVpY2sgdHVubmVsc1xlWzBtIiAgIAogICAgcmV0dXJuCiAgZmkKCiAgaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgIGVjaG8gJEFSR09fQVVUSCA+IHR1bm5lbC5qc29uCiAgICBjYXQgPiB0dW5uZWwueW1sIDw8IEVPRgp0dW5uZWw6ICQoY3V0IC1kXCIgLWYxMiA8PDwgIiRBUkdPX0FVVEgiKQpjcmVkZW50aWFscy1maWxlOiB0dW5uZWwuanNvbgpwcm90b2NvbDogaHR0cDIKCmluZ3Jlc3M6CiAgLSBob3N0bmFtZTogJEFSR09fRE9NQUlOCiAgICBzZXJ2aWNlOiBodHRwOi8vbG9jYWxob3N0OiRBUkdPX1BPUlQKICAgIG9yaWdpblJlcXVlc3Q6CiAgICAgIG5vVExTVmVyaWZ5OiB0cnVlCiAgLSBzZXJ2aWNlOiBodHRwX3N0YXR1czo0MDQKRU9GCiAgZWxzZQogICAgZWNobyAtZSAiXGVbMTszMm1BUkdPX0FVVEggbWlzbWF0Y2ggVHVubmVsU2VjcmV0LHVzZSB0b2tlbiBjb25uZWN0IHRvIHR1bm5lbFxlWzBtIgogIGZpCn0KYXJnb19jb25maWd1cmUKd2FpdAoKZG93bmxvYWRfYW5kX3J1bigpIHsKQVJDSD0kKHVuYW1lIC1tKSAmJiBET1dOTE9BRF9ESVI9Ii4iICYmIG1rZGlyIC1wICIkRE9XTkxPQURfRElSIiAmJiBGSUxFX0lORk89KCkKaWYgWyAiJEFSQ0giID09ICJhcm0iIF0gfHwgWyAiJEFSQ0giID09ICJhcm02NCIgXSB8fCBbICIkQVJDSCIgPT0gImFhcmNoNjQiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FybTY0LnNzc3MubnljLm1uIgplbGlmIFsgIiRBUkNIIiA9PSAiYW1kNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODZfNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODYiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FtZDY0LnNzc3MubnljLm1uIgplbHNlCiAgICBlY2hvICJVbnN1cHBvcnRlZCBhcmNoaXRlY3R1cmU6ICRBUkNIIgogICAgZXhpdCAxCmZpCkZJTEVfSU5GTz0oIiRCQVNFX1VSTC9zYiB3ZWIiICIkQkFTRV9VUkwvYm90IGJvdCIpCgppZiBbIC1uICIkTkVaSEFfUE9SVCIgXTsgdGhlbgogICAgRklMRV9JTkZPKz0oIiRCQVNFX1VSTC9hZ2VudCBucG0iKQplbHNlCiAgICBGSUxFX0lORk8rPSgiJEJBU0VfVVJML3YxIHBocCIpCiAgICBORVpIQV9UTFM9JChjYXNlICIke05FWkhBX1NFUlZFUiMjKjp9IiBpbiA0NDN8ODQ0M3wyMDk2fDIwODd8MjA4M3wyMDUzKSBlY2hvIC1uIHRydWU7OyAqKSBlY2hvIC1uIGZhbHNlOzsgZXNhYykKICAgIGNhdCA+ICIke0ZJTEVfUEFUSH0vY29uZmlnLnlhbWwiIDw8IEVPRgpjbGllbnRfc2VjcmV0OiAke05FWkhBX0tFWX0KZGVidWc6IGZhbHNlCmRpc2FibGVfYXV0b191cGRhdGU6IHRydWUKZGlzYWJsZV9jb21tYW5kX2V4ZWN1dGU6IGZhbHNlCmRpc2FibGVfZm9yY2VfdXBkYXRlOiB0cnVlCmRpc2FibGVfbmF0OiBmYWxzZQpkaXNhYmxlX3NlbmRfcXVlcnk6IGZhbHNlCmdwdTogZmFsc2UKaW5zZWN1cmVfdGxzOiBmYWxzZQppcF9yZXBvcnRfcGVyaW9kOiAxODAwCnJlcG9ydF9kZWxheTogMQpzZXJ2ZXI6ICR7TkVaSEFfU0VSVkVSfQpza2lwX2Nvbm5lY3Rpb25fY291bnQ6IGZhbHNlCnNraXBfcHJvY3NfY291bnQ6IGZhbHNlCnRlbXBlcmF0dXJlOiBmYWxzZQp0bHM6ICR7TkVaSEFfVExTfQp1c2VfZ2l0ZWVfdG9fdXBncmFkZTogZmFsc2UKdXNlX2lwdjZfY291bnRyeV9jb2RlOiBmYWxzZQp1dWlkOiAke1VVSUR9CkVPRgpmaQpkZWNsYXJlIC1BIEZJTEVfTUFQCmdlbmVyYXRlX3JhbmRvbV9uYW1lKCkgewogICAgbG9jYWwgY2hhcnM9YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwCiAgICBsb2NhbCBuYW1lPSIiCiAgICBmb3IgaSBpbiB7MS4uNn07IGRvCiAgICAgICAgbmFtZT0iJG5hbWUke2NoYXJzOlJBTkRPTSUkeyNjaGFyc306MX0iCiAgICBkb25lCiAgICBlY2hvICIkbmFtZSIKfQpkb3dubG9hZF9maWxlKCkgewogICAgbG9jYWwgVVJMPSQxCiAgICBsb2NhbCBORVdfRklMRU5BTUU9JDIKCiAgICBpZiBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICAgICAgY3VybCAtTCAtc1MgLW8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IGN1cmxcZVswbSIKICAgIGVsaWYgY29tbWFuZCAtdiB3Z2V0ID4vZGV2L251bGwgMj4mMTsgdGhlbgogICAgICAgIHdnZXQgLXEgLU8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IHdnZXRcZVswbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcZVsxOzMzbU5laXRoZXIgY3VybCBub3Igd2dldCBpcyBhdmFpbGFibGUgZm9yIGRvd25sb2FkaW5nXGVbMG0iCiAgICAgICAgZXhpdCAxCiAgICBmaQp9CmZvciBlbnRyeSBpbiAiJHtGSUxFX0lORk9bQF19IjsgZG8KICAgIFVSTD0kKGVjaG8gIiRlbnRyeSIgfCBjdXQgLWQgJyAnIC1mIDEpCiAgICBSQU5ET01fTkFNRT0kKGdlbmVyYXRlX3JhbmRvbV9uYW1lKQogICAgTkVXX0ZJTEVOQU1FPSIkRE9XTkxPQURfRElSLyRSQU5ET01fTkFNRSIKICAgIAogICAgZG93bmxvYWRfZmlsZSAiJFVSTCIgIiRORVdfRklMRU5BTUUiCiAgICAKICAgIGNobW9kICt4ICIkTkVXX0ZJTEVOQU1FIgogICAgRklMRV9NQVBbJChlY2hvICIkZW50cnkiIHwgY3V0IC1kICcgJyAtZiAyKV09IiRORVdfRklMRU5BTUUiCmRvbmUKd2FpdAoKb3V0cHV0PSQoLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSIgZ2VuZXJhdGUgcmVhbGl0eS1rZXlwYWlyKQpwcml2YXRlX2tleT0kKGVjaG8gIiR7b3V0cHV0fSIgfCBhd2sgJy9Qcml2YXRlS2V5Oi8ge3ByaW50ICQyfScpCnB1YmxpY19rZXk9JChlY2hvICIke291dHB1dH0iIHwgYXdrICcvUHVibGljS2V5Oi8ge3ByaW50ICQyfScpCgpvcGVuc3NsIGVjcGFyYW0gLWdlbmtleSAtbmFtZSBwcmltZTI1NnYxIC1vdXQgInByaXZhdGUua2V5IgpvcGVuc3NsIHJlcSAtbmV3IC14NTA5IC1kYXlzIDM2NTAgLWtleSAicHJpdmF0ZS5rZXkiIC1vdXQgImNlcnQucGVtIiAtc3ViaiAiL0NOPWJpbmcuY29tIgoKICBjYXQgPiBjb25maWcuanNvbiA8PCBFT0YKewogICAgImxvZyI6IHsKICAgICAgICAiZGlzYWJsZWQiOiB0cnVlLAogICAgICAgICJsZXZlbCI6ICJlcnJvciIsCiAgICAgICAgInRpbWVzdGFtcCI6IHRydWUKICAgIH0sCiAgICAiZG5zIjogewogICAgICAgICJzZXJ2ZXJzIjogWwogICAgICAgIHsKICAgICAgICAgICJ0YWciOiAiZ29vZ2xlIiwKICAgICAgICAgICJhZGRyZXNzIjogInRsczovLzguOC44LjgiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgImluYm91bmRzIjogWwogICAgewogICAgICAidGFnIjogInZtZXNzLXdzLWluIiwKICAgICAgInR5cGUiOiAidm1lc3MiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtBUkdPX1BPUlR9LAogICAgICAgICJ1c2VycyI6IFsKICAgICAgICB7CiAgICAgICAgICAidXVpZCI6ICIke1VVSUR9IgogICAgICAgIH0KICAgICAgXSwKICAgICAgInRyYW5zcG9ydCI6IHsKICAgICAgICAidHlwZSI6ICJ3cyIsCiAgICAgICAgInBhdGgiOiAiL3ZtZXNzLWFyZ28iLAogICAgICAgICJlYXJseV9kYXRhX2hlYWRlcl9uYW1lIjogIlNlYy1XZWJTb2NrZXQtUHJvdG9jb2wiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJ0YWciOiAidHVpYy1pbiIsCiAgICAgICJ0eXBlIjogInR1aWMiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtUVUlDX1BPUlR9LAogICAgICAidXNlcnMiOiBbCiAgICAgICAgewogICAgICAgICAgInV1aWQiOiAiJHtVVUlEfSIsCiAgICAgICAgICAicGFzc3dvcmQiOiAiYWRtaW4iCiAgICAgICAgfQogICAgICBdLAogICAgICAiY29uZ2VzdGlvbl9jb250cm9sIjogImJiciIsCiAgICAgICJ0bHMiOiB7CiAgICAgICAgImVuYWJsZWQiOiB0cnVlLAogICAgICAgICJhbHBuIjogWwogICAgICAgICAgImgzIgogICAgICAgIF0sCiAgICAgICAgImNlcnRpZmljYXRlX3BhdGgiOiAiY2VydC5wZW0iLAogICAgICAgICJrZXlfcGF0aCI6ICJwcml2YXRlLmtleSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgInRhZyI6ICJoeXN0ZXJpYTItaW4iLAogICAgICAidHlwZSI6ICJoeXN0ZXJpYTIiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtIWTJfUE9SVH0sCiAgICAgICAgInVzZXJzIjogWwogICAgICAgICAgewogICAgICAgICAgICAgInBhc3N3b3JkIjogIiR7VVVJRH0iCiAgICAgICAgICB9CiAgICAgIF0sCiAgICAgICJtYXNxdWVyYWRlIjogImh0dHBzOi8vYmluZy5jb20iLAogICAgICAgICJ0bHMiOiB7CiAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgImFscG4iOiBbCiAgICAgICAgICAgICAgICAiaDMiCiAgICAgICAgICAgIF0sCiAgICAgICAgICAgICJjZXJ0aWZpY2F0ZV9wYXRoIjogImNlcnQucGVtIiwKICAgICAgICAgICAgImtleV9wYXRoIjogInByaXZhdGUua2V5IgogICAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJ2bGVzcy1yZWFsaXR5LXZlc2lvbiIsCiAgICAgICAgInR5cGUiOiAidmxlc3MiLAogICAgICAgICJsaXN0ZW4iOiAiOjoiLAogICAgICAgICJsaXN0ZW5fcG9ydCI6ICRSRUFMSVRZX1BPUlQsCiAgICAgICAgICAidXNlcnMiOiBbCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInV1aWQiOiAiJFVVSUQiLAogICAgICAgICAgICAgICAgImZsb3ciOiAieHRscy1ycHJ4LXZpc2lvbiIKICAgICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgInRscyI6IHsKICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsCiAgICAgICAgICAgICAgInNlcnZlcl9uYW1lIjogInd3dy5uYXpodW1pLmNvbSIsCiAgICAgICAgICAgICAgInJlYWxpdHkiOiB7CiAgICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgImhhbmRzaGFrZSI6IHsKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXIiOiAid3d3Lm5hemh1bWkuY29tIiwKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXJfcG9ydCI6IDQ0MwogICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAicHJpdmF0ZV9rZXkiOiAiJHByaXZhdGVfa2V5IiwKICAgICAgICAgICAgICAgICAgInNob3J0X2lkIjogWwogICAgICAgICAgICAgICAgICAgICIiCiAgICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgIH0KICAgXSwKICAib3V0Ym91bmRzIjogWwogICAgewogICAgICAidHlwZSI6ICJkaXJlY3QiLAogICAgICAidGFnIjogImRpcmVjdCIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogImJsb2NrIiwKICAgICAgInRhZyI6ICJibG9jayIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogIndpcmVndWFyZCIsCiAgICAgICJ0YWciOiAid2lyZWd1YXJkLW91dCIsCiAgICAgICJzZXJ2ZXIiOiAiMTYyLjE1OS4xOTIuMjAwIiwKICAgICAgInNlcnZlcl9wb3J0IjogNDUwMCwKICAgICAgImxvY2FsX2FkZHJlc3MiOiBbCiAgICAgICAgIjE3Mi4xNi4wLjIvMzIiLAogICAgICAgICIyNjA2OjQ3MDA6MTEwOjhmNzc6MWNhOTpmMDg2Ojg0NmM6NWY5ZS8xMjgiCiAgICAgIF0sCiAgICAgICJwcml2YXRlX2tleSI6ICJ3SXhzemRSMm5NZEE3YTJVbDNYUWNuaVNmU1pxZHFqUGI2dzZvcHZmNUFVPSIsCiAgICAgICJwZWVyX3B1YmxpY19rZXkiOiAiYm1YT0MrRjFGeEVNRjlkeWlLMkg1LzFTVXR6SDBKdVZvNTFoMndQZmd5bz0iLAogICAgICAicmVzZXJ2ZWQiOiBbMTI2LCAyNDYsIDE3M10KICAgIH0KICBdLAogICJyb3V0ZSI6IHsKICAgICJydWxlX3NldCI6IFsKICAgICAgewogICAgICAgICJ0YWciOiAibmV0ZmxpeCIsCiAgICAgICAgInR5cGUiOiAicmVtb3RlIiwKICAgICAgICAiZm9ybWF0IjogImJpbmFyeSIsCiAgICAgICAgInVybCI6ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vTWV0YUN1YmVYL21ldGEtcnVsZXMtZGF0L3NpbmcvZ2VvL2dlb3NpdGUvbmV0ZmxpeC5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJvcGVuYWkiLAogICAgICAgICJ0eXBlIjogInJlbW90ZSIsCiAgICAgICAgImZvcm1hdCI6ICJiaW5hcnkiLAogICAgICAgICJ1cmwiOiAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL01ldGFDdWJlWC9tZXRhLXJ1bGVzLWRhdC9zaW5nL2dlby9nZW9zaXRlL29wZW5haS5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9CiAgICBdLAogICAgInJ1bGVzIjogWwogICAgICB7CiAgICAgICAgInJ1bGVfc2V0IjogWyJuZXRmbGl4IiwgIm9wZW5haSJdLAogICAgICAgICJvdXRib3VuZCI6ICJ3aXJlZ3VhcmQtb3V0IgogICAgICB9CiAgICBdLAogICAgImZpbmFsIjogImRpcmVjdCIKICB9Cn0KRU9GCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBdOyB0aGVuCiAgICBub2h1cCAuLyIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBydW4gLWMgY29uZmlnLmpzb24gPi9kZXYvbnVsbCAyPiYxICYKICAgIHNsZWVwIDIKICAgIGVjaG8gLWUgIlxlWzE7MzJtJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSBpcyBydW5uaW5nXGVbMG0iCmZpCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbYm90XX0pIiBdOyB0aGVuCiAgICBpZiBbWyAkQVJHT19BVVRIID1+IF5bQS1aMC05YS16PV17MTIwLDI1MH0kIF1dOyB0aGVuCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIHJ1biAtLXRva2VuICR7QVJHT19BVVRIfSIKICAgIGVsaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgICAgYXJncz0idHVubmVsIC0tZWRnZS1pcC12ZXJzaW9uIGF1dG8gLS1jb25maWcgdHVubmVsLnltbCBydW4iCiAgICBlbHNlCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIC0tbG9nZmlsZSBib290LmxvZyAtLWxvZ2xldmVsIGluZm8gLS11cmwgaHR0cDovL2xvY2FsaG9zdDokQVJHT19QT1JUIgogICAgZmkKICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkiICRhcmdzID4vZGV2L251bGwgMj4mMSAmCiAgICBzbGVlcCAyCiAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkgaXMgcnVubmluZ1xlWzBtIiAKZmkKCmlmIFsgLW4gIiRORVpIQV9TRVJWRVIiIF0gJiYgWyAtbiAiJE5FWkhBX1BPUlQiIF0gJiYgWyAtbiAiJE5FWkhBX0tFWSIgXTsgdGhlbgogICAgaWYgWyAtZSAiJChiYXNlbmFtZSAke0ZJTEVfTUFQW25wbV19KSIgXTsgdGhlbgoJICB0bHNQb3J0cz0oIjQ0MyIgIjg0NDMiICIyMDk2IiAiMjA4NyIgIjIwODMiICIyMDUzIikKICAgICAgW1sgIiR7dGxzUG9ydHNbKl19IiA9fiAiJHtORVpIQV9QT1JUfSIgXV0gJiYgTkVaSEFfVExTPSItLXRscyIgfHwgTkVaSEFfVExTPSIiCiAgICAgIGV4cG9ydCBUTVBESVI9JChwd2QpCiAgICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkiIC1zICR7TkVaSEFfU0VSVkVSfToke05FWkhBX1BPUlR9IC1wICR7TkVaSEFfS0VZfSAke05FWkhBX1RMU30gPi9kZXYvbnVsbCAyPiYxICYKICAgICAgc2xlZXAgMgogICAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkgaXMgcnVubmluZ1xlWzBtIgogICAgZmkKZWxpZiBbIC1uICIkTkVaSEFfU0VSVkVSIiBdICYmIFsgLW4gIiRORVpIQV9LRVkiIF07IHRoZW4KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtwaHBdfSkiIF07IHRoZW4KICAgICAgbm9odXAgLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3BocF19KSIgLWMgIiR7RklMRV9QQVRIfS9jb25maWcueWFtbCIgPi9kZXYvbnVsbCAyPiYxICYKICAgICAgZWNobyAtZSAiXGVbMTszMm0kKGJhc2VuYW1lICR7RklMRV9NQVBbcGhwXX0pIGlzIHJ1bm5pbmdcZVswbSIKICAgIGZpCmVsc2UKICAgIGVjaG8gLWUgIlxlWzE7MzVtTkVaSEEgdmFyaWFibGUgaXMgZW1wdHksIHNraXBwaW5nIHJ1bm5pbmdcZVswbSIKZmkKZm9yIGtleSBpbiAiJHshRklMRV9NQVBbQF19IjsgZG8KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFska2V5XX0pIiBdOyB0aGVuCiAgICAgICAgcm0gLXJmICIkKGJhc2VuYW1lICR7RklMRV9NQVBbJGtleV19KSIgPi9kZXYvbnVsbCAyPiYxCiAgICBmaQpkb25lCn0KZG93bmxvYWRfYW5kX3J1bgoKZ2V0X2FyZ29kb21haW4oKSB7CiAgaWYgW1sgLW4gJEFSR09fQVVUSCBdXTsgdGhlbgogICAgZWNobyAiJEFSR09fRE9NQUlOIgogIGVsc2UKICAgIGxvY2FsIHJldHJ5PTAKICAgIGxvY2FsIG1heF9yZXRyaWVzPTYKICAgIGxvY2FsIGFyZ29kb21haW49IiIKICAgIHdoaWxlIFtbICRyZXRyeSAtbHQgJG1heF9yZXRyaWVzIF1dOyBkbwogICAgICAoKHJldHJ5KyspKQogICAgICBhcmdvZG9tYWluPSQoc2VkIC1uICdzfC4qaHR0cHM6Ly9cKFteL10qdHJ5Y2xvdWRmbGFyZVwuY29tXCkuKnxcMXxwJyBib290LmxvZykKICAgICAgaWYgW1sgLW4gJGFyZ29kb21haW4gXV07IHRoZW4KICAgICAgICBicmVhawogICAgICBmaQogICAgICBzbGVlcCAxCiAgICBkb25lCiAgICBlY2hvICIkYXJnb2RvbWFpbiIKICBmaQp9CgpzZW5kX3RlbGVncmFtKCkgewogIFsgLWYgIiR7RklMRV9QQVRIfS9zdWIudHh0IiBdIHx8IHJldHVybgogIE1FU1NBR0U9JChjYXQgIiR7RklMRV9QQVRIfS9zdWIudHh0IikKICBMT0NBTF9NRVNTQUdFPSIqJHtOQU1FfeiKgueCueaOqOmAgemAmuefpSpcYFxgXGAke01FU1NBR0V9XGBcYFxgIgogIEJPVF9NRVNTQUdFPSI8Yj4ke05BTUV96IqC54K55o6o6YCB6YCa55+lPC9iPlxuPHByZT4ke01FU1NBR0V9PC9wcmU+IgogIGlmIFsgLW4gIiR7Qk9UX1RPS0VOfSIgXSAmJiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHBzOi8vYXBpLnRlbGVncmFtLm9yZy9ib3Qke0JPVF9UT0tFTn0vc2VuZE1lc3NhZ2UiIFwKICAgICAgLWQgImNoYXRfaWQ9JHtDSEFUX0lEfSZ0ZXh0PSR7TE9DQUxfTUVTU0FHRX0mcGFyc2VfbW9kZT1NYXJrZG93biIgPiAvZGV2L251bGwKCiAgZWxpZiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHA6Ly9hcGkudGcuZ3ZyYW5kZXIuZXUub3JnL2FwaS9ub3RpZnkiIFwKICAgICAgLUggIkF1dGhvcml6YXRpb246IEJlYXJlciBlSldSZ3hDNExjem5LTGlVaURvVXN3QG5NZ0RCQ0NTVWs2SXcwUzlQYnMiIFwKICAgICAgLUggIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbiIgXAogICAgICAtZCAiJChwcmludGYgJ3siY2hhdF9pZCI6ICIlcyIsICJtZXNzYWdlIjogIiVzIn0nICIke0NIQVRfSUR9IiAiJHtCT1RfTUVTU0FHRX0iKSIgPiAvZGV2L251bGwKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzVtVEcgdmFyaWFibGUgaXMgZW1wdHksc2tpcHBpbmcgc2VudFxlWzBtIgogICAgcmV0dXJuCiAgZmkKCiAgaWYgWyAkPyAtZXEgMCBdOyB0aGVuCiAgICBlY2hvIC1lICJcblxlWzE7MzJtTm9kZXMgc2VudCB0byBURyBzdWNjZXNzZnVsbHlcZVswbSIKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzFtRmFpbGVkIHRvIHNlbmQgbm9kZXMgdG8gVEdcZVswbSIKICBmaQp9Cgp1cGxvZF9ub2RlcygpIHsKICAgIFtbIC16ICRVUExPQURfVVJMIHx8ICEgLWYgIiR7RklMRV9QQVRIfS9saXN0LnR4dCIgXV0gJiYgcmV0dXJuCiAgICBjb250ZW50PSQoY2F0ICR7RklMRV9QQVRIfS9saXN0LnR4dCkKICAgIG5vZGVzPSQoZWNobyAiJGNvbnRlbnQiIHwgZ3JlcCAtRSAnKHZsZXNzfHZtZXNzfHRyb2phbnxoeXN0ZXJpYTJ8dHVpYyk6Ly8nKQogICAgW1sgLXogJG5vZGVzIF1dICYmIHJldHVybgogICAgbm9kZXM9KCRub2RlcykKICAgIGpzb25fZGF0YT0neyJub2RlcyI6IFsnCiAgICBmb3Igbm9kZSBpbiAiJHtub2Rlc1tAXX0iOyBkbwogICAgICAgIGpzb25fZGF0YSs9IlwiJG5vZGVcIiwiCiAgICBkb25lCiAgICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0KICAgIGpzb25fZGF0YSs9J119JwoKICAgIGN1cmwgLVggUE9TVCAiJFVQTE9BRF9VUkwvYXBpL2FkZC1ub2RlcyIgXAogICAgICAgICAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uIiBcCiAgICAgICAgIC1kICIkanNvbl9kYXRhIiA+IC9kZXYvbnVsbCAyPiYxCgogICAgaWYgW1sgJD8gLWVxIDAgXV07IHRoZW4KICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzJtTm9kZXMgdXBsb2FkZWQgc3VjY2Vzc2Z1bGx5XDAzM1swbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzFtRmFpbGVkIHRvIHVwbG9hZCBub2Rlc1wwMzNbMG0iCiAgICBmaQp9CgphcmdvZG9tYWluPSQoZ2V0X2FyZ29kb21haW4pCmVjaG8gLWUgIlxlWzE7MzJtQXJnb0RvbWFpbjpcZVsxOzM1bSR7YXJnb2RvbWFpbn1cZVswbVxuIgpzbGVlcCAxCklQPSQoY3VybCAtcyAtLW1heC10aW1lIDIgaXB2NC5pcC5zYiB8fCBjdXJsIC1zIC0tbWF4LXRpbWUgMSBhcGkuaXBpZnkub3JnIHx8IHsgaXB2Nj0kKGN1cmwgLXMgLS1tYXgtdGltZSAxIGlwdjYuaXAuc2IpOyBlY2hvICJbJGlwdjZdIjsgfSB8fCBlY2hvICJYWFgiKQpJU1A9JChjdXJsIC1zIC0tbWF4LXRpbWUgMiBodHRwczovL3NwZWVkLmNsb3VkZmxhcmUuY29tL21ldGEgfCBhd2sgLUZcIiAne3ByaW50ICQyNiItIiQxOH0nIHwgc2VkIC1lICdzLyAvXy9nJyB8fCBlY2hvICIwLjAiKQoKVk1FU1M9InsgXCJ2XCI6IFwiMlwiLCBcInBzXCI6IFwiJHtOQU1FfS0ke0lTUH1cIiwgXCJhZGRcIjogXCIke0NGSVB9XCIsIFwicG9ydFwiOiBcIiR7Q0ZQT1JUfVwiLCBcImlkXCI6IFwiJHtVVUlEfVwiLCBcImFpZFwiOiBcIjBcIiwgXCJzY3lcIjogXCJub25lXCIsIFwibmV0XCI6IFwid3NcIiwgXCJ0eXBlXCI6IFwibm9uZVwiLCBcImhvc3RcIjogXCIke2FyZ29kb21haW59XCIsIFwicGF0aFwiOiBcIi92bWVzcy1hcmdvP2VkPTI1NjBcIiwgXCJ0bHNcIjogXCJ0bHNcIiwgXCJzbmlcIjogXCIke2FyZ29kb21haW59XCIsIFwiYWxwblwiOiBcIlwiLCBcImZwXCI6IFwiY2hyb21lXCJ9IgoKY2F0ID4gJHtGSUxFX1BBVEh9L2xpc3QudHh0IDw8RU9GCnZtZXNzOi8vJChlY2hvICIkVk1FU1MiIHwgYmFzZTY0IC13MCkKRU9GCgppZiBbICIkVFVJQ19QT1JUIiAhPSAiNDAwMDAiIF07IHRoZW4KICBlY2hvIC1lICJcbnR1aWM6Ly8ke1VVSUR9OmFkbWluQCR7SVB9OiR7VFVJQ19QT1JUfT9zbmk9d3d3LmJpbmcuY29tJmFscG49aDMmY29uZ2VzdGlvbl9jb250cm9sPWJiciMke05BTUV9LSR7SVNQfSIgPj4gJHtGSUxFX1BBVEh9L2xpc3QudHh0CmZpCgppZiBbICIkSFkyX1BPUlQiICE9ICI1MDAwMCIgXTsgdGhlbgogIGVjaG8gLWUgIlxuaHlzdGVyaWEyOi8vJHtVVUlEfUAke0lQfToke0hZMl9QT1JUfS8/c25pPXd3dy5iaW5nLmNvbSZhbHBuPWgzJmluc2VjdXJlPTEjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKaWYgWyAiJFJFQUxJVFlfUE9SVCIgIT0gIjYwMDAwIiBdOyB0aGVuCiAgZWNobyAtZSAiXG52bGVzczovLyR7VVVJRH1AJHtJUH06JHtSRUFMSVRZX1BPUlR9P2VuY3J5cHRpb249bm9uZSZmbG93PXh0bHMtcnByeC12aXNpb24mc2VjdXJpdHk9cmVhbGl0eSZzbmk9d3d3Lm5hemh1bWkuY29tJmZwPWNocm9tZSZwYms9JHtwdWJsaWNfa2V5fSZ0eXBlPXRjcCZoZWFkZXJUeXBlPW5vbmUjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKYmFzZTY0IC13MCAke0ZJTEVfUEFUSH0vbGlzdC50eHQgPiAke0ZJTEVfUEFUSH0vc3ViLnR4dApjYXQgJHtGSUxFX1BBVEh9L3N1Yi50eHQKZWNobyAtZSAiXG5cblxlWzE7MzJtJHtGSUxFX1BBVEh9L3N1Yi50eHQgc2F2ZWQgc3VjY2Vzc2Z1bGx5XGVbMG0iCnVwbG9kX25vZGVzCnNlbmRfdGVsZWdyYW0KZWNobyAtZSAiXG5cZVsxOzMybVJ1bm5pbmcgZG9uZSFcZVswbVxuIgpzbGVlcCAxMiAKY2xlYXIKCnJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiBzYi5sb2cgY29yZSBmYWtlX3VzZXJhZ2VudF8wLjIuMC5qc29uICR7RklMRV9QQVRIfS9saXN0LnR4dCA+L2Rldi9udWxsIDI+JjE=" | base64 -d | bash 21 | -------------------------------------------------------------------------------- /python/app.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import subprocess 4 | import http.server 5 | import socketserver 6 | import threading 7 | 8 | PORT = int(os.environ.get('PORT') or 3000) # http port 9 | 10 | class MyHandler(http.server.SimpleHTTPRequestHandler): 11 | 12 | def log_message(self, format, *args): 13 | pass 14 | 15 | def do_GET(self): 16 | if self.path == '/': 17 | self.send_response(200) 18 | self.end_headers() 19 | self.wfile.write(b'Hello, world') 20 | elif self.path == '/sub': 21 | try: 22 | with open("./sub.txt", 'rb') as file: 23 | content = file.read() 24 | self.send_response(200) 25 | self.send_header('Content-Type', 'text/plain; charset=utf-8') 26 | self.end_headers() 27 | self.wfile.write(content) 28 | except FileNotFoundError: 29 | self.send_response(500) 30 | self.end_headers() 31 | self.wfile.write(b'Error reading file') 32 | else: 33 | self.send_response(404) 34 | self.end_headers() 35 | self.wfile.write(b'Not found') 36 | httpd = socketserver.TCPServer(('', PORT), MyHandler) 37 | server_thread = threading.Thread(target=httpd.serve_forever) 38 | server_thread.daemon = True 39 | server_thread.start() 40 | 41 | shell_command = "chmod +x start.sh && ./start.sh" 42 | 43 | try: 44 | completed_process = subprocess.run(['bash', '-c', shell_command], stdout=sys.stdout, stderr=subprocess.PIPE, text=True, check=True) 45 | 46 | print("App is running") 47 | 48 | except subprocess.CalledProcessError as e: 49 | print(f"Error: {e.returncode}") 50 | print("Standard Output:") 51 | print(e.stdout) 52 | print("Standard Error:") 53 | print(e.stderr) 54 | sys.exit(1) 55 | 56 | server_thread.join() 57 | -------------------------------------------------------------------------------- /python/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export UUID=${UUID:-'bc97f674-c578-4940-9234-0a1da46041b9'} # 哪吒v1,在不同的平台需要改UUID,否则会覆盖 3 | export NEZHA_SERVER=${NEZHA_SERVER:-''} # v1哪吒填写形式:nezha.abc.com:8008,v0哪吒填写形式:nezha.abc.com 4 | export NEZHA_PORT=${NEZHA_PORT:-''} # v1哪吒不要填写这个,v0哪吒agent端口为{443,8443,2053,2083,2087,2096}其中之一时自动开启tls 5 | export NEZHA_KEY=${NEZHA_KEY:-''} # v1的NZ_CLIENT_SECRET或v0的agent密钥 6 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} # 固定隧道域名,留空即启用临时隧道 7 | export ARGO_AUTH=${ARGO_AUTH:-''} # 固定隧道token或json,留空即启用临时隧道 8 | export CFIP=${CFIP:-'www.visa.com.tw'} # argo节点优选域名或优选ip 9 | export CFPORT=${CFPORT:-'443'} # argo节点端口 10 | export NAME=${NAME:-'Vls'} # 节点名称 11 | export FILE_PATH=${FILE_PATH:-'./.cache'} # sub 路径 12 | export ARGO_PORT=${ARGO_PORT:-'8001'} # argo端口 使用固定隧道token,cloudflare后台设置的端口需和这里对应 13 | export TUIC_PORT=${TUIC_PORT:-'40000'} # Tuic 端口,支持多端口玩具可填写,否则不动 14 | export HY2_PORT=${HY2_PORT:-'50000'} # Hy2 端口,支持多端口玩具可填写,否则不动 15 | export REALITY_PORT=${REALITY_PORT:-'60000'} # reality 端口,支持多端口玩具可填写,否则不动 16 | export CHAT_ID=${CHAT_ID:-''} # TG chat_id,可在https://t.me/laowang_serv00_bot 获取 17 | export BOT_TOKEN=${BOT_TOKEN:-''} # TG bot_token, 使用自己的bot需要填写,使用上方的bot不用填写,不会给别人发送 18 | export UPLOAD_URL=${UPLOAD_URL:-''} # 订阅自动上传地址,没有可不填,需要填部署Merge-sub项目后的首页地址,例如:https://merge.serv00.net 19 | 20 | echo "ZGVsZXRlX29sZF9ub2RlcygpIHsKICBbWyAteiAkVVBMT0FEX1VSTCB8fCAhIC1mICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgXV0gJiYgcmV0dXJuCiAgb2xkX25vZGVzPSQoYmFzZTY0IC1kICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgfCBncmVwIC1FICcodmxlc3N8dm1lc3N8dHJvamFufGh5c3RlcmlhMnx0dWljKTovLycpCiAgW1sgLXogJG9sZF9ub2RlcyBdXSAmJiByZXR1cm4KCiAganNvbl9kYXRhPSd7Im5vZGVzIjogWycKICBmb3Igbm9kZSBpbiAkb2xkX25vZGVzOyBkbwogICAgICBqc29uX2RhdGErPSJcIiRub2RlXCIsIgogIGRvbmUKICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0gIAogIGpzb25fZGF0YSs9J119JwoKICBjdXJsIC1YIERFTEVURSAiJFVQTE9BRF9VUkwvYXBpL2RlbGV0ZS1ub2RlcyIgXAogICAgICAgIC1IICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24iIFwKICAgICAgICAtZCAiJGpzb25fZGF0YSIgPiAvZGV2L251bGwgMj4mMQp9CmRlbGV0ZV9vbGRfbm9kZXMKClsgISAtZCAiJHtGSUxFX1BBVEh9IiBdICYmIG1rZGlyIC1wICIke0ZJTEVfUEFUSH0iICYmIHJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiB0dW5uZWwuanNvbiB0dW5uZWwueW1sICIke0ZJTEVfUEFUSH0vc3ViLnR4dCIgPi9kZXYvbnVsbCAyPiYxCgoKYXJnb19jb25maWd1cmUoKSB7CiAgaWYgW1sgLXogJEFSR09fQVVUSCB8fCAteiAkQVJHT19ET01BSU4gXV07IHRoZW4KICAgIGVjaG8gLWUgIlxlWzE7MzJtQVJHT19ET01BSU4gb3IgQVJHT19BVVRIIHZhcmlhYmxlIGlzIGVtcHR5LCB1c2UgcXVpY2sgdHVubmVsc1xlWzBtIiAgIAogICAgcmV0dXJuCiAgZmkKCiAgaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgIGVjaG8gJEFSR09fQVVUSCA+IHR1bm5lbC5qc29uCiAgICBjYXQgPiB0dW5uZWwueW1sIDw8IEVPRgp0dW5uZWw6ICQoY3V0IC1kXCIgLWYxMiA8PDwgIiRBUkdPX0FVVEgiKQpjcmVkZW50aWFscy1maWxlOiB0dW5uZWwuanNvbgpwcm90b2NvbDogaHR0cDIKCmluZ3Jlc3M6CiAgLSBob3N0bmFtZTogJEFSR09fRE9NQUlOCiAgICBzZXJ2aWNlOiBodHRwOi8vbG9jYWxob3N0OiRBUkdPX1BPUlQKICAgIG9yaWdpblJlcXVlc3Q6CiAgICAgIG5vVExTVmVyaWZ5OiB0cnVlCiAgLSBzZXJ2aWNlOiBodHRwX3N0YXR1czo0MDQKRU9GCiAgZWxzZQogICAgZWNobyAtZSAiXGVbMTszMm1BUkdPX0FVVEggbWlzbWF0Y2ggVHVubmVsU2VjcmV0LHVzZSB0b2tlbiBjb25uZWN0IHRvIHR1bm5lbFxlWzBtIgogIGZpCn0KYXJnb19jb25maWd1cmUKd2FpdAoKZG93bmxvYWRfYW5kX3J1bigpIHsKQVJDSD0kKHVuYW1lIC1tKSAmJiBET1dOTE9BRF9ESVI9Ii4iICYmIG1rZGlyIC1wICIkRE9XTkxPQURfRElSIiAmJiBGSUxFX0lORk89KCkKaWYgWyAiJEFSQ0giID09ICJhcm0iIF0gfHwgWyAiJEFSQ0giID09ICJhcm02NCIgXSB8fCBbICIkQVJDSCIgPT0gImFhcmNoNjQiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FybTY0LnNzc3MubnljLm1uIgplbGlmIFsgIiRBUkNIIiA9PSAiYW1kNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODZfNjQiIF0gfHwgWyAiJEFSQ0giID09ICJ4ODYiIF07IHRoZW4KICAgIEJBU0VfVVJMPSJodHRwczovL2FtZDY0LnNzc3MubnljLm1uIgplbHNlCiAgICBlY2hvICJVbnN1cHBvcnRlZCBhcmNoaXRlY3R1cmU6ICRBUkNIIgogICAgZXhpdCAxCmZpCkZJTEVfSU5GTz0oIiRCQVNFX1VSTC9zYiB3ZWIiICIkQkFTRV9VUkwvYm90IGJvdCIpCgppZiBbIC1uICIkTkVaSEFfUE9SVCIgXTsgdGhlbgogICAgRklMRV9JTkZPKz0oIiRCQVNFX1VSTC9hZ2VudCBucG0iKQplbHNlCiAgICBGSUxFX0lORk8rPSgiJEJBU0VfVVJML3YxIHBocCIpCiAgICBORVpIQV9UTFM9JChjYXNlICIke05FWkhBX1NFUlZFUiMjKjp9IiBpbiA0NDN8ODQ0M3wyMDk2fDIwODd8MjA4M3wyMDUzKSBlY2hvIC1uIHRydWU7OyAqKSBlY2hvIC1uIGZhbHNlOzsgZXNhYykKICAgIGNhdCA+ICIke0ZJTEVfUEFUSH0vY29uZmlnLnlhbWwiIDw8IEVPRgpjbGllbnRfc2VjcmV0OiAke05FWkhBX0tFWX0KZGVidWc6IGZhbHNlCmRpc2FibGVfYXV0b191cGRhdGU6IHRydWUKZGlzYWJsZV9jb21tYW5kX2V4ZWN1dGU6IGZhbHNlCmRpc2FibGVfZm9yY2VfdXBkYXRlOiB0cnVlCmRpc2FibGVfbmF0OiBmYWxzZQpkaXNhYmxlX3NlbmRfcXVlcnk6IGZhbHNlCmdwdTogZmFsc2UKaW5zZWN1cmVfdGxzOiBmYWxzZQppcF9yZXBvcnRfcGVyaW9kOiAxODAwCnJlcG9ydF9kZWxheTogMQpzZXJ2ZXI6ICR7TkVaSEFfU0VSVkVSfQpza2lwX2Nvbm5lY3Rpb25fY291bnQ6IGZhbHNlCnNraXBfcHJvY3NfY291bnQ6IGZhbHNlCnRlbXBlcmF0dXJlOiBmYWxzZQp0bHM6ICR7TkVaSEFfVExTfQp1c2VfZ2l0ZWVfdG9fdXBncmFkZTogZmFsc2UKdXNlX2lwdjZfY291bnRyeV9jb2RlOiBmYWxzZQp1dWlkOiAke1VVSUR9CkVPRgpmaQpkZWNsYXJlIC1BIEZJTEVfTUFQCmdlbmVyYXRlX3JhbmRvbV9uYW1lKCkgewogICAgbG9jYWwgY2hhcnM9YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwCiAgICBsb2NhbCBuYW1lPSIiCiAgICBmb3IgaSBpbiB7MS4uNn07IGRvCiAgICAgICAgbmFtZT0iJG5hbWUke2NoYXJzOlJBTkRPTSUkeyNjaGFyc306MX0iCiAgICBkb25lCiAgICBlY2hvICIkbmFtZSIKfQpkb3dubG9hZF9maWxlKCkgewogICAgbG9jYWwgVVJMPSQxCiAgICBsb2NhbCBORVdfRklMRU5BTUU9JDIKCiAgICBpZiBjb21tYW5kIC12IGN1cmwgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgICAgICAgY3VybCAtTCAtc1MgLW8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IGN1cmxcZVswbSIKICAgIGVsaWYgY29tbWFuZCAtdiB3Z2V0ID4vZGV2L251bGwgMj4mMTsgdGhlbgogICAgICAgIHdnZXQgLXEgLU8gIiRORVdfRklMRU5BTUUiICIkVVJMIgogICAgICAgIGVjaG8gLWUgIlxlWzE7MzJtRG93bmxvYWRlZCAkTkVXX0ZJTEVOQU1FIGJ5IHdnZXRcZVswbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcZVsxOzMzbU5laXRoZXIgY3VybCBub3Igd2dldCBpcyBhdmFpbGFibGUgZm9yIGRvd25sb2FkaW5nXGVbMG0iCiAgICAgICAgZXhpdCAxCiAgICBmaQp9CmZvciBlbnRyeSBpbiAiJHtGSUxFX0lORk9bQF19IjsgZG8KICAgIFVSTD0kKGVjaG8gIiRlbnRyeSIgfCBjdXQgLWQgJyAnIC1mIDEpCiAgICBSQU5ET01fTkFNRT0kKGdlbmVyYXRlX3JhbmRvbV9uYW1lKQogICAgTkVXX0ZJTEVOQU1FPSIkRE9XTkxPQURfRElSLyRSQU5ET01fTkFNRSIKICAgIAogICAgZG93bmxvYWRfZmlsZSAiJFVSTCIgIiRORVdfRklMRU5BTUUiCiAgICAKICAgIGNobW9kICt4ICIkTkVXX0ZJTEVOQU1FIgogICAgRklMRV9NQVBbJChlY2hvICIkZW50cnkiIHwgY3V0IC1kICcgJyAtZiAyKV09IiRORVdfRklMRU5BTUUiCmRvbmUKd2FpdAoKb3V0cHV0PSQoLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSIgZ2VuZXJhdGUgcmVhbGl0eS1rZXlwYWlyKQpwcml2YXRlX2tleT0kKGVjaG8gIiR7b3V0cHV0fSIgfCBhd2sgJy9Qcml2YXRlS2V5Oi8ge3ByaW50ICQyfScpCnB1YmxpY19rZXk9JChlY2hvICIke291dHB1dH0iIHwgYXdrICcvUHVibGljS2V5Oi8ge3ByaW50ICQyfScpCgpvcGVuc3NsIGVjcGFyYW0gLWdlbmtleSAtbmFtZSBwcmltZTI1NnYxIC1vdXQgInByaXZhdGUua2V5IgpvcGVuc3NsIHJlcSAtbmV3IC14NTA5IC1kYXlzIDM2NTAgLWtleSAicHJpdmF0ZS5rZXkiIC1vdXQgImNlcnQucGVtIiAtc3ViaiAiL0NOPWJpbmcuY29tIgoKICBjYXQgPiBjb25maWcuanNvbiA8PCBFT0YKewogICAgImxvZyI6IHsKICAgICAgICAiZGlzYWJsZWQiOiB0cnVlLAogICAgICAgICJsZXZlbCI6ICJlcnJvciIsCiAgICAgICAgInRpbWVzdGFtcCI6IHRydWUKICAgIH0sCiAgICAiZG5zIjogewogICAgICAgICJzZXJ2ZXJzIjogWwogICAgICAgIHsKICAgICAgICAgICJ0YWciOiAiZ29vZ2xlIiwKICAgICAgICAgICJhZGRyZXNzIjogInRsczovLzguOC44LjgiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgImluYm91bmRzIjogWwogICAgewogICAgICAidGFnIjogInZtZXNzLXdzLWluIiwKICAgICAgInR5cGUiOiAidm1lc3MiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtBUkdPX1BPUlR9LAogICAgICAgICJ1c2VycyI6IFsKICAgICAgICB7CiAgICAgICAgICAidXVpZCI6ICIke1VVSUR9IgogICAgICAgIH0KICAgICAgXSwKICAgICAgInRyYW5zcG9ydCI6IHsKICAgICAgICAidHlwZSI6ICJ3cyIsCiAgICAgICAgInBhdGgiOiAiL3ZtZXNzLWFyZ28iLAogICAgICAgICJlYXJseV9kYXRhX2hlYWRlcl9uYW1lIjogIlNlYy1XZWJTb2NrZXQtUHJvdG9jb2wiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJ0YWciOiAidHVpYy1pbiIsCiAgICAgICJ0eXBlIjogInR1aWMiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtUVUlDX1BPUlR9LAogICAgICAidXNlcnMiOiBbCiAgICAgICAgewogICAgICAgICAgInV1aWQiOiAiJHtVVUlEfSIsCiAgICAgICAgICAicGFzc3dvcmQiOiAiYWRtaW4iCiAgICAgICAgfQogICAgICBdLAogICAgICAiY29uZ2VzdGlvbl9jb250cm9sIjogImJiciIsCiAgICAgICJ0bHMiOiB7CiAgICAgICAgImVuYWJsZWQiOiB0cnVlLAogICAgICAgICJhbHBuIjogWwogICAgICAgICAgImgzIgogICAgICAgIF0sCiAgICAgICAgImNlcnRpZmljYXRlX3BhdGgiOiAiY2VydC5wZW0iLAogICAgICAgICJrZXlfcGF0aCI6ICJwcml2YXRlLmtleSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgInRhZyI6ICJoeXN0ZXJpYTItaW4iLAogICAgICAidHlwZSI6ICJoeXN0ZXJpYTIiLAogICAgICAibGlzdGVuIjogIjo6IiwKICAgICAgImxpc3Rlbl9wb3J0IjogJHtIWTJfUE9SVH0sCiAgICAgICAgInVzZXJzIjogWwogICAgICAgICAgewogICAgICAgICAgICAgInBhc3N3b3JkIjogIiR7VVVJRH0iCiAgICAgICAgICB9CiAgICAgIF0sCiAgICAgICJtYXNxdWVyYWRlIjogImh0dHBzOi8vYmluZy5jb20iLAogICAgICAgICJ0bHMiOiB7CiAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgImFscG4iOiBbCiAgICAgICAgICAgICAgICAiaDMiCiAgICAgICAgICAgIF0sCiAgICAgICAgICAgICJjZXJ0aWZpY2F0ZV9wYXRoIjogImNlcnQucGVtIiwKICAgICAgICAgICAgImtleV9wYXRoIjogInByaXZhdGUua2V5IgogICAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJ2bGVzcy1yZWFsaXR5LXZlc2lvbiIsCiAgICAgICAgInR5cGUiOiAidmxlc3MiLAogICAgICAgICJsaXN0ZW4iOiAiOjoiLAogICAgICAgICJsaXN0ZW5fcG9ydCI6ICRSRUFMSVRZX1BPUlQsCiAgICAgICAgICAidXNlcnMiOiBbCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInV1aWQiOiAiJFVVSUQiLAogICAgICAgICAgICAgICAgImZsb3ciOiAieHRscy1ycHJ4LXZpc2lvbiIKICAgICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgInRscyI6IHsKICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsCiAgICAgICAgICAgICAgInNlcnZlcl9uYW1lIjogInd3dy5uYXpodW1pLmNvbSIsCiAgICAgICAgICAgICAgInJlYWxpdHkiOiB7CiAgICAgICAgICAgICAgICAgICJlbmFibGVkIjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgImhhbmRzaGFrZSI6IHsKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXIiOiAid3d3Lm5hemh1bWkuY29tIiwKICAgICAgICAgICAgICAgICAgICAgICJzZXJ2ZXJfcG9ydCI6IDQ0MwogICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAicHJpdmF0ZV9rZXkiOiAiJHByaXZhdGVfa2V5IiwKICAgICAgICAgICAgICAgICAgInNob3J0X2lkIjogWwogICAgICAgICAgICAgICAgICAgICIiCiAgICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgIH0KICAgXSwKICAib3V0Ym91bmRzIjogWwogICAgewogICAgICAidHlwZSI6ICJkaXJlY3QiLAogICAgICAidGFnIjogImRpcmVjdCIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogImJsb2NrIiwKICAgICAgInRhZyI6ICJibG9jayIKICAgIH0sCiAgICB7CiAgICAgICJ0eXBlIjogIndpcmVndWFyZCIsCiAgICAgICJ0YWciOiAid2lyZWd1YXJkLW91dCIsCiAgICAgICJzZXJ2ZXIiOiAiMTYyLjE1OS4xOTIuMjAwIiwKICAgICAgInNlcnZlcl9wb3J0IjogNDUwMCwKICAgICAgImxvY2FsX2FkZHJlc3MiOiBbCiAgICAgICAgIjE3Mi4xNi4wLjIvMzIiLAogICAgICAgICIyNjA2OjQ3MDA6MTEwOjhmNzc6MWNhOTpmMDg2Ojg0NmM6NWY5ZS8xMjgiCiAgICAgIF0sCiAgICAgICJwcml2YXRlX2tleSI6ICJ3SXhzemRSMm5NZEE3YTJVbDNYUWNuaVNmU1pxZHFqUGI2dzZvcHZmNUFVPSIsCiAgICAgICJwZWVyX3B1YmxpY19rZXkiOiAiYm1YT0MrRjFGeEVNRjlkeWlLMkg1LzFTVXR6SDBKdVZvNTFoMndQZmd5bz0iLAogICAgICAicmVzZXJ2ZWQiOiBbMTI2LCAyNDYsIDE3M10KICAgIH0KICBdLAogICJyb3V0ZSI6IHsKICAgICJydWxlX3NldCI6IFsKICAgICAgewogICAgICAgICJ0YWciOiAibmV0ZmxpeCIsCiAgICAgICAgInR5cGUiOiAicmVtb3RlIiwKICAgICAgICAiZm9ybWF0IjogImJpbmFyeSIsCiAgICAgICAgInVybCI6ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vTWV0YUN1YmVYL21ldGEtcnVsZXMtZGF0L3NpbmcvZ2VvL2dlb3NpdGUvbmV0ZmxpeC5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9LAogICAgICB7CiAgICAgICAgInRhZyI6ICJvcGVuYWkiLAogICAgICAgICJ0eXBlIjogInJlbW90ZSIsCiAgICAgICAgImZvcm1hdCI6ICJiaW5hcnkiLAogICAgICAgICJ1cmwiOiAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL01ldGFDdWJlWC9tZXRhLXJ1bGVzLWRhdC9zaW5nL2dlby9nZW9zaXRlL29wZW5haS5zcnMiLAogICAgICAgICJkb3dubG9hZF9kZXRvdXIiOiAiZGlyZWN0IgogICAgICB9CiAgICBdLAogICAgInJ1bGVzIjogWwogICAgICB7CiAgICAgICAgInJ1bGVfc2V0IjogWyJuZXRmbGl4IiwgIm9wZW5haSJdLAogICAgICAgICJvdXRib3VuZCI6ICJ3aXJlZ3VhcmQtb3V0IgogICAgICB9CiAgICBdLAogICAgImZpbmFsIjogImRpcmVjdCIKICB9Cn0KRU9GCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBdOyB0aGVuCiAgICBub2h1cCAuLyIkKGJhc2VuYW1lICR7RklMRV9NQVBbd2ViXX0pIiBydW4gLWMgY29uZmlnLmpzb24gPi9kZXYvbnVsbCAyPiYxICYKICAgIHNsZWVwIDIKICAgIGVjaG8gLWUgIlxlWzE7MzJtJChiYXNlbmFtZSAke0ZJTEVfTUFQW3dlYl19KSBpcyBydW5uaW5nXGVbMG0iCmZpCgppZiBbIC1lICIkKGJhc2VuYW1lICR7RklMRV9NQVBbYm90XX0pIiBdOyB0aGVuCiAgICBpZiBbWyAkQVJHT19BVVRIID1+IF5bQS1aMC05YS16PV17MTIwLDI1MH0kIF1dOyB0aGVuCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIHJ1biAtLXRva2VuICR7QVJHT19BVVRIfSIKICAgIGVsaWYgW1sgJEFSR09fQVVUSCA9fiBUdW5uZWxTZWNyZXQgXV07IHRoZW4KICAgICAgYXJncz0idHVubmVsIC0tZWRnZS1pcC12ZXJzaW9uIGF1dG8gLS1jb25maWcgdHVubmVsLnltbCBydW4iCiAgICBlbHNlCiAgICAgIGFyZ3M9InR1bm5lbCAtLWVkZ2UtaXAtdmVyc2lvbiBhdXRvIC0tbm8tYXV0b3VwZGF0ZSAtLXByb3RvY29sIGh0dHAyIC0tbG9nZmlsZSBib290LmxvZyAtLWxvZ2xldmVsIGluZm8gLS11cmwgaHR0cDovL2xvY2FsaG9zdDokQVJHT19QT1JUIgogICAgZmkKICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkiICRhcmdzID4vZGV2L251bGwgMj4mMSAmCiAgICBzbGVlcCAyCiAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtib3RdfSkgaXMgcnVubmluZ1xlWzBtIiAKZmkKCmlmIFsgLW4gIiRORVpIQV9TRVJWRVIiIF0gJiYgWyAtbiAiJE5FWkhBX1BPUlQiIF0gJiYgWyAtbiAiJE5FWkhBX0tFWSIgXTsgdGhlbgogICAgaWYgWyAtZSAiJChiYXNlbmFtZSAke0ZJTEVfTUFQW25wbV19KSIgXTsgdGhlbgoJICB0bHNQb3J0cz0oIjQ0MyIgIjg0NDMiICIyMDk2IiAiMjA4NyIgIjIwODMiICIyMDUzIikKICAgICAgW1sgIiR7dGxzUG9ydHNbKl19IiA9fiAiJHtORVpIQV9QT1JUfSIgXV0gJiYgTkVaSEFfVExTPSItLXRscyIgfHwgTkVaSEFfVExTPSIiCiAgICAgIGV4cG9ydCBUTVBESVI9JChwd2QpCiAgICAgIG5vaHVwIC4vIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkiIC1zICR7TkVaSEFfU0VSVkVSfToke05FWkhBX1BPUlR9IC1wICR7TkVaSEFfS0VZfSAke05FWkhBX1RMU30gPi9kZXYvbnVsbCAyPiYxICYKICAgICAgc2xlZXAgMgogICAgICBlY2hvIC1lICJcZVsxOzMybSQoYmFzZW5hbWUgJHtGSUxFX01BUFtucG1dfSkgaXMgcnVubmluZ1xlWzBtIgogICAgZmkKZWxpZiBbIC1uICIkTkVaSEFfU0VSVkVSIiBdICYmIFsgLW4gIiRORVpIQV9LRVkiIF07IHRoZW4KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFtwaHBdfSkiIF07IHRoZW4KICAgICAgbm9odXAgLi8iJChiYXNlbmFtZSAke0ZJTEVfTUFQW3BocF19KSIgLWMgIiR7RklMRV9QQVRIfS9jb25maWcueWFtbCIgPi9kZXYvbnVsbCAyPiYxICYKICAgICAgZWNobyAtZSAiXGVbMTszMm0kKGJhc2VuYW1lICR7RklMRV9NQVBbcGhwXX0pIGlzIHJ1bm5pbmdcZVswbSIKICAgIGZpCmVsc2UKICAgIGVjaG8gLWUgIlxlWzE7MzVtTkVaSEEgdmFyaWFibGUgaXMgZW1wdHksIHNraXBwaW5nIHJ1bm5pbmdcZVswbSIKZmkKZm9yIGtleSBpbiAiJHshRklMRV9NQVBbQF19IjsgZG8KICAgIGlmIFsgLWUgIiQoYmFzZW5hbWUgJHtGSUxFX01BUFska2V5XX0pIiBdOyB0aGVuCiAgICAgICAgcm0gLXJmICIkKGJhc2VuYW1lICR7RklMRV9NQVBbJGtleV19KSIgPi9kZXYvbnVsbCAyPiYxCiAgICBmaQpkb25lCn0KZG93bmxvYWRfYW5kX3J1bgoKZ2V0X2FyZ29kb21haW4oKSB7CiAgaWYgW1sgLW4gJEFSR09fQVVUSCBdXTsgdGhlbgogICAgZWNobyAiJEFSR09fRE9NQUlOIgogIGVsc2UKICAgIGxvY2FsIHJldHJ5PTAKICAgIGxvY2FsIG1heF9yZXRyaWVzPTYKICAgIGxvY2FsIGFyZ29kb21haW49IiIKICAgIHdoaWxlIFtbICRyZXRyeSAtbHQgJG1heF9yZXRyaWVzIF1dOyBkbwogICAgICAoKHJldHJ5KyspKQogICAgICBhcmdvZG9tYWluPSQoc2VkIC1uICdzfC4qaHR0cHM6Ly9cKFteL10qdHJ5Y2xvdWRmbGFyZVwuY29tXCkuKnxcMXxwJyBib290LmxvZykKICAgICAgaWYgW1sgLW4gJGFyZ29kb21haW4gXV07IHRoZW4KICAgICAgICBicmVhawogICAgICBmaQogICAgICBzbGVlcCAxCiAgICBkb25lCiAgICBlY2hvICIkYXJnb2RvbWFpbiIKICBmaQp9CgpzZW5kX3RlbGVncmFtKCkgewogIFsgLWYgIiR7RklMRV9QQVRIfS9zdWIudHh0IiBdIHx8IHJldHVybgogIE1FU1NBR0U9JChjYXQgIiR7RklMRV9QQVRIfS9zdWIudHh0IikKICBMT0NBTF9NRVNTQUdFPSIqJHtOQU1FfeiKgueCueaOqOmAgemAmuefpSpcYFxgXGAke01FU1NBR0V9XGBcYFxgIgogIEJPVF9NRVNTQUdFPSI8Yj4ke05BTUV96IqC54K55o6o6YCB6YCa55+lPC9iPlxuPHByZT4ke01FU1NBR0V9PC9wcmU+IgogIGlmIFsgLW4gIiR7Qk9UX1RPS0VOfSIgXSAmJiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHBzOi8vYXBpLnRlbGVncmFtLm9yZy9ib3Qke0JPVF9UT0tFTn0vc2VuZE1lc3NhZ2UiIFwKICAgICAgLWQgImNoYXRfaWQ9JHtDSEFUX0lEfSZ0ZXh0PSR7TE9DQUxfTUVTU0FHRX0mcGFyc2VfbW9kZT1NYXJrZG93biIgPiAvZGV2L251bGwKCiAgZWxpZiBbIC1uICIke0NIQVRfSUR9IiBdOyB0aGVuCiAgICBjdXJsIC1zIC1YIFBPU1QgImh0dHA6Ly9hcGkudGcuZ3ZyYW5kZXIuZXUub3JnL2FwaS9ub3RpZnkiIFwKICAgICAgLUggIkF1dGhvcml6YXRpb246IEJlYXJlciBlSldSZ3hDNExjem5LTGlVaURvVXN3QG5NZ0RCQ0NTVWs2SXcwUzlQYnMiIFwKICAgICAgLUggIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbiIgXAogICAgICAtZCAiJChwcmludGYgJ3siY2hhdF9pZCI6ICIlcyIsICJtZXNzYWdlIjogIiVzIn0nICIke0NIQVRfSUR9IiAiJHtCT1RfTUVTU0FHRX0iKSIgPiAvZGV2L251bGwKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzVtVEcgdmFyaWFibGUgaXMgZW1wdHksc2tpcHBpbmcgc2VudFxlWzBtIgogICAgcmV0dXJuCiAgZmkKCiAgaWYgWyAkPyAtZXEgMCBdOyB0aGVuCiAgICBlY2hvIC1lICJcblxlWzE7MzJtTm9kZXMgc2VudCB0byBURyBzdWNjZXNzZnVsbHlcZVswbSIKICBlbHNlCiAgICBlY2hvIC1lICJcblxlWzE7MzFtRmFpbGVkIHRvIHNlbmQgbm9kZXMgdG8gVEdcZVswbSIKICBmaQp9Cgp1cGxvZF9ub2RlcygpIHsKICAgIFtbIC16ICRVUExPQURfVVJMIHx8ICEgLWYgIiR7RklMRV9QQVRIfS9saXN0LnR4dCIgXV0gJiYgcmV0dXJuCiAgICBjb250ZW50PSQoY2F0ICR7RklMRV9QQVRIfS9saXN0LnR4dCkKICAgIG5vZGVzPSQoZWNobyAiJGNvbnRlbnQiIHwgZ3JlcCAtRSAnKHZsZXNzfHZtZXNzfHRyb2phbnxoeXN0ZXJpYTJ8dHVpYyk6Ly8nKQogICAgW1sgLXogJG5vZGVzIF1dICYmIHJldHVybgogICAgbm9kZXM9KCRub2RlcykKICAgIGpzb25fZGF0YT0neyJub2RlcyI6IFsnCiAgICBmb3Igbm9kZSBpbiAiJHtub2Rlc1tAXX0iOyBkbwogICAgICAgIGpzb25fZGF0YSs9IlwiJG5vZGVcIiwiCiAgICBkb25lCiAgICBqc29uX2RhdGE9JHtqc29uX2RhdGElLH0KICAgIGpzb25fZGF0YSs9J119JwoKICAgIGN1cmwgLVggUE9TVCAiJFVQTE9BRF9VUkwvYXBpL2FkZC1ub2RlcyIgXAogICAgICAgICAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uIiBcCiAgICAgICAgIC1kICIkanNvbl9kYXRhIiA+IC9kZXYvbnVsbCAyPiYxCgogICAgaWYgW1sgJD8gLWVxIDAgXV07IHRoZW4KICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzJtTm9kZXMgdXBsb2FkZWQgc3VjY2Vzc2Z1bGx5XDAzM1swbSIKICAgIGVsc2UKICAgICAgICBlY2hvIC1lICJcMDMzWzE7MzFtRmFpbGVkIHRvIHVwbG9hZCBub2Rlc1wwMzNbMG0iCiAgICBmaQp9CgphcmdvZG9tYWluPSQoZ2V0X2FyZ29kb21haW4pCmVjaG8gLWUgIlxlWzE7MzJtQXJnb0RvbWFpbjpcZVsxOzM1bSR7YXJnb2RvbWFpbn1cZVswbVxuIgpzbGVlcCAxCklQPSQoY3VybCAtcyAtLW1heC10aW1lIDIgaXB2NC5pcC5zYiB8fCBjdXJsIC1zIC0tbWF4LXRpbWUgMSBhcGkuaXBpZnkub3JnIHx8IHsgaXB2Nj0kKGN1cmwgLXMgLS1tYXgtdGltZSAxIGlwdjYuaXAuc2IpOyBlY2hvICJbJGlwdjZdIjsgfSB8fCBlY2hvICJYWFgiKQpJU1A9JChjdXJsIC1zIC0tbWF4LXRpbWUgMiBodHRwczovL3NwZWVkLmNsb3VkZmxhcmUuY29tL21ldGEgfCBhd2sgLUZcIiAne3ByaW50ICQyNiItIiQxOH0nIHwgc2VkIC1lICdzLyAvXy9nJyB8fCBlY2hvICIwLjAiKQoKVk1FU1M9InsgXCJ2XCI6IFwiMlwiLCBcInBzXCI6IFwiJHtOQU1FfS0ke0lTUH1cIiwgXCJhZGRcIjogXCIke0NGSVB9XCIsIFwicG9ydFwiOiBcIiR7Q0ZQT1JUfVwiLCBcImlkXCI6IFwiJHtVVUlEfVwiLCBcImFpZFwiOiBcIjBcIiwgXCJzY3lcIjogXCJub25lXCIsIFwibmV0XCI6IFwid3NcIiwgXCJ0eXBlXCI6IFwibm9uZVwiLCBcImhvc3RcIjogXCIke2FyZ29kb21haW59XCIsIFwicGF0aFwiOiBcIi92bWVzcy1hcmdvP2VkPTI1NjBcIiwgXCJ0bHNcIjogXCJ0bHNcIiwgXCJzbmlcIjogXCIke2FyZ29kb21haW59XCIsIFwiYWxwblwiOiBcIlwiLCBcImZwXCI6IFwiY2hyb21lXCJ9IgoKY2F0ID4gJHtGSUxFX1BBVEh9L2xpc3QudHh0IDw8RU9GCnZtZXNzOi8vJChlY2hvICIkVk1FU1MiIHwgYmFzZTY0IC13MCkKRU9GCgppZiBbICIkVFVJQ19QT1JUIiAhPSAiNDAwMDAiIF07IHRoZW4KICBlY2hvIC1lICJcbnR1aWM6Ly8ke1VVSUR9OmFkbWluQCR7SVB9OiR7VFVJQ19QT1JUfT9zbmk9d3d3LmJpbmcuY29tJmFscG49aDMmY29uZ2VzdGlvbl9jb250cm9sPWJiciMke05BTUV9LSR7SVNQfSIgPj4gJHtGSUxFX1BBVEh9L2xpc3QudHh0CmZpCgppZiBbICIkSFkyX1BPUlQiICE9ICI1MDAwMCIgXTsgdGhlbgogIGVjaG8gLWUgIlxuaHlzdGVyaWEyOi8vJHtVVUlEfUAke0lQfToke0hZMl9QT1JUfS8/c25pPXd3dy5iaW5nLmNvbSZhbHBuPWgzJmluc2VjdXJlPTEjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKaWYgWyAiJFJFQUxJVFlfUE9SVCIgIT0gIjYwMDAwIiBdOyB0aGVuCiAgZWNobyAtZSAiXG52bGVzczovLyR7VVVJRH1AJHtJUH06JHtSRUFMSVRZX1BPUlR9P2VuY3J5cHRpb249bm9uZSZmbG93PXh0bHMtcnByeC12aXNpb24mc2VjdXJpdHk9cmVhbGl0eSZzbmk9d3d3Lm5hemh1bWkuY29tJmZwPWNocm9tZSZwYms9JHtwdWJsaWNfa2V5fSZ0eXBlPXRjcCZoZWFkZXJUeXBlPW5vbmUjJHtOQU1FfS0ke0lTUH0iID4+ICR7RklMRV9QQVRIfS9saXN0LnR4dApmaQoKYmFzZTY0IC13MCAke0ZJTEVfUEFUSH0vbGlzdC50eHQgPiAke0ZJTEVfUEFUSH0vc3ViLnR4dApjYXQgJHtGSUxFX1BBVEh9L3N1Yi50eHQKZWNobyAtZSAiXG5cblxlWzE7MzJtJHtGSUxFX1BBVEh9L3N1Yi50eHQgc2F2ZWQgc3VjY2Vzc2Z1bGx5XGVbMG0iCnVwbG9kX25vZGVzCnNlbmRfdGVsZWdyYW0KZWNobyAtZSAiXG5cZVsxOzMybVJ1bm5pbmcgZG9uZSFcZVswbVxuIgpzbGVlcCAxMiAKY2xlYXIKCnJtIC1yZiBib290LmxvZyBjb25maWcuanNvbiBzYi5sb2cgY29yZSBmYWtlX3VzZXJhZ2VudF8wLjIuMC5qc29uICR7RklMRV9QQVRIfS9saXN0LnR4dCA+L2Rldi9udWxsIDI+JjE=" | base64 -d | bash 21 | -------------------------------------------------------------------------------- /sb4.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 | HOSTNAME=$(hostname) 15 | USERNAME=$(whoami | tr '[:upper:]' '[:lower:]') 16 | export UUID=${UUID:-$(uuidgen -r)} 17 | export NEZHA_SERVER=${NEZHA_SERVER:-''} # v1哪吒形式:nezha.abc.com:8008,v0哪吒形式:nezha.abc.com 18 | export NEZHA_PORT=${NEZHA_PORT:-''} # v1哪吒不需要此变量,v0的agent端口 19 | export NEZHA_KEY=${NEZHA_KEY:-''} # v1的NZ_CLIENT_SECRET或v0的agent密钥 20 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} 21 | export ARGO_AUTH=${ARGO_AUTH:-''} 22 | export CFIP=${CFIP:-'www.visa.com.sg'} 23 | export CFPORT=${CFPORT:-'443'} 24 | export SUB_TOKEN=${SUB_TOKEN:-${UUID:0:8}} 25 | export CHAT_ID=${CHAT_ID:-''} 26 | export BOT_TOKEN=${BOT_TOKEN:-''} 27 | export UPLOAD_URL=${UPLOAD_URL:-''} 28 | 29 | if [[ "$HOSTNAME" =~ ct8 ]]; then 30 | CURRENT_DOMAIN="ct8.pl" 31 | elif [[ "$HOSTNAME" =~ useruno ]]; then 32 | CURRENT_DOMAIN="useruno.com" 33 | else 34 | CURRENT_DOMAIN="serv00.net" 35 | fi 36 | WORKDIR="${HOME}/domains/${USERNAME}.${CURRENT_DOMAIN}/logs" 37 | FILE_PATH="${HOME}/domains/${USERNAME}.${CURRENT_DOMAIN}/public_html" 38 | rm -rf "$WORKDIR" "$FILE_PATH" && mkdir -p "$WORKDIR" "$FILE_PATH" && chmod 777 "$WORKDIR" "$FILE_PATH" >/dev/null 2>&1 39 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1 40 | command -v curl &>/dev/null && COMMAND="curl -so" || command -v wget &>/dev/null && COMMAND="wget -qO" || { red "Error: neither curl nor wget found, please install one of them." >&2; exit 1; } 41 | 42 | check_port () { 43 | clear 44 | purple "正在安装中,请稍等..." 45 | port_list=$(devil port list) 46 | tcp_ports=$(echo "$port_list" | grep -c "tcp") 47 | udp_ports=$(echo "$port_list" | grep -c "udp") 48 | 49 | if [[ $tcp_ports -ne 1 || $udp_ports -ne 2 ]]; then 50 | red "端口规则不符合要求,正在调整..." 51 | 52 | if [[ $tcp_ports -gt 1 ]]; then 53 | tcp_to_delete=$((tcp_ports - 1)) 54 | echo "$port_list" | awk '/tcp/ {print $1, $2}' | head -n $tcp_to_delete | while read port type; do 55 | devil port del $type $port 56 | green "已删除TCP端口: $port" 57 | done 58 | fi 59 | 60 | if [[ $udp_ports -gt 2 ]]; then 61 | udp_to_delete=$((udp_ports - 2)) 62 | echo "$port_list" | awk '/udp/ {print $1, $2}' | head -n $udp_to_delete | while read port type; do 63 | devil port del $type $port 64 | green "已删除UDP端口: $port" 65 | done 66 | fi 67 | 68 | if [[ $tcp_ports -lt 1 ]]; then 69 | while true; do 70 | tcp_port=$(shuf -i 10000-65535 -n 1) 71 | result=$(devil port add tcp $tcp_port 2>&1) 72 | if [[ $result == *"Ok"* ]]; then 73 | green "已添加TCP端口: $tcp_port" 74 | break 75 | else 76 | yellow "端口 $tcp_port 不可用,尝试其他端口..." 77 | fi 78 | done 79 | fi 80 | 81 | if [[ $udp_ports -lt 2 ]]; then 82 | udp_ports_to_add=$((2 - udp_ports)) 83 | udp_ports_added=0 84 | while [[ $udp_ports_added -lt $udp_ports_to_add ]]; do 85 | udp_port=$(shuf -i 10000-65535 -n 1) 86 | result=$(devil port add udp $udp_port 2>&1) 87 | if [[ $result == *"Ok"* ]]; then 88 | green "已添加UDP端口: $udp_port" 89 | if [[ $udp_ports_added -eq 0 ]]; then 90 | udp_port1=$udp_port 91 | else 92 | udp_port2=$udp_port 93 | fi 94 | udp_ports_added=$((udp_ports_added + 1)) 95 | else 96 | yellow "端口 $udp_port 不可用,尝试其他端口..." 97 | fi 98 | done 99 | fi 100 | yellow "\n端口已调整完成,将断开ssh连接,请重新连接shh重新执行脚本" 101 | quick_command 102 | devil binexec on >/dev/null 2>&1 103 | kill -9 $(ps -o ppid= -p $$) >/dev/null 2>&1 104 | else 105 | tcp_port=$(echo "$port_list" | awk '/tcp/ {print $1}') 106 | udp_ports=$(echo "$port_list" | awk '/udp/ {print $1}') 107 | udp_port1=$(echo "$udp_ports" | sed -n '1p') 108 | udp_port2=$(echo "$udp_ports" | sed -n '2p') 109 | fi 110 | purple "vmess-argo使用的tcp端口为: $tcp_port" 111 | purple "tuic和hy2使用的udp端口分别为: $udp_port1 和 $udp_port2" 112 | export VMESS_PORT=$tcp_port 113 | export TUIC_PORT=$udp_port1 114 | export HY2_PORT=$udp_port2 115 | } 116 | 117 | check_website() { 118 | FULL_DOMAIN="${USERNAME}.${CURRENT_DOMAIN}" 119 | CURRENT_SITE=$(devil www list | awk -v domain="$FULL_DOMAIN" '$1 == domain && $2 == "php"') 120 | if [ -n "$CURRENT_SITE" ]; then 121 | green "已存在 ${FULL_DOMAIN} 的PHP站点,无需修改" 122 | else 123 | EXIST_SITE=$(devil www list | awk -v domain="$FULL_DOMAIN" '$1 == domain') 124 | 125 | if [ -n "$EXIST_SITE" ]; then 126 | devil www del "$FULL_DOMAIN" >/dev/null 2>&1 127 | devil www add "$FULL_DOMAIN" php "$HOME/domains/$FULL_DOMAIN" >/dev/null 2>&1 128 | green "已删除旧的站点并创建新的php站点" 129 | else 130 | devil www add "$FULL_DOMAIN" php "$HOME/domains/$FULL_DOMAIN" >/dev/null 2>&1 131 | green "已创建php站点 ${FULL_DOMAIN}" 132 | fi 133 | fi 134 | 135 | index_url="https://github.com/eooce/Sing-box/releases/download/00/index.html" 136 | [ -f "${FILE_PATH}/index.html" ] || $COMMAND "${FILE_PATH}/index.html" "$index_url" 137 | } 138 | 139 | argo_configure() { 140 | if [[ -z $ARGO_AUTH || -z $ARGO_DOMAIN ]]; then 141 | green "ARGO_DOMAIN or ARGO_AUTH is empty,use quick tunnel" 142 | return 143 | fi 144 | 145 | if [[ $ARGO_AUTH =~ TunnelSecret ]]; then 146 | echo $ARGO_AUTH > tunnel.json 147 | cat > tunnel.yml << EOF 148 | tunnel: $(cut -d\" -f12 <<< "$ARGO_AUTH") 149 | credentials-file: tunnel.json 150 | protocol: http2 151 | 152 | ingress: 153 | - hostname: $ARGO_DOMAIN 154 | service: http://localhost:$VMESS_PORT 155 | originRequest: 156 | noTLSVerify: true 157 | - service: http_status:404 158 | EOF 159 | else 160 | yellow "当前使用的是token,请在cloudflare后台设置隧道端口为${purple}${VMESS_PORT}${re}" 161 | fi 162 | } 163 | 164 | generate_config() { 165 | 166 | openssl ecparam -genkey -name prime256v1 -out "private.key" 167 | openssl req -new -x509 -days 3650 -key "private.key" -out "cert.pem" -subj "/CN=$USERNAME.${CURRENT_DOMAIN}" 168 | 169 | yellow "获取可用IP中,请稍等..." 170 | available_ip=$(get_ip) 171 | purple "当前选择IP为: $available_ip 如安装完后节点不通可尝试重新安装" 172 | 173 | cat > config.json <> config.json <> config.json < "${WORKDIR}/config.yaml" << EOF 344 | client_secret: ${NEZHA_KEY} 345 | debug: false 346 | disable_auto_update: true 347 | disable_command_execute: false 348 | disable_force_update: true 349 | disable_nat: false 350 | disable_send_query: false 351 | gpu: false 352 | insecure_tls: false 353 | ip_report_period: 1800 354 | report_delay: 1 355 | server: ${NEZHA_SERVER} 356 | skip_connection_count: false 357 | skip_procs_count: false 358 | temperature: false 359 | tls: ${NEZHA_TLS} 360 | use_gitee_to_upgrade: false 361 | use_ipv6_country_code: false 362 | uuid: ${UUID} 363 | EOF 364 | fi 365 | declare -A FILE_MAP 366 | generate_random_name() { 367 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 368 | local name="" 369 | for i in {1..6}; do 370 | name="$name${chars:RANDOM%${#chars}:1}" 371 | done 372 | echo "$name" 373 | } 374 | 375 | download_with_fallback() { 376 | local URL=$1 377 | local NEW_FILENAME=$2 378 | 379 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" & 380 | CURL_PID=$! 381 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 382 | 383 | sleep 1 384 | 385 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 386 | 387 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then 388 | kill $CURL_PID 2>/dev/null 389 | wait $CURL_PID 2>/dev/null 390 | wget -q -O "$NEW_FILENAME" "$URL" 391 | green "Downloading $NEW_FILENAME by wget" 392 | else 393 | wait $CURL_PID 394 | green "Downloading $NEW_FILENAME by curl" 395 | fi 396 | } 397 | 398 | for entry in "${FILE_INFO[@]}"; do 399 | URL=$(echo "$entry" | cut -d ' ' -f 1) 400 | RANDOM_NAME=$(generate_random_name) 401 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME" 402 | 403 | download_with_fallback "$URL" "$NEW_FILENAME" 404 | 405 | chmod +x "$NEW_FILENAME" 406 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME" 407 | done 408 | wait 409 | 410 | if [ -e "$(basename ${FILE_MAP[web]})" ]; then 411 | nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & 412 | sleep 2 413 | 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"; } 414 | fi 415 | 416 | if [ -e "$(basename ${FILE_MAP[bot]})" ]; then 417 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then 418 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}" 419 | elif [[ $ARGO_AUTH =~ TunnelSecret ]]; then 420 | args="tunnel --edge-ip-version auto --config tunnel.yml run" 421 | else 422 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$VMESS_PORT" 423 | fi 424 | nohup ./"$(basename ${FILE_MAP[bot]})" $args >/dev/null 2>&1 & 425 | sleep 2 426 | 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"; } 427 | fi 428 | 429 | if [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_PORT" ] && [ -n "$NEZHA_KEY" ]; then 430 | if [ -e "$(basename ${FILE_MAP[npm]})" ]; then 431 | tlsPorts=("443" "8443" "2096" "2087" "2083" "2053") 432 | [[ "${tlsPorts[*]}" =~ "${NEZHA_PORT}" ]] && NEZHA_TLS="--tls" || NEZHA_TLS="" 433 | export TMPDIR=$(pwd) 434 | nohup ./"$(basename ${FILE_MAP[npm]})" -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} >/dev/null 2>&1 & 435 | sleep 2 436 | 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"; } 437 | fi 438 | elif [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_KEY" ]; then 439 | if [ -e "$(basename ${FILE_MAP[php]})" ]; then 440 | nohup ./"$(basename ${FILE_MAP[php]})" -c "${WORKDIR}/config.yaml" >/dev/null 2>&1 & 441 | sleep 2 442 | pgrep -x "$(basename ${FILE_MAP[php]})" > /dev/null && green "$(basename ${FILE_MAP[php]}) is running" || { red "$(basename ${FILE_MAP[php]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[php]})" && nohup ./"$(basename ${FILE_MAP[php]})" -s -c "${WORKDIR}/config.yaml" >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[php]}) restarted"; } 443 | fi 444 | else 445 | purple "NEZHA variable is empty, skipping running" 446 | fi 447 | 448 | for key in "${!FILE_MAP[@]}"; do 449 | if [ -e "$(basename ${FILE_MAP[$key]})" ]; then 450 | rm -rf "$(basename ${FILE_MAP[$key]})" >/dev/null 2>&1 451 | fi 452 | done 453 | 454 | } 455 | 456 | get_argodomain() { 457 | if [[ -n $ARGO_AUTH ]]; then 458 | echo "$ARGO_DOMAIN" 459 | else 460 | local retry=0 461 | local max_retries=6 462 | local argodomain="" 463 | while [[ $retry -lt $max_retries ]]; do 464 | ((retry++)) 465 | argodomain=$(grep -oE 'https://[[:alnum:]+\.-]+\.trycloudflare\.com' boot.log | sed 's@https://@@') 466 | if [[ -n $argodomain ]]; then 467 | break 468 | fi 469 | sleep 1 470 | done 471 | echo "$argodomain" 472 | fi 473 | } 474 | 475 | get_ip() { 476 | IP_LIST=($(devil vhost list | awk '/^[0-9]+/ {print $1}')) 477 | API_URL="https://status.eooce.com/api" 478 | IP="" 479 | THIRD_IP=${IP_LIST[2]} 480 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${THIRD_IP}") 481 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then 482 | IP=$THIRD_IP 483 | else 484 | FIRST_IP=${IP_LIST[0]} 485 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${FIRST_IP}") 486 | 487 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then 488 | IP=$FIRST_IP 489 | else 490 | IP=${IP_LIST[1]} 491 | fi 492 | fi 493 | echo "$IP" 494 | } 495 | 496 | generate_sub_link () { 497 | echo "" 498 | rm -rf ${FILE_PATH}/.htaccess 499 | base64 -w0 ${FILE_PATH}/list.txt > ${FILE_PATH}/v2.log 500 | PHP_URL="https://00.ssss.nyc.mn/sub.php" 501 | QR_URL="https://00.ssss.nyc.mn/qrencode" 502 | $COMMAND "${FILE_PATH}/${SUB_TOKEN}.php" "$PHP_URL" 503 | $COMMAND "${WORKDIR}/qrencode" "$QR_URL" && chmod +x "${WORKDIR}/qrencode" 504 | V2rayN_LINK="https://${USERNAME}.${CURRENT_DOMAIN}/v2.log" 505 | AUTO_LINK="https://${USERNAME}.${CURRENT_DOMAIN}/${SUB_TOKEN}" 506 | curl -sS "https://sublink.eooce.com/clash?config=${V2rayN_LINK}" -o ${FILE_PATH}/clash.yaml 507 | curl -sS "https://sublink.eooce.com/singbox?config=${V2rayN_LINK}" -o ${FILE_PATH}/singbox.yaml 508 | "${WORKDIR}/qrencode" -m 2 -t UTF8 "${AUTO_LINK}" 509 | purple "\n自适应节点订阅链接: ${AUTO_LINK}\n" 510 | green "二维码和节点订阅链接适用于 V2rayN/Nekoray/ShadowRocket/Clash/Mihomo/Sing-box/karing/Loon/sterisand 等\n\n" 511 | cat > ${FILE_PATH}/.htaccess << EOF 512 | RewriteEngine On 513 | DirectoryIndex index.html 514 | RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(\?|$) 515 | RewriteRule ^$ /index.html [L] 516 | 517 | Order Allow,Deny 518 | Allow from all 519 | 520 | 521 | Order Allow,Deny 522 | Deny from all 523 | 524 | RewriteRule ^${SUB_TOKEN}$ ${SUB_TOKEN}.php [L] 525 | EOF 526 | } 527 | 528 | get_links(){ 529 | argodomain=$(get_argodomain) 530 | echo -e "\e[1;32mArgoDomain:\e[1;35m${argodomain}\e[0m\n" 531 | ISP=$(curl -s --max-time 2 https://speed.cloudflare.com/meta | awk -F\" '{print $26}' | sed -e 's/ /_/g' || echo "0") 532 | get_name() { if [ "$HOSTNAME" = "s1.ct8.pl" ]; then SERVER="CT8"; else SERVER=$(echo "$HOSTNAME" | cut -d '.' -f 1); fi; echo "$SERVER"; } 533 | NAME="$ISP-$(get_name)" 534 | 535 | yellow "注意:v2ray或其他软件的跳过证书验证需设置为true,否则hy2或tuic节点可能不通\n" 536 | cat > ${FILE_PATH}/list.txt < /dev/null 2>&1 561 | devil www add keep.${USERNAME}.${CURRENT_DOMAIN} nodejs /usr/local/bin/node18 > /dev/null 2>&1 562 | keep_path="$HOME/domains/keep.${USERNAME}.${CURRENT_DOMAIN}/public_nodejs" 563 | [ -d "$keep_path" ] || mkdir -p "$keep_path" 564 | app_file_url="https://00.ssss.nyc.mn/sbx4.js" 565 | $COMMAND "${keep_path}/app.js" "$app_file_url" 566 | 567 | cat > ${keep_path}/.env < /dev/null 2>&1 582 | ln -fs /usr/local/bin/npm18 ~/bin/npm > /dev/null 2>&1 583 | mkdir -p ~/.npm-global 584 | npm config set prefix '~/.npm-global' 585 | echo 'export PATH=~/.npm-global/bin:~/bin:$PATH' >> $HOME/.bash_profile && source $HOME/.bash_profile 586 | rm -rf $HOME/.npmrc > /dev/null 2>&1 587 | cd ${keep_path} && npm install dotenv axios --silent > /dev/null 2>&1 588 | rm $HOME/domains/keep.${USERNAME}.${CURRENT_DOMAIN}/public_nodejs/public/index.html > /dev/null 2>&1 589 | # devil www options keep.${USERNAME}.${CURRENT_DOMAIN} sslonly on > /dev/null 2>&1 590 | devil www restart keep.${USERNAME}.${CURRENT_DOMAIN} > /dev/null 2>&1 591 | if curl -skL "http://keep.${USERNAME}.${CURRENT_DOMAIN}/${USERNAME}" | grep -q "running"; then 592 | green "\n全自动保活服务安装成功\n" 593 | green "所有服务都运行正常,全自动保活任务添加成功\n\n" 594 | purple "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/stop 结束进程\n" 595 | purple "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/list 全部进程列表\n" 596 | yellow "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/${USERNAME} 调起保活程序 备用保活路径: /run /go /start\n" 597 | purple "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/status 查看进程状态\n\n" 598 | purple "如果需要TG通知,在${yellow}https://t.me/laowang_serv00_bot${re}${purple}获取CHAT_ID,并带CHAT_ID环境变量运行${re}\n\n" 599 | quick_command 600 | else 601 | red "\n全自动保活服务安装失败,存在未运行的进程\n访问 ${yellow}http://keep.${USERNAME}.${CURRENT_DOMAIN}/status ${red}检查,建议执行以下命令后重装: \n\ndevil www del ${USERNAME}.${CURRENT_DOMAIN}\ndevil www del keep.${USERNAME}.${CURRENT_DOMAIN}\nrm -rf $HOME/domains/*\nshopt -s extglob dotglob\nrm -rf $HOME/!(domains|mail|repo|backups)\n\n${re}" 602 | fi 603 | } 604 | 605 | quick_command() { 606 | COMMAND="00" 607 | SCRIPT_PATH="$HOME/bin/$COMMAND" 608 | mkdir -p "$HOME/bin" 609 | echo "#!/bin/bash" > "$SCRIPT_PATH" 610 | echo "bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sb_serv00.sh)" >> "$SCRIPT_PATH" 611 | chmod +x "$SCRIPT_PATH" 612 | if [[ ":$PATH:" != *":$HOME/bin:"* ]]; then 613 | echo "export PATH=\"\$HOME/bin:\$PATH\"" >> "$HOME/.bashrc" 2>/dev/null 614 | source "$HOME/.bashrc" 615 | fi 616 | green "快捷指令00创建成功,下次运行输入00快速启动\n" 617 | } 618 | 619 | install_singbox() { 620 | clear 621 | cd $WORKDIR 622 | check_port 623 | check_website 624 | argo_configure 625 | generate_config 626 | download_singbox 627 | get_links 628 | } 629 | install_singbox 630 | -------------------------------------------------------------------------------- /sb_00.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 | HOSTNAME=$(hostname) 15 | USERNAME=$(whoami | tr '[:upper:]' '[:lower:]') 16 | export UUID=${UUID:-$(uuidgen -r)} 17 | export NEZHA_SERVER=${NEZHA_SERVER:-''} 18 | export NEZHA_PORT=${NEZHA_PORT:-''} 19 | export NEZHA_KEY=${NEZHA_KEY:-''} 20 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''} 21 | export ARGO_AUTH=${ARGO_AUTH:-''} 22 | export CFIP=${CFIP:-'www.visa.com.sg'} 23 | export CFPORT=${CFPORT:-'443'} 24 | export SUB_TOKEN=${SUB_TOKEN:-${UUID:0:8}} 25 | 26 | if [[ "$HOSTNAME" =~ ct8 ]]; then 27 | CURRENT_DOMAIN="ct8.pl" 28 | elif [[ "$HOSTNAME" =~ useruno ]]; then 29 | CURRENT_DOMAIN="useruno.com" 30 | else 31 | CURRENT_DOMAIN="serv00.net" 32 | fi 33 | WORKDIR="${HOME}/domains/${USERNAME}.${CURRENT_DOMAIN}/logs" 34 | FILE_PATH="${HOME}/domains/${USERNAME}.${CURRENT_DOMAIN}/public_html" 35 | rm -rf "$WORKDIR" && mkdir -p "$WORKDIR" "$FILE_PATH" && chmod 777 "$WORKDIR" "$FILE_PATH" >/dev/null 2>&1 36 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1 37 | command -v curl &>/dev/null && COMMAND="curl -so" || command -v wget &>/dev/null && COMMAND="wget -qO" || { red "Error: neither curl nor wget found, please install one of them." >&2; exit 1; } 38 | 39 | check_port () { 40 | port_list=$(devil port list) 41 | tcp_ports=$(echo "$port_list" | grep -c "tcp") 42 | udp_ports=$(echo "$port_list" | grep -c "udp") 43 | 44 | if [[ $tcp_ports -ne 1 || $udp_ports -ne 2 ]]; then 45 | red "端口规则不符合要求,正在调整..." 46 | 47 | if [[ $tcp_ports -gt 1 ]]; then 48 | tcp_to_delete=$((tcp_ports - 1)) 49 | echo "$port_list" | awk '/tcp/ {print $1, $2}' | head -n $tcp_to_delete | while read port type; do 50 | devil port del $type $port 51 | green "已删除TCP端口: $port" 52 | done 53 | fi 54 | 55 | if [[ $udp_ports -gt 2 ]]; then 56 | udp_to_delete=$((udp_ports - 2)) 57 | echo "$port_list" | awk '/udp/ {print $1, $2}' | head -n $udp_to_delete | while read port type; do 58 | devil port del $type $port 59 | green "已删除UDP端口: $port" 60 | done 61 | fi 62 | 63 | if [[ $tcp_ports -lt 1 ]]; then 64 | while true; do 65 | tcp_port=$(shuf -i 10000-65535 -n 1) 66 | result=$(devil port add tcp $tcp_port 2>&1) 67 | if [[ $result == *"Ok"* ]]; then 68 | green "已添加TCP端口: $tcp_port" 69 | break 70 | else 71 | yellow "端口 $tcp_port 不可用,尝试其他端口..." 72 | fi 73 | done 74 | fi 75 | 76 | if [[ $udp_ports -lt 2 ]]; then 77 | udp_ports_to_add=$((2 - udp_ports)) 78 | udp_ports_added=0 79 | while [[ $udp_ports_added -lt $udp_ports_to_add ]]; do 80 | udp_port=$(shuf -i 10000-65535 -n 1) 81 | result=$(devil port add udp $udp_port 2>&1) 82 | if [[ $result == *"Ok"* ]]; then 83 | green "已添加UDP端口: $udp_port" 84 | if [[ $udp_ports_added -eq 0 ]]; then 85 | udp_port1=$udp_port 86 | else 87 | udp_port2=$udp_port 88 | fi 89 | udp_ports_added=$((udp_ports_added + 1)) 90 | else 91 | yellow "端口 $udp_port 不可用,尝试其他端口..." 92 | fi 93 | done 94 | fi 95 | green "端口已调整完成,将断开ssh连接,请重新连接shh重新执行脚本" 96 | devil binexec on >/dev/null 2>&1 97 | kill -9 $(ps -o ppid= -p $$) >/dev/null 2>&1 98 | else 99 | tcp_port=$(echo "$port_list" | awk '/tcp/ {print $1}') 100 | udp_ports=$(echo "$port_list" | awk '/udp/ {print $1}') 101 | udp_port1=$(echo "$udp_ports" | sed -n '1p') 102 | udp_port2=$(echo "$udp_ports" | sed -n '2p') 103 | fi 104 | 105 | export VMESS_PORT=$tcp_port 106 | export TUIC_PORT=$udp_port1 107 | export HY2_PORT=$udp_port2 108 | purple "vmess-argo使用的tcp端口: $tcp_port" 109 | purple "tuic和hy2分别使用的UDP端口: $udp_port1 和 $udp_port2" 110 | } 111 | 112 | check_website() { 113 | FULL_DOMAIN="${USERNAME}.${CURRENT_DOMAIN}" 114 | CURRENT_SITE=$(devil www list | awk -v domain="$FULL_DOMAIN" '$1 == domain && $2 == "php"') 115 | if [ -n "$CURRENT_SITE" ]; then 116 | green "已存在 ${FULL_DOMAIN} 的PHP站点,无需修改" 117 | else 118 | EXIST_SITE=$(devil www list | awk -v domain="$FULL_DOMAIN" '$1 == domain') 119 | 120 | if [ -n "$EXIST_SITE" ]; then 121 | devil www del "$FULL_DOMAIN" >/dev/null 2>&1 122 | devil www add "$FULL_DOMAIN" php "$HOME/domains/$FULL_DOMAIN" >/dev/null 2>&1 123 | green "已删除旧的站点并创建新的php站点" 124 | else 125 | devil www add "$FULL_DOMAIN" php "$HOME/domains/$FULL_DOMAIN" >/dev/null 2>&1 126 | green "已创建php站点 ${FULL_DOMAIN}" 127 | fi 128 | fi 129 | 130 | index_url="https://github.com/eooce/Sing-box/releases/download/00/index.html" 131 | [ -f "${FILE_PATH}/index.html" ] || $COMMAND "${FILE_PATH}/index.html" "$index_url" 132 | } 133 | 134 | argo_configure() { 135 | clear 136 | purple "正在安装中,请稍等..." 137 | if [[ -z $ARGO_AUTH || -z $ARGO_DOMAIN ]]; then 138 | green "ARGO_DOMAIN or ARGO_AUTH is empty,use quick tunnel" 139 | return 140 | fi 141 | 142 | if [[ $ARGO_AUTH =~ TunnelSecret ]]; then 143 | echo $ARGO_AUTH > tunnel.json 144 | cat > tunnel.yml << EOF 145 | tunnel: $(cut -d\" -f12 <<< "$ARGO_AUTH") 146 | credentials-file: tunnel.json 147 | protocol: http2 148 | 149 | ingress: 150 | - hostname: $ARGO_DOMAIN 151 | service: http://localhost:$VMESS_PORT 152 | originRequest: 153 | noTLSVerify: true 154 | - service: http_status:404 155 | EOF 156 | else 157 | green "ARGO_AUTH mismatch TunnelSecret,use token connect to tunnel" 158 | fi 159 | } 160 | 161 | generate_config() { 162 | 163 | openssl ecparam -genkey -name prime256v1 -out "private.key" 164 | openssl req -new -x509 -days 3650 -key "private.key" -out "cert.pem" -subj "/CN=$USERNAME.${CURRENT_DOMAIN}" 165 | 166 | yellow "获取可用IP中,请稍等..." 167 | available_ip=$(get_ip) 168 | purple "当前选择IP为:$available_ip 如安装完后节点不通可尝试重新安装" 169 | 170 | cat > config.json <> config.json <> config.json < "${WORKDIR}/config.yaml" << EOF 341 | client_secret: ${NEZHA_KEY} 342 | debug: false 343 | disable_auto_update: true 344 | disable_command_execute: false 345 | disable_force_update: true 346 | disable_nat: false 347 | disable_send_query: false 348 | gpu: false 349 | insecure_tls: false 350 | ip_report_period: 1800 351 | report_delay: 1 352 | server: ${NEZHA_SERVER} 353 | skip_connection_count: false 354 | skip_procs_count: false 355 | temperature: false 356 | tls: ${NEZHA_TLS} 357 | use_gitee_to_upgrade: false 358 | use_ipv6_country_code: false 359 | uuid: ${UUID} 360 | EOF 361 | fi 362 | declare -A FILE_MAP 363 | generate_random_name() { 364 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 365 | local name="" 366 | for i in {1..6}; do 367 | name="$name${chars:RANDOM%${#chars}:1}" 368 | done 369 | echo "$name" 370 | } 371 | 372 | download_with_fallback() { 373 | local URL=$1 374 | local NEW_FILENAME=$2 375 | 376 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" & 377 | CURL_PID=$! 378 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 379 | 380 | sleep 1 381 | 382 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 383 | 384 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then 385 | kill $CURL_PID 2>/dev/null 386 | wait $CURL_PID 2>/dev/null 387 | wget -q -O "$NEW_FILENAME" "$URL" 388 | green "Downloading $NEW_FILENAME by wget" 389 | else 390 | wait $CURL_PID 391 | green "Downloading $NEW_FILENAME by curl" 392 | fi 393 | } 394 | 395 | for entry in "${FILE_INFO[@]}"; do 396 | URL=$(echo "$entry" | cut -d ' ' -f 1) 397 | RANDOM_NAME=$(generate_random_name) 398 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME" 399 | 400 | download_with_fallback "$URL" "$NEW_FILENAME" 401 | 402 | chmod +x "$NEW_FILENAME" 403 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME" 404 | done 405 | wait 406 | 407 | if [ -e "$(basename ${FILE_MAP[web]})" ]; then 408 | nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & 409 | sleep 2 410 | 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"; } 411 | fi 412 | 413 | if [ -e "$(basename ${FILE_MAP[bot]})" ]; then 414 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then 415 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}" 416 | elif [[ $ARGO_AUTH =~ TunnelSecret ]]; then 417 | args="tunnel --edge-ip-version auto --config tunnel.yml run" 418 | else 419 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$VMESS_PORT" 420 | fi 421 | nohup ./"$(basename ${FILE_MAP[bot]})" $args >/dev/null 2>&1 & 422 | sleep 2 423 | 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"; } 424 | fi 425 | 426 | if [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_PORT" ] && [ -n "$NEZHA_KEY" ]; then 427 | if [ -e "$(basename ${FILE_MAP[npm]})" ]; then 428 | tlsPorts=("443" "8443" "2096" "2087" "2083" "2053") 429 | [[ "${tlsPorts[*]}" =~ "${NEZHA_PORT}" ]] && NEZHA_TLS="--tls" || NEZHA_TLS="" 430 | export TMPDIR=$(pwd) 431 | nohup ./"$(basename ${FILE_MAP[npm]})" -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} >/dev/null 2>&1 & 432 | sleep 2 433 | 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"; } 434 | fi 435 | elif [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_KEY" ]; then 436 | if [ -e "$(basename ${FILE_MAP[php]})" ]; then 437 | nohup ./"$(basename ${FILE_MAP[php]})" -c "${WORKDIR}/config.yaml" >/dev/null 2>&1 & 438 | sleep 2 439 | pgrep -x "$(basename ${FILE_MAP[php]})" > /dev/null && green "$(basename ${FILE_MAP[php]}) is running" || { red "$(basename ${FILE_MAP[php]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[php]})" && nohup ./"$(basename ${FILE_MAP[php]})" -s -c "${WORKDIR}/config.yaml" >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[php]}) restarted"; } 440 | fi 441 | else 442 | purple "NEZHA variable is empty, skipping running" 443 | fi 444 | 445 | for key in "${!FILE_MAP[@]}"; do 446 | if [ -e "$(basename ${FILE_MAP[$key]})" ]; then 447 | rm -rf "$(basename ${FILE_MAP[$key]})" >/dev/null 2>&1 448 | fi 449 | done 450 | 451 | } 452 | 453 | get_argodomain() { 454 | if [[ -n $ARGO_AUTH ]]; then 455 | echo "$ARGO_DOMAIN" 456 | else 457 | local retry=0 458 | local max_retries=6 459 | local argodomain="" 460 | while [[ $retry -lt $max_retries ]]; do 461 | ((retry++)) 462 | argodomain=$(grep -oE 'https://[[:alnum:]+\.-]+\.trycloudflare\.com' boot.log | sed 's@https://@@') 463 | if [[ -n $argodomain ]]; then 464 | break 465 | fi 466 | sleep 1 467 | done 468 | echo "$argodomain" 469 | fi 470 | } 471 | 472 | get_ip() { 473 | IP_LIST=($(devil vhost list | awk '/^[0-9]+/ {print $1}')) 474 | API_URL="https://status.eooce.com/api" 475 | IP="" 476 | THIRD_IP=${IP_LIST[2]} 477 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${THIRD_IP}") 478 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then 479 | IP=$THIRD_IP 480 | else 481 | FIRST_IP=${IP_LIST[0]} 482 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${FIRST_IP}") 483 | 484 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then 485 | IP=$FIRST_IP 486 | else 487 | IP=${IP_LIST[1]} 488 | fi 489 | fi 490 | echo "$IP" 491 | } 492 | 493 | generate_sub_link () { 494 | echo "" 495 | rm -rf ${FILE_PATH}/.htaccess 496 | base64 -w0 ${FILE_PATH}/list.txt > ${FILE_PATH}/v2.log 497 | PHP_URL="https://00.ssss.nyc.mn/sub.php" 498 | QR_URL="https://00.ssss.nyc.mn/qrencode" 499 | $COMMAND "${FILE_PATH}/${SUB_TOKEN}.php" "$PHP_URL" 500 | $COMMAND "${WORKDIR}/qrencode" "$QR_URL" && chmod +x "${WORKDIR}/qrencode" 501 | V2rayN_LINK="https://${USERNAME}.${CURRENT_DOMAIN}/v2.log" 502 | AUTO_LINK="https://${USERNAME}.${CURRENT_DOMAIN}/${SUB_TOKEN}" 503 | curl -sS "https://sublink.eooce.com/clash?config=${V2rayN_LINK}" -o ${FILE_PATH}/clash.yaml 504 | curl -sS "https://sublink.eooce.com/singbox?config=${V2rayN_LINK}" -o ${FILE_PATH}/singbox.yaml 505 | "${WORKDIR}/qrencode" -m 2 -t UTF8 "${AUTO_LINK}" 506 | purple "\n自适应节点订阅链接: ${AUTO_LINK}\n" 507 | green "二维码和节点订阅链接适用于 V2rayN/Nekoray/ShadowRocket/Clash/Mihomo/Sing-box/karing/Loon/sterisand 等\n\n" 508 | cat > ${FILE_PATH}/.htaccess << EOF 509 | RewriteEngine On 510 | DirectoryIndex index.html 511 | RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(\?|$) 512 | RewriteRule ^$ /index.html [L] 513 | 514 | Order Allow,Deny 515 | Allow from all 516 | 517 | 518 | Order Allow,Deny 519 | Deny from all 520 | 521 | RewriteRule ^${SUB_TOKEN}$ ${SUB_TOKEN}.php [L] 522 | EOF 523 | } 524 | 525 | get_links(){ 526 | argodomain=$(get_argodomain) 527 | echo -e "\e[1;32mArgoDomain:\e[1;35m${argodomain}\e[0m\n" 528 | ISP=$(curl -s --max-time 2 https://speed.cloudflare.com/meta | awk -F\" '{print $26}' | sed -e 's/ /_/g' || echo "0") 529 | get_name() { if [ "$HOSTNAME" = "s1.ct8.pl" ]; then SERVER="CT8"; else SERVER=$(echo "$HOSTNAME" | cut -d '.' -f 1); fi; echo "$SERVER"; } 530 | NAME="$ISP-$(get_name)" 531 | 532 | yellow "注意:v2ray或其他软件的跳过证书验证需设置为true,否则hy2或tuic节点可能不通\n" 533 | cat > ${FILE_PATH}/list.txt </dev/null 2>&1 37 | command -v curl &>/dev/null && COMMAND="curl -so" || command -v wget &>/dev/null && COMMAND="wget -qO" || { red "Error: neither curl nor wget found, please install one of them." >&2; exit 1; } 38 | 39 | check_port () { 40 | port_list=$(devil port list) 41 | tcp_ports=$(echo "$port_list" | grep -c "tcp") 42 | udp_ports=$(echo "$port_list" | grep -c "udp") 43 | 44 | if [[ $tcp_ports -ne 1 || $udp_ports -ne 2 ]]; then 45 | red "端口规则不符合要求,正在调整..." 46 | 47 | if [[ $tcp_ports -gt 1 ]]; then 48 | tcp_to_delete=$((tcp_ports - 1)) 49 | echo "$port_list" | awk '/tcp/ {print $1, $2}' | head -n $tcp_to_delete | while read port type; do 50 | devil port del $type $port >/dev/null 2>&1 51 | green "已删除TCP端口: $port" 52 | done 53 | fi 54 | 55 | if [[ $udp_ports -gt 2 ]]; then 56 | udp_to_delete=$((udp_ports - 2)) 57 | echo "$port_list" | awk '/udp/ {print $1, $2}' | head -n $udp_to_delete | while read port type; do 58 | devil port del $type $port >/dev/null 2>&1 59 | green "已删除UDP端口: $port" 60 | done 61 | fi 62 | 63 | if [[ $tcp_ports -lt 1 ]]; then 64 | while true; do 65 | tcp_port=$(shuf -i 10000-65535 -n 1) 66 | result=$(devil port add tcp $tcp_port 2>&1) 67 | if [[ $result == *"Ok"* ]]; then 68 | green "已添加TCP端口: $tcp_port" 69 | break 70 | else 71 | yellow "端口 $tcp_port 不可用,尝试其他端口..." 72 | fi 73 | done 74 | fi 75 | 76 | if [[ $udp_ports -lt 2 ]]; then 77 | udp_ports_to_add=$((2 - udp_ports)) 78 | udp_ports_added=0 79 | while [[ $udp_ports_added -lt $udp_ports_to_add ]]; do 80 | udp_port=$(shuf -i 10000-65535 -n 1) 81 | result=$(devil port add udp $udp_port 2>&1) 82 | if [[ $result == *"Ok"* ]]; then 83 | green "已添加UDP端口: $udp_port" 84 | if [[ $udp_ports_added -eq 0 ]]; then 85 | udp_port1=$udp_port 86 | else 87 | udp_port2=$udp_port 88 | fi 89 | udp_ports_added=$((udp_ports_added + 1)) 90 | else 91 | yellow "端口 $udp_port 不可用,尝试其他端口..." 92 | fi 93 | done 94 | fi 95 | green "端口已调整完成,将断开ssh连接,请重新连接shh重新执行脚本" 96 | quick_command 97 | devil binexec on >/dev/null 2>&1 98 | kill -9 $(ps -o ppid= -p $$) >/dev/null 2>&1 99 | else 100 | tcp_port=$(echo "$port_list" | awk '/tcp/ {print $1}') 101 | udp_ports=$(echo "$port_list" | awk '/udp/ {print $1}') 102 | udp_port1=$(echo "$udp_ports" | sed -n '1p') 103 | udp_port2=$(echo "$udp_ports" | sed -n '2p') 104 | fi 105 | purple "vmess-argo使用的tcp端口为: $tcp_port" 106 | purple "tuic和hy2使用的udp端口分别为: $udp_port1 和 $udp_port2" 107 | export VMESS_PORT=$tcp_port 108 | export TUIC_PORT=$udp_port1 109 | export HY2_PORT=$udp_port2 110 | } 111 | 112 | changge_ports() { 113 | reading "将删除全部端口然后随机开放1个tcp端口和2个udp端口,确定继续吗?(直接回车即确认更换)【y/n】: " choice 114 | 115 | if [[ -z "$choice" || "$choice" == "y" || "$choice" == "Y" ]]; then 116 | devil port list | grep -E "^\s*[0-9]+" | while read -r line; do 117 | port=$(echo "$line" | awk '{print $1}') 118 | proto=$(echo "$line" | awk '{print $2}') 119 | 120 | if [[ "$proto" != "tcp" && "$proto" != "udp" ]]; then 121 | continue 122 | fi 123 | 124 | if ! [[ "$port" =~ ^[0-9]+$ ]]; then 125 | continue 126 | fi 127 | 128 | if devil port del "${proto}" "${port}" > /dev/null 2>&1; then 129 | green "Port ${port}/${proto} has been removed successfully" 130 | else 131 | red "Failed to remove port ${port}/${proto}" 132 | fi 133 | done 134 | check_port 135 | else 136 | menu 137 | fi 138 | } 139 | 140 | check_website() { 141 | FULL_DOMAIN="${USERNAME}.${CURRENT_DOMAIN}" 142 | CURRENT_SITE=$(devil www list | awk -v domain="$FULL_DOMAIN" '$1 == domain && $2 == "php"') 143 | if [ -n "$CURRENT_SITE" ]; then 144 | green "已存在 ${FULL_DOMAIN} 的PHP站点,无需修改" 145 | else 146 | EXIST_SITE=$(devil www list | awk -v domain="$FULL_DOMAIN" '$1 == domain') 147 | 148 | if [ -n "$EXIST_SITE" ]; then 149 | devil www del "$FULL_DOMAIN" >/dev/null 2>&1 150 | devil www add "$FULL_DOMAIN" php "$HOME/domains/$FULL_DOMAIN" >/dev/null 2>&1 151 | green "已删除旧的站点并添加新的php站点" 152 | else 153 | devil www add "$FULL_DOMAIN" php "$HOME/domains/$FULL_DOMAIN" >/dev/null 2>&1 154 | green "已创建新PHP站点 ${FULL_DOMAIN}" 155 | fi 156 | fi 157 | 158 | index_url="https://github.com/eooce/Sing-box/releases/download/00/index.html" 159 | [ -f "${FILE_PATH}/index.html" ] || $COMMAND "${FILE_PATH}/index.html" "$index_url" 160 | } 161 | 162 | read_variables() { 163 | if [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_KEY" ]; then 164 | green "使用自定义变量哪吒运行哪吒探针" 165 | return 166 | else 167 | reading "是否需要安装哪吒探针?(直接回车则不安装)【y/n】: " nz_choice 168 | [[ -z $nz_choice ]] && return 169 | [[ "$nz_choice" != "y" && "$nz_choice" != "Y" ]] && return 170 | reading "\n请输入哪吒探针域名或ip\nv1哪吒形式:nezha.abc.com:8008,v0哪吒形式:nezha.abc.com :" NEZHA_SERVER 171 | green "你的哪吒域名为: $NEZHA_SERVER" 172 | if [[ "$NEZHA_SERVER" != *":"* ]]; then 173 | reading "请输入哪吒v0探针端口(直接回车将设置为5555):" NEZHA_PORT 174 | [[ -z $NEZHA_PORT ]] && NEZHA_PORT="5555" 175 | green "你的哪吒端口为: $NEZHA_PORT" 176 | else 177 | NEZHA_PORT="" 178 | fi 179 | reading "请输入v0的agent密钥或v1的NZ_CLIENT_SECRET:" NEZHA_KEY 180 | green "你的哪吒密钥为: $NEZHA_PORT" 181 | 182 | reading "是否需要Telegram通知?(直接回车则不启用)【y/n】: " tg_notification 183 | if [[ "$tg_notification" == "y" || "$tg_notification" == "Y" ]]; then 184 | 185 | reading "请输入Telegram chat ID (tg上@laowang_serv00_bot获取): " tg_chat_id 186 | [[ -z $tg_chat_id ]] && { red "Telegram chat ID不能为空"; return; } 187 | green "你设置的Telegram chat_id为: ${tg_chat_id}" 188 | 189 | reading "请输入Telegram Bot Token (直接回车使用老王的bot通知或填写自己的): " tg_token 190 | [[ -z $tg_token ]] && tg_token="" 191 | green "你设置的Telegram bot token为: ${tg_token}" 192 | fi 193 | fi 194 | } 195 | 196 | install_singbox() { 197 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1 198 | echo -e "${yellow}本脚本同时四协议共存${purple}(vmess-ws,vmess-ws-tls(argo),hysteria2,tuic)${re}" 199 | reading "\n确定继续安装吗?(直接回车即确认安装)【y/n】: " choice 200 | case "${choice:-y}" in 201 | [Yy]|"") 202 | clear 203 | cd $WORKDIR 204 | check_port 205 | check_website 206 | read_variables 207 | argo_configure 208 | generate_config 209 | download_singbox 210 | get_links 211 | ;; 212 | [Nn]) exit 0 ;; 213 | *) red "无效的选择,请输入y或n" && menu ;; 214 | esac 215 | } 216 | 217 | 218 | uninstall_singbox() { 219 | reading "\n确定要卸载吗?【y/n】: " choice 220 | case "$choice" in 221 | [Yy]) 222 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1 223 | rm -rf $WORKDIR && find ${FILE_PATH} -mindepth 1 ! -name 'index.html' -exec rm -rf {} + 224 | devil www del keep.${USERNAME}.${CURRENT_DOMAIN} 2>/dev/null || true 225 | rm -rf ${HOME}/domains/${USERNAME}.${CURRENT_DOMAIN}/public_nodejs 2 >/dev/null || true 226 | rm -rf "${HOME}/bin/00" >/dev/null 2>&1 227 | [ -d "${HOME}/bin" ] && [ -z "$(ls -A "${HOME}/bin")" ] && rmdir "${HOME}/bin" 228 | sed -i '/export PATH="\$HOME\/bin:\$PATH"/d' "${HOME}/.bashrc" >/dev/null 2>&1 229 | source "${HOME}/.bashrc" 230 | clear 231 | green "Sing-box四合一已完全卸载" 232 | ;; 233 | [Nn]) exit 0 ;; 234 | *) red "无效的选择,请输入y或n" && menu ;; 235 | esac 236 | } 237 | 238 | reset_system() { 239 | reading "\n确定重置系统吗吗?【y/n】: " choice 240 | case "$choice" in 241 | [Yy]) yellow "\n初始化系统中,请稍后...\n" 242 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1 243 | find "${HOME}" -mindepth 1 ! -name "domains" ! -name "mail" ! -name "repo" ! -name "backups" -exec rm -rf {} + > /dev/null 2>&1 244 | devil www list | awk 'NF>=2 && $1 ~ /\./ {print $1}' | while read -r domain; do devil www del "$domain"; done 245 | rm -rf $HOME/domains/* > /dev/null 2>&1 246 | green "\n初始化系统完成!\n" 247 | ;; 248 | *) menu ;; 249 | esac 250 | } 251 | 252 | argo_configure() { 253 | if [[ -z $ARGO_AUTH || -z $ARGO_DOMAIN ]]; then 254 | reading "是否需要使用固定argo隧道?(直接回车将使用临时隧道)【y/n】: " argo_choice 255 | [[ -z $argo_choice ]] && return 256 | [[ "$argo_choice" != "y" && "$argo_choice" != "Y" && "$argo_choice" != "n" && "$argo_choice" != "N" ]] && { red "无效的选择,请输入y或n"; return; } 257 | if [[ "$argo_choice" == "y" || "$argo_choice" == "Y" ]]; then 258 | reading "请输入argo固定隧道域名: " ARGO_DOMAIN 259 | green "你的argo固定隧道域名为: $ARGO_DOMAIN" 260 | reading "请输入argo固定隧道密钥(Json或Token): " ARGO_AUTH 261 | green "你的argo固定隧道密钥为: $ARGO_AUTH" 262 | else 263 | green "ARGO隧道变量未设置,将使用临时隧道" 264 | return 265 | fi 266 | fi 267 | 268 | if [[ $ARGO_AUTH =~ TunnelSecret ]]; then 269 | echo $ARGO_AUTH > tunnel.json 270 | cat > tunnel.yml << EOF 271 | tunnel: $(cut -d\" -f12 <<< "$ARGO_AUTH") 272 | credentials-file: tunnel.json 273 | protocol: http2 274 | 275 | ingress: 276 | - hostname: $ARGO_DOMAIN 277 | service: http://localhost:$VMESS_PORT 278 | originRequest: 279 | noTLSVerify: true 280 | - service: http_status:404 281 | EOF 282 | else 283 | yellow "\n当前使用的是token,请在cloudflare后台设置隧道端口为${purple}${VMESS_PORT}${re}" 284 | fi 285 | } 286 | 287 | generate_config() { 288 | 289 | openssl ecparam -genkey -name prime256v1 -out "private.key" 290 | openssl req -new -x509 -days 3650 -key "private.key" -out "cert.pem" -subj "/CN=$USERNAME.${CURRENT_DOMAIN}" 291 | 292 | yellow "获取可用IP中,请稍等..." 293 | available_ip=$(get_ip) 294 | purple "当前选择IP为:$available_ip 如安装完后节点不通可尝试重新安装" 295 | 296 | cat > config.json <> config.json <> config.json < "${WORKDIR}/config.yaml" << EOF 466 | client_secret: ${NEZHA_KEY} 467 | debug: false 468 | disable_auto_update: true 469 | disable_command_execute: false 470 | disable_force_update: true 471 | disable_nat: false 472 | disable_send_query: false 473 | gpu: false 474 | insecure_tls: false 475 | ip_report_period: 1800 476 | report_delay: 1 477 | server: ${NEZHA_SERVER} 478 | skip_connection_count: false 479 | skip_procs_count: false 480 | temperature: false 481 | tls: ${NEZHA_TLS} 482 | use_gitee_to_upgrade: false 483 | use_ipv6_country_code: false 484 | uuid: ${UUID} 485 | EOF 486 | fi 487 | declare -A FILE_MAP 488 | generate_random_name() { 489 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 490 | local name="" 491 | for i in {1..6}; do 492 | name="$name${chars:RANDOM%${#chars}:1}" 493 | done 494 | echo "$name" 495 | } 496 | 497 | download_with_fallback() { 498 | local URL=$1 499 | local NEW_FILENAME=$2 500 | 501 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" & 502 | CURL_PID=$! 503 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 504 | 505 | sleep 1 506 | 507 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0) 508 | 509 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then 510 | kill $CURL_PID 2>/dev/null 511 | wait $CURL_PID 2>/dev/null 512 | wget -q -O "$NEW_FILENAME" "$URL" 513 | green "Downloading $NEW_FILENAME by wget" 514 | else 515 | wait $CURL_PID 516 | green "Downloading $NEW_FILENAME by curl" 517 | fi 518 | } 519 | 520 | for entry in "${FILE_INFO[@]}"; do 521 | URL=$(echo "$entry" | cut -d ' ' -f 1) 522 | RANDOM_NAME=$(generate_random_name) 523 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME" 524 | 525 | download_with_fallback "$URL" "$NEW_FILENAME" 526 | 527 | chmod +x "$NEW_FILENAME" 528 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME" 529 | done 530 | wait 531 | 532 | if [ -e "$(basename ${FILE_MAP[web]})" ]; then 533 | nohup ./"$(basename ${FILE_MAP[web]})" run -c config.json >/dev/null 2>&1 & 534 | sleep 2 535 | 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"; } 536 | fi 537 | 538 | if [ -e "$(basename ${FILE_MAP[bot]})" ]; then 539 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then 540 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}" 541 | elif [[ $ARGO_AUTH =~ TunnelSecret ]]; then 542 | args="tunnel --edge-ip-version auto --config tunnel.yml run" 543 | else 544 | args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$VMESS_PORT" 545 | fi 546 | nohup ./"$(basename ${FILE_MAP[bot]})" $args >/dev/null 2>&1 & 547 | sleep 2 548 | 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"; } 549 | fi 550 | 551 | if [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_PORT" ] && [ -n "$NEZHA_KEY" ]; then 552 | if [ -e "$(basename ${FILE_MAP[npm]})" ]; then 553 | tlsPorts=("443" "8443" "2096" "2087" "2083" "2053") 554 | [[ "${tlsPorts[*]}" =~ "${NEZHA_PORT}" ]] && NEZHA_TLS="--tls" || NEZHA_TLS="" 555 | export TMPDIR=$(pwd) 556 | nohup ./"$(basename ${FILE_MAP[npm]})" -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} >/dev/null 2>&1 & 557 | sleep 2 558 | 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"; } 559 | fi 560 | elif [ -n "$NEZHA_SERVER" ] && [ -n "$NEZHA_KEY" ]; then 561 | if [ -e "$(basename ${FILE_MAP[php]})" ]; then 562 | nohup ./"$(basename ${FILE_MAP[php]})" -c "${WORKDIR}/config.yaml" >/dev/null 2>&1 & 563 | sleep 2 564 | pgrep -x "$(basename ${FILE_MAP[php]})" > /dev/null && green "$(basename ${FILE_MAP[php]}) is running" || { red "$(basename ${FILE_MAP[php]}) is not running, restarting..."; pkill -x "$(basename ${FILE_MAP[php]})" && nohup ./"$(basename ${FILE_MAP[php]})" -s -c "${WORKDIR}/config.yaml" >/dev/null 2>&1 & sleep 2; purple "$(basename ${FILE_MAP[php]}) restarted"; } 565 | fi 566 | else 567 | purple "NEZHA variable is empty, skipping running" 568 | fi 569 | 570 | for key in "${!FILE_MAP[@]}"; do 571 | if [ -e "$(basename ${FILE_MAP[$key]})" ]; then 572 | rm -rf "$(basename ${FILE_MAP[$key]})" >/dev/null 2>&1 573 | fi 574 | done 575 | 576 | } 577 | 578 | get_argodomain() { 579 | if [[ -n $ARGO_AUTH ]]; then 580 | echo "$ARGO_DOMAIN" 581 | else 582 | local retry=0 583 | local max_retries=6 584 | local argodomain="" 585 | while [[ $retry -lt $max_retries ]]; do 586 | ((retry++)) 587 | argodomain=$(grep -oE 'https://[[:alnum:]+\.-]+\.trycloudflare\.com' boot.log | sed 's@https://@@') 588 | if [[ -n $argodomain ]]; then 589 | break 590 | fi 591 | sleep 1 592 | done 593 | echo "$argodomain" 594 | fi 595 | } 596 | 597 | get_ip() { 598 | IP_LIST=($(devil vhost list | awk '/^[0-9]+/ {print $1}')) 599 | API_URL="https://status.eooce.com/api" 600 | IP="" 601 | THIRD_IP=${IP_LIST[2]} 602 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${THIRD_IP}") 603 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then 604 | IP=$THIRD_IP 605 | else 606 | FIRST_IP=${IP_LIST[0]} 607 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${FIRST_IP}") 608 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then 609 | IP=$FIRST_IP 610 | else 611 | IP=${IP_LIST[1]} 612 | fi 613 | fi 614 | echo "$IP" 615 | } 616 | 617 | generate_sub_link () { 618 | echo "" 619 | rm -rf ${FILE_PATH}/.htaccess 620 | base64 -w0 ${FILE_PATH}/list.txt > ${FILE_PATH}/v2.log 621 | PHP_URL="https://00.ssss.nyc.mn/sub.php" 622 | QR_URL="https://00.ssss.nyc.mn/qrencode" 623 | $COMMAND "${FILE_PATH}/${SUB_TOKEN}.php" "$PHP_URL" 624 | V2rayN_LINK="https://${USERNAME}.${CURRENT_DOMAIN}/v2.log" 625 | AUTO_LINK="https://${USERNAME}.${CURRENT_DOMAIN}/${SUB_TOKEN}" 626 | $COMMAND "${WORKDIR}/qrencode" "$QR_URL" && chmod +x "${WORKDIR}/qrencode" 627 | curl -sS "https://sublink.eooce.com/clash?config=${V2rayN_LINK}" -o ${FILE_PATH}/clash.yaml 628 | curl -sS "https://sublink.eooce.com/singbox?config=${V2rayN_LINK}" -o ${FILE_PATH}/singbox.yaml 629 | "${WORKDIR}/qrencode" -m 2 -t UTF8 "${AUTO_LINK}" 630 | purple "\n自适应节点订阅链接: ${AUTO_LINK}\n" 631 | green "二维码和节点订阅链接适用于 V2rayN/Nekoray/ShadowRocket/Clash/Mihomo/Sing-box/karing/Loon/sterisand 等\n\n" 632 | cat > ${FILE_PATH}/.htaccess << EOF 633 | RewriteEngine On 634 | DirectoryIndex index.html 635 | RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(\?|$) 636 | RewriteRule ^$ /index.html [L] 637 | 638 | Order Allow,Deny 639 | Allow from all 640 | 641 | 642 | Order Allow,Deny 643 | Deny from all 644 | 645 | RewriteRule ^${SUB_TOKEN}$ ${SUB_TOKEN}.php [L] 646 | EOF 647 | } 648 | 649 | install_keepalive () { 650 | purple "正在安装保活服务中,请稍等......" 651 | devil www del keep.${USERNAME}.${CURRENT_DOMAIN} > /dev/null 2>&1 652 | devil www add keep.${USERNAME}.${CURRENT_DOMAIN} nodejs /usr/local/bin/node18 > /dev/null 2>&1 653 | keep_path="$HOME/domains/keep.${USERNAME}.${CURRENT_DOMAIN}/public_nodejs" 654 | [ -d "$keep_path" ] || mkdir -p "$keep_path" 655 | app_file_url="https://00.ssss.nyc.mn/sbx4.js" 656 | $COMMAND "${keep_path}/app.js" "$app_file_url" 657 | 658 | cat > ${keep_path}/.env < /dev/null 2>&1 673 | ln -fs /usr/local/bin/node18 ~/bin/node > /dev/null 2>&1 674 | ln -fs /usr/local/bin/npm18 ~/bin/npm > /dev/null 2>&1 675 | mkdir -p ~/.npm-global 676 | npm config set prefix '~/.npm-global' 677 | echo 'export PATH=~/.npm-global/bin:~/bin:$PATH' >> $HOME/.bash_profile && source $HOME/.bash_profile 678 | rm -rf $HOME/.npmrc > /dev/null 2>&1 679 | cd ${keep_path} && npm install dotenv axios --silent > /dev/null 2>&1 680 | rm $HOME/domains/keep.${USERNAME}.${CURRENT_DOMAIN}/public_nodejs/public/index.html > /dev/null 2>&1 681 | # devil www options keep.${USERNAME}.${CURRENT_DOMAIN} sslonly on > /dev/null 2>&1 682 | devil www restart keep.${USERNAME}.${CURRENT_DOMAIN}> /dev/null 2>&1 683 | if curl -skL "http://keep.${USERNAME}.${CURRENT_DOMAIN}/${USERNAME}" | grep -q "running"; then 684 | green "\n全自动保活服务安装成功\n" 685 | green "所有服务都运行正常,全自动保活任务添加成功\n\n" 686 | purple "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/stop 结束进程\n" 687 | purple "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/list 全部进程列表\n" 688 | yellow "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/${USERNAME} 调起保活程序 备用保活路径: /run /go /start\n" 689 | purple "访问 http://keep.${USERNAME}.${CURRENT_DOMAIN}/status 查看进程状态\n\n" 690 | purple "如果需要TG通知,在${yellow}https://t.me/laowang_serv00_bot${re}${purple}获取CHAT_ID,并带CHAT_ID环境变量运行${re}\n\n" 691 | quick_command 692 | else 693 | red "\n全自动保活服务安装失败,存在未运行的进程,请执行以下命令后重装: \n\ndevil www del ${USERNAME}.${CURRENT_DOMAIN}\ndevil www del keep.${USERNAME}.${CURRENT_DOMAIN}\nrm -rf $HOME/domains/*\n\n" 694 | fi 695 | } 696 | 697 | get_links(){ 698 | argodomain=$(get_argodomain) 699 | echo -e "\e[1;32mArgoDomain: \e[1;35m${argodomain}\e[0m\n" 700 | ISP=$(curl -s --max-time 2 https://speed.cloudflare.com/meta | awk -F\" '{print $26}' | sed -e 's/ /_/g' || echo "0") 701 | get_name() { if [ "$HOSTNAME" = "s1.ct8.pl" ]; then SERVER="CT8"; else SERVER=$(echo "$HOSTNAME" | cut -d '.' -f 1); fi; echo "$SERVER"; } 702 | NAME="$ISP-$(get_name)" 703 | yellow "注意:v2ray或其他软件的跳过证书验证需设置为true,否则hy2或tuic节点可能不通\n" 704 | cat > ${FILE_PATH}/list.txt < "$SCRIPT_PATH" 728 | echo "bash <(curl -Ls https://raw.githubusercontent.com/eooce/sing-box/main/sb_serv00.sh)" >> "$SCRIPT_PATH" 729 | chmod +x "$SCRIPT_PATH" 730 | if [[ ":$PATH:" != *":$HOME/bin:"* ]]; then 731 | echo 'export PATH="$HOME/bin:$PATH"' >> "$HOME/.bashrc" 2>/dev/null 732 | source "$HOME/.bashrc" 733 | fi 734 | green "快捷指令00创建成功,下次运行输入00快速进入菜单\n" 735 | } 736 | 737 | 738 | get_url_info() { 739 | if devil www list 2>&1 | grep -q "keep.${USERNAME}.${CURRENT_DOMAIN}"; then 740 | purple "\n-------------------保活相关链接------------------\n\n" 741 | purple "http://keep.${USERNAME}.${CURRENT_DOMAIN}/stop 结束进程\n" 742 | purple "http://keep.${USERNAME}.${CURRENT_DOMAIN}/list 全部进程列表\n" 743 | yellow "http://keep.${USERNAME}.${CURRENT_DOMAIN}/${USERNAME} 调起保活程序\n" 744 | purple "http://keep.${USERNAME}.${CURRENT_DOMAIN}/status 查看进程状态\n\n" 745 | else 746 | red "尚未安装自动保活服务\n" && sleep 2 && menu 747 | fi 748 | } 749 | 750 | get_nodes(){ 751 | cat ${FILE_PATH}/list.txt 752 | TOKEN=$(sed -n 's/^SUB_TOKEN=\(.*\)/\1/p' $HOME/domains/keep.${USERNAME}.${CURRENT_DOMAIN}/public_nodejs/.env) 753 | yellow "\n自适应节点订阅链接: https://${USERNAME}.${CURRENT_DOMAIN}/${TOKEN}\n二维码和节点订阅链接适用于V2rayN/Nekoray/ShadowRocket/Clash/Sing-box/karing/Loon/sterisand 等\n" 754 | } 755 | 756 | menu() { 757 | clear 758 | echo "" 759 | purple "=== Serv00|ct8老王sing-box一键四合一安装脚本 ===\n" 760 | echo -e "${green}脚本地址:${re}${yellow}https://github.com/eooce/Sing-box${re}\n" 761 | echo -e "${green}反馈论坛:${re}${yellow}https://bbs.vps8.me${re}\n" 762 | echo -e "${green}TG反馈群组:${re}${yellow}https://t.me/vps888${re}\n" 763 | purple "转载请著名出处,请勿滥用\n" 764 | yellow "快速启动命令00\n" 765 | green "1. 安装四合一" 766 | echo "===============" 767 | red "2. 卸载四合一" 768 | echo "===============" 769 | green "3. 查看节点信息" 770 | echo "===============" 771 | green "4. 查看保活链接" 772 | echo "===============" 773 | yellow "5. 更换节点端口" 774 | echo "===============" 775 | yellow "6. 初始化系统" 776 | echo "===============" 777 | red "0. 退出脚本" 778 | echo "===========" 779 | reading "请输入选择(0-6): " choice 780 | echo "" 781 | case "${choice}" in 782 | 1) install_singbox ;; 783 | 2) uninstall_singbox ;; 784 | 3) get_nodes ;; 785 | 4) get_url_info ;; 786 | 5) changge_ports ;; 787 | 6) reset_system ;; 788 | 0) exit 0 ;; 789 | *) red "无效的选项,请输入 0 到 6" ;; 790 | esac 791 | } 792 | menu 793 | --------------------------------------------------------------------------------